Roland's homepage

My random knot in the Web

FreeBSD 13.1 install on a Lenovo IdeaPad 5

When I originally got this machine, I needed it for $WORK. That is no longer the case, so I wanted to install FreeBSD 13.1 in combination with ZFS to gain experience with the latter.

TL;DR Nice and quiet. Slightly faster than my i7-7700 workstation. Except for wifi, everything works.

In this article, commands that can be run as a normal user are predixed with “>”. All other commands should be run as root.


Lenovo IdeaPad 5 15ALC05 specs:

  • CPU: AMD Ryzen 5 5500U
  • GPU: AMD Radeon RX Vega 7 (built-in, codename “renoir”)
  • RAM: 16 GiB (2 GiB in use by the GPU)
  • SSD: 512 GiB
  • display: 15.6” FHD IPS
  • battery: L19M4PF1 15V/70Wh
  • wifi: Qualcomm Atheros QCA6174
  • bluetooth: Qualcomm Atheros QCA61x4 Bluetooth 4.0 (via usb)


The wifi chip is not supported on FreeBSD 13.1. A driver is being worked on (at10k) but the wifi subsystem needs updating, so it’s a big job. Since tethering to a smartphone or ethernet adaptor works fine this is not a deal-braker for me. I’ve never used bluetooth on a PC, so I didn’t test that either.

This laptop doesn’t have a built-in ethernet port. So I’m using a Sitecom USB-C to ethernet adapter. This is recognized as a ue0 device.

Download and install the software distribution

Since I’m on the amd64 platform, I downloaded FreeBSD-13.1-RELEASE-amd64-dvd1.iso.

Installing it on a new thumbdrive:

dd if=FreeBSD-13.1-RELEASE-amd64-dvd1.iso of=/dev/da1 bs=1m conv=sync
4408+0 records in
4408+0 records out
4622123008 bytes transferred in 172.740381 secs (26757629 bytes/sec)

Note that commands as shown above are to be run as root, unless they are preceded by > which means they are to be run as a normal user.

Wherever you see the username rsmith, you should replace that with the username of the primary user.


It is a good idea to have Chapter 2 of the FreeBSD handbook handy during installation. Below are the settings that I used.

  • Keymap: default
  • Hostname: styx.erewhon.home (yours will be different, of course)
  • Optional components: deselect lib32, select ports and src.
  • System partitioning: Auto (ZFS)
  • ZFS configuration:
    • Set encrypt to YES, then “Proceed with install”. This will encrypt basically all your data including system configuration and passwords.
    • Virtual device type “stripe” (since there is only one built-in drive)
    • Device “nvd0”.
    • Choose a strong ZFS encryption passphrase. Note that without this password the disk is unreadable. So make sure not to lose it. :-)
  • Fill in a root password.
  • No IP4 of IP6 or configuration at this point.
  • Timezone Europe/Netherlands → CEST
  • Set time and date if needed.
  • Services: disable sshd.
  • System hardening: enable all except “read_msgbuf”.
  • New user: “rsmith”, groups “video network”. Every user that wants to run X needs to be in the video group.
  • Shell: tcsh
  • Homedir: /home/rsmith
  • Homedir permissions: 700
  • Password auth: yes
  • No empty password, no random password.
  • Fill in a user password.
  • Exit installer.

Go into shell to make changes:

pw groupadd usb
pw usermod rsmith -G wheel,video,usb,network

The usb group is used to give users access to USB devices. The network group is used to give normal users the rights to run e.g. ifconfig and dhclient via doas.

At this point we can reboot into the new system.


Since this laptop does not have built-in ethernet, I’ve downloaded all the packages I wanted plus their dependencies from the latest quarterly distribution (using two self-made scripts), and put them on a USB thumbdrive in a directory packages. This is mounted on styx, and the packages are installed.

Initially, only a couple of packages are installed:

mount_msdosfs -m 644 -M 755 /dev/da0s1 /media
cd /media/packages
setenv SIGNATURE_TYPE none
pkg add pkg-1.18.4.pkg
pkg add git-2.37.3.pkg


If you are using a later quarterly package set, the version numbers of packages can differ.

Now we place /etc and /usr/local/etc under git control to track changes:

cd /etc
echo '*.db' >>.gitignore
echo 'zfs/zpool.cache' >>.gitignore
git init -b main .
git add .
git commit -m "Initial commit after setup."
cd /usr/local/etc
git init -b main .
git add .
git commit -m "Initial commit after setup."

Now to install the rest of the packages:

cd /media/packages
pkg add *.pkg

This will take a while. :-)

Among these packages the following are necessary to get X to work well on this machine (next to xorg-7.7_3.pkg, of course):

  • drm-kmod-20220907_1.pkg (kernel modules and firmware for the GPU)
  • xf86-input-synaptics-1.9.1_9.pkg (touchpad driver)
  • f86-video-amdgpu-22.0.0_1.pkg (video driver)

Unmount and remove the USB stick containing the packages, then commit the changes in the configuration files:

umount /media
cd /etc/
git add .
git commit -m "After packages installation."
cd /usr/locat/etc
git add .
git commit -m "After packages installation."

