ThinkPad T480 is my new main laptop which runs FreeBSD

I’ve been using FreeBSD as my primary server OS for quite a long time.
But, for unknown reasons, I have never seriously used it on client workstations.

Maybe it’s partly because I’m a CUI-oriented person who loves doing things on text terminals as much as possible.

Actually, I have been pretty happy with any client OS as long as I could use a decent terminal on it, so that I could SSH into FreeBSD servers where I spent a lot of time doing jobs which didn’t require graphical interface.

However, it’s also true that I have been wishing for a FreeBSD desktop which allows me to do everything from web browsing to text editing on a single machine.

So I started a research on FreeBSD laptops in the midst of this year’s longer-than-usual rainy season. After gathering information on the web, I tried various GUI setup on VMs and then I bought a new laptop, Lenovo ThinkPad T480.

Experimenting for a while on the T480, finally I’ve got a fully working FreeBSD laptop for daily use, just after the rainy season was over!

Because it has proven to be a really great machine for running FreeBSD, I write this article to share something with anyone who looks for a similar experience.

T480 FreeBSD Workstation

Laptop Specs

Generally speaking, I love small machines with low power consumption. But this time, my goal is replacing my main desktop (running Windows) with a new laptop, so I invested on performance much more than usual.

What works and what does not

With FreeBSD 12.0-RELEASE + Xorg + XFCE4, I can get the following stuff working on T480.

I haven’t tested the following items.

Initial Setup

Disable Secure Boot, TPM and Bluetooth

To boot T480 from FreeBSD installation media, I had to enter the BIOS menu and disable Secure Boot and TPM.
It is also required to disable Bluetooth to avoid hangup on system reboot.

To enter the setup menu on startup, press Enter at the Lenovo logo screen. A loud beep can be suppressed by turn Mute button on.

To enter the BIOS setup from the menu, press F1.
Change the following settings and press F10 to save and exit.

It looks like the memstick installer supports UEFI boot so I left “Startup” page’s “UEFI/Legacy Boot” and “CSM Support” untouched (“UEFI Only” and “NO” respectively).

Which Version to Install?

At first, I selected the following FreeBSD versions as candidates.

With experts' advices on Twitter and experiments on actual machine with installation media and RAM disk (Maybe on another post), I chose 12.0-RELEASE to start with. Now it turns out to be the right choice based on the right advices.

OS Installation

There’s almost nothing special about installation. But here’s a few things to note.

Basic Configurations After the First Boot

After the first boot, I logged in and performed the following usual configurations.

Setting up Grahpical Desktop Environment

I’m completely new to the graphical desktop world. So it’s inevitable for me to learn things one by one through a lot of trial and error.

Anyway, I use the following components to build my desktop.

Plus, here is the list of graphical applications for my daily use.

Setup process was as follows.

Personal Notes on Further Setup

Touchpad and TrackPoint


I was able to perform suspend/resume by running acpiconf -s 3 or from the XFCE4’s “Logout” dialog almost out of the box.
But at some point, I realized the following behaviors of the Logout dialog.

After some struggle, those were solved by creating the following polkit rule file (e.g. 85-suspend.rules) in /usr/local/etc/polkit-1/rules.d directory.

NOTE: To use this configuration, your user account have to be in operator group. I did this during installation as mentioned earlier.

// pkg info -D xfce4-session
// xfce4-session-4.12.1_6:
// Always:
// To be able to shutdown or reboot your system, you'll have to add .rules
// files in /usr/local/etc/polkit-1/rules.d directory. Which looks
// like this (replace PUTYOURGROUPHERE by your group):