System configuration

After every change to a configuration file, this is added and then committed in the same way as shown above so it can be turned back if needed.


After testing with kldload amdgpu, it turns out that amdgpu kernel module works as expected. So we add the following to /etc/rc.conf:



Added the following to /etc/sysctl.conf:


This is needed so that non-root users can mount disks.


CPU’s from both Intel and AMD have security issues with symmetric multithreading (“hyperthreading” according to Intel). In my testing it slowed down a CPU intensive multithreaded programs. So in it is better to switch it off. Add to /boot/loader.conf:


Umount and shutdown

Since I want to be able to perform these actions as a member of the wheel group, some modes and permissions need changing.

chmod u+s /sbin/umount
chown root:wheel /sbin/shutdown


Create /etc/devfs.rules with the following contents:

add path 'da*' mode 0660 group usb
add path 'msdosfs/*' mode 0660 group usb
add path 'usb/*' mode 0660 group usb
add path 'ugen*' mode 0660 group usb
add path 'ttyU*' mode 0660 group usb
add path 'cuaU*' mode 0660 group usb

Then add to /etc/rc.conf:


This gives the members of the usb group access to USB devices.


Added to /etc/rc.conf:


So not forget to run the setup for local-unbound:


Configuring network dongle

Network access is handy for transferring files and remote login.

I’ve got a Sitecom USB-C to gigabit LAN adapter. When I plug it in, it is recognized as the ue0 device. (When I plug in my smartphone with tethering enabled, it uses the same device. Obviously, using gigabit ethernet is preferred.)

The network can be started with:

ifconfig ue0 up
dhclient ue0

Remote access

It is very handy to be able to log in remotely, especially in the setting-up phase. To enable that we have to configure and start the secure shell daemon, sshd. Edit /etc/ssh/sshd_config:

  • Change Port to another value XXXX > 1000.
  • Change AddressFamily to inet.
  • Add AllowUsers rsmith
  • Uncomment HostKey for rsa and ed25519.
  • Change X11Forwarding to no.
  • Change Compression to no.

This allows the user rsmith to log in via the network.

To make this work I had to add my public ssh key (~/.ssh/ on the machine I’m calling from) to ~/.ssh/authorized_keys on styx.

The network was started with:

ifconfig ue0 up
dhclient ue0
service sshd onestart

Then I could log in remotely with ssh -p XXXX styx.erewhon.home.

Configuring X

When starting Xorg as rsmith, the default twm window manager comes up with three xterm windows. The modesetting driver works when the amdgpu module is loaded.

Based on the file from another laptop, I created the /usr/local/etc/X11/xorg.conf.d/monitor.conf file shown below, mainly because the screen size was not recognized correctly:

Section "Monitor"
  Identifier  "Monitor0"
  VendorName  "CMN 151e"
  ModelName   "built-in"
  DisplaySize 344 193

Section "Screen"
  Identifier  "Screen0"
  Monitor     "Monitor0"
  SubSection "Display"
    Viewport    0 0
    Depth       24

With this, the screen size is correct.

To get the touchpad to work, I needed the iichid and ig4 modules. To enable this:

kldload iichid
kldload ig4

I also added those to kld_list in /etc/rc.conf:

kld_list="amdgpu.ko iichid.ko ig4.ko amdtemp.ko"

(The module amdtemp is added to be able to see the the processor temperatures.)

Based on the information found in the Linux Arch wiki, I also created this /usr/local/etc/X11/xorg.conf.d/touchpad.conf file:

Section "InputClass"
    Identifier "MSFT0001:00 04F3:3140 TouchPad"
    Driver "synaptics"
    MatchIsTouchpad "on"
      Option "TapButton1" "1"
      Option "TapButton2" "3"
      Option "TapButton3" "2"
      Option "VertEdgeScroll" "on"
      Option "VertTwoFingerScroll" "on"
      Option "HorizEdgeScroll" "on"
      Option "HorizTwoFingerScroll" "on"
      Option "CircularScrolling" "on"
      Option "CircScrollTrigger" "2"
      Option "EmulateTwoFingerMinZ" "40"
      Option "EmulateTwoFingerMinW" "8"
      Option "CoastingSpeed" "0"
      Option "FingerLow" "30"
      Option "FingerHigh" "50"
      Option "MaxTapTime" "125"
      Option "PalmDetect" "on"

The touchpad works, but could probably use some tuning. Not sure yet if the tapping is such a good idea. Next to modifying touchpad.conf and restarting X, one can also use the synclient program in the xf86-input-synaptics-1.9.1_9.pkg package to see and change the settings.

Since I don’t use a desktop environment but just a windowmanager (i3), some settings were added to my ~/.xinitrc:

# Display settings
xrandr --output eDP-1 --gamma 1:1:1 --brightness 1

# Allow local access to x server (for notify-send)
xhost +local:


Out of the box, there is no sound out of the speakers. :-(

The default sound device looks sensible:

> cat /dev/sndstat
Installed devices:
pcm0: <ATI R6xx (HDMI)> (play)
pcm1: <ATI R6xx (HDMI)> (play)
pcm2: <Realtek ALC257 (Analog)> (play/rec) default
pcm3: <Realtek ALC257 (Right Analog Mic)> (rec)
No devices installed from userspace.

The headphones work, though. Looking at the relevant part of sysctl dev.hdaa.1:

dev.hdaa.1.nid33_original: 0x04211010 as=1 seq=0 device=Headphones
conn=Jack ctype=1/8 loc=Right color=Black misc=0
dev.hdaa.1.nid33_config: 0x04211010 as=1 seq=0 device=Headphones
conn=Jack ctype=1/8 loc=Right color=Black misc=0
dev.hdaa.1.nid33: pin: Headphones (Black Jack)
    Widget cap: 0x0040058d PWR UNSOL STEREO
    Association: 0 (0x0001)
        Pin cap: 0x0001001c PDC HP OUT EAPD
    Pin config: 0x04211010 as=1 seq=0 device=Headphones conn=Jack
                ctype=1/8 loc=Right color=Black misc=0
    Pin control: 0x000000c0 HP OUT
          EAPD: 0x00000002 EAPD
    Output amp: 0x80000000 mute=1 step=0 size=0 offset=0 (0/0dB)
    Connections: 2
          + <- nid=2 [audio output] (selected)
          + [DISABLED] <- nid=3 [audio output] [DISABLED]

It seems that audioset 1 (as=1) is connected to the headphones and pcm2.

However, all the speakers are disabled:

> sysctl dev.hdaa.1 | grep '^dev.*pin.*Speaker'
dev.hdaa.1.nid30: pin: Speaker (None) [DISABLED]
dev.hdaa.1.nid27: pin: Speaker (None) [DISABLED]
dev.hdaa.1.nid26: pin: Speaker (None) [DISABLED]
dev.hdaa.1.nid24: pin: Speaker (None) [DISABLED]
dev.hdaa.1.nid20: pin: Speaker (Fixed) [DISABLED]

Let’s look at nid20, because that is the only fixed speaker:

> sysctl dev.hdaa.1.nid20
dev.hdaa.1.nid20: pin: Speaker (Fixed) [DISABLED]
    Widget cap: 0x0040058d PWR UNSOL STEREO
        Pin cap: 0x00010014 PDC OUT EAPD
    Pin config: 0x90170120 as=2 seq=0 device=Speaker conn=Fixed
                ctype=Analog loc=Internal color=Unknown misc=1
    Pin control: 0x00000000
          EAPD: 0x00000002 EAPD
    Output amp: 0x80000000 mute=1 step=0 size=0 offset=0 (0/0dB)
    Connections: 1
          + [DISABLED] <- nid=2 [audio output]

Normally, we want the sound to go to the speakers, unless the headphones are connected. The way to do that is to set the same audioset for both (as=1 in this case), and them set the speakers as sequence 0 (seq=0) and the headphones as sequence 15.

To test this, the following commands are used:

sysctl dev.hdaa.1.nid20_config="as=1 seq=0 misc=0"
sysctl dev.hdaa.1.nid33_config="as=1 seq=15"
sysctl dev.hdaa.1.reconfig=1

This enables both. Note that without misc=0 the speakers did not work.

Normally, this configuration is set in /boot/device.hints, and that is where I put them. The syntax there is slightly different:

hint.hdaa.1.nid20.config="as=1 seq=0 misc=0"
hint.hdaa.1.nid33.config="as=1 seq=15"

See snd_hda(4) for more information.

Scheduler tweaks for desktop use

In /etc/sysctl.conf, I added the following:


This improves interactivity for a desktop/laptop role.

ZFS tweak

By default, ZFS uses a lot of memory for its Adaptive Replacement Cache (“ARC”). On this machine, the ARC grew to about 85% of memory. Since it is adaptive, the cache size will reduce when programs request more memory.

If you want to reduce the amount of memory used by ZFS ARC to e.g. 2 GiB, add the following to /boot/loader.conf:


When I did some test with a CPU and memory intensive program (CalculiX FEA) it performed significantly faster with the reduced ZFS cache. Probably because it isn’t fighting ZFS over cache memory. :-)


Transferring data

At this point I wanted to transfer the data in my $HOME to the laptop. since I have a point-to-point gigabit ethernet connection between my workstation and styx, the fastest way to do that is with netcat (nc).

First we start the “listener” on styx:

cd /home
nc -l 65000 | tar xvf -

Then on the machine I’m coming from:

cd /home
tar cvf - rsmith/ | nc -N styx.erewhon.home 65000

The top speeds (achieved with large files) over a gigabit point-to-point link was ≈122 MB/s. That pretty much saturates the ethernet connection.

Speed test

As a speed test, I ran the multithreaded CalculiX FEA solver on an existing calculation. On a workstation with an i7-7700 running as 3.6 GHz this takes about 27.5 seconds with symmetric multithreading (“SMT”) disabled.

On the Ryzen 5500U running at 2 GHZ, it took 24 seconds with SMT disabled. With SMT enabled it took 25 seconds.

For comments, please send me an e-mail.

Related articles

←  Using a USB headset on FreeBSD Writing speed on FreeBSD 13.1-p2 amd64 with ZFS  →