polkit.addRule(function (action, subject) {
  if (( == "org.freedesktop.consolekit.system.restart" || == "org.freedesktop.consolekit.system.stop")
      && subject.isInGroup("operator")) {
    return polkit.Result.YES;

// For those who have working suspend/resume:

polkit.addRule(function (action, subject) {
  if ( == "org.freedesktop.consolekit.system.suspend"
      && subject.isInGroup("operator")) {
    return polkit.Result.YES;

// Explicitly disallow hibernation because it's not supported by the OS.

polkit.addRule(function (action, subject) {
  if ( == "org.freedesktop.consolekit.system.hibernate") {
    return polkit.Result.NO;

Now suspend/resume seems to work more reliably by command, lid close/open or from Logout dialog!

Screen Brightness

Beep on Logout

EPSON Ink-Jet Printer EP-802A






Maybe in another post.

Failover between Ethernet and WiFi

With the advice on FreeBSD Forum and Twitter, I finally got “lagg failover between Ethernet and Wireless interfaces” working as in the FreeBSD Handbook.

My configuration (in /etc/rc.conf) is as follows.

ifconfig_em0="ether <WiFi MAC Address> up"
ifconfig_wlan0="WPA up"
create_args_wlan0="country JP"
ifconfig_lagg0="up laggproto failover laggport em0 laggport wlan0 DHCP"

As opposed to the handbook’s example, I use the WiFi MAC address on the Ethernet interface. Other than that, it’s essentially the same as the handbook.
(I’ve also tried “Ethernet MAC on WiFi” and it worked)

But at first I ran into a problem here.

When I reboot my system with the above configuration, lagg0 has only Ethernet (em0) as its member port. WiFi interface was not in the lagg0 because it seemed to be created after the lagg was initially configured. By manually running “service netif restart”, the lagg failover begins to work but I wondered how to avoid this manual intervention.

A discussion on the forum quickly solved the problem.

It suggests loading WiFi-related kernel modueles by loader instead of devd.
I achieved this by adding the following lines to /boot/loader.conf and reboot.


This made iwm0 detected much earlier and lagg0 was successfully configured with both em0 and wlan0 as its members on boot.

Then I got another suggestion on Twitter that it’s better to load modules which are not required for boot from rc not loader.

I moved them from /boot/loader.conf to /etc/rc.conf and confirmed that it also worked as expected.

kld_list="/boot/modules/i915kms.ko if_iwm iwm8265fw"

(As I previously mentioned, i915kms.ko is for graphics.)

Burning CDs

I hadn’t burnt CDs for a long time but recently I was asked to create an audio CD. So I plugged in a USB CD-R/RW drive to my laptop and tried it on FreeBSD.

I found my system already had GUI-based Xfburn and Brasero in addition to cdrecord, a good old command-line burner program.

At first I tried GUI-based ones but both said ‘No burner found’. Because I was in a hurry at the time, I used cdrecord (as root) for the first time in 15 years.

  1. Check the CD drive’s device number.

    sudo cdrecord -scanbus
    	1,0,0	100) 'BUFFALO ' 'Optical Drive   ' '2.00' Removable CD-ROM
  2. Burn it.

    sudo cdrecord -v dev=1,0,0 -pad -dao music.wav 

Because running cdrecord with root privilege could burn CDs, it was obvious that device permissions kept the GUI burners run by a normal user from finding the burner.

cd0 had the following owner/mode. As my user account (a normal user) was in operator group, I could read from the device but couldn’t write to it.

crw-r-----  1 root  operator   0x7f Nov  9 10:16 cd0

I adjusted the device permissions with devfs.

  1. Add the following a devfs ruleset in /etc/devfs.rules.
    I added pass and xpt because adding only cd0 didn’t work.

    add path cd0 group operator mode 0660
    add path pass1 group operator mode 0660
    add path xpt0 group operator mode 0660

    Maybe ‘cd0’, ‘pass1’ and ‘xpt0’ could be ‘cd*’, ‘pass*’ and ‘xpt*’.
    But for now I use the formers with the following output.

    camcontrol devlist
    <Samsung SSD 860 EVO 1TB RVT02B6Q>  at scbus0 target 0 lun 0 (ada0,pass0)
    <BUFFALO Optical Drive 2.00>       at scbus1 target 0 lun 0 (pass1,cd0)
    <Generic- SD/MMC 1.00>             at scbus2 target 0 lun 0 (da0,pass2)
  2. Add a line to /etc/rc.conf to use the devfs ruleset.

  3. Reboot the system.

  4. Now I can burn CDs with GUI programs too.

Webcam and Video Conferencing

(Added on 2020-05-24)
It was a pleasant surprise to find that jitsi video conference using Firefox/Chromium just works with the help of cuse.ko and webcamd!

  1. Install webcamd.

    sudo pkg install webcamd
  2. Add a user to the webcamd group.

    sudo pw groupmod webcamd -m genneko
  3. Configure the cuse kernel module to be loaded on boot.

    sudo sysrc kld_list+=cuse
  4. Configure the webcamd to be started on boot.

    sudo sysrc webcamd_enable=YES


    sudo service webcamd enable
  5. Manually load the module and restart devd to start the service, or reboot the entire system.

    sudo kldload cuse
    sudo service devd restart


    sudo shutdown -r now


Revision History