June 15, 2026 AD
FreeBSD 15 really feels like a breakthrough release.
It’s always been my favorite operating system for servers, but with the arrival of pkgbase, massive improvements to the LinuxKPI drivers, and the launch of the Laptop Support and Usability Project, it’s become my primary desktop, too.
Since my last attempt with FreeBSD 14, a lot has changed:
I’m getting about 6-7 hours of battery life with my ThinkPad X1 Carbon. Other than Bluetooth (which I have not attempted), everything on my device functions well with FreeBSD.
There’s also a new Laptop Compatibility Matrix where you can see what works on your own hardware.
So let’s build a FreeBSD laptop system with KDE!
This guide assumes you’re using Intel graphics with an Intel wireless chipset. I’m sure that other hardware configurations work fine, but I’m sticking with firsthand experience here.
Grab a FreeBSD 15.1 memstick
image
and dd it to a USB stick:
curl -OJ https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/15.1/FreeBSD-15.1-RELEASE-amd64-memstick.img
sudo dd if=FreeBSD-15.1-RELEASE-amd64-memstick.img of=/dev/sdX bs=1M conv=syncThe installation wizard is straightforward. Make sure your system is configured for UEFI
boot, and select ZFS (GPT) for the disk layout.
When prompted for base system installation type, choose Packages to get the new
pkgbase goodness.
You’ll want to enable SSH in the installer. Better to copy paste into an SSH session than to type everything manually into a virtual console!
Once you reboot, login as root using the password you specified during installation.
First, we’ll configure device drivers and make various tweaks to get optimum performance and battery life out of a desktop system.
Many of these steps are not strictly necessary, but they work well for me. Use your own judgment!
First, open up /boot/loader.conf and consider adding the following:
# /boot/loader.conf
# Timeout at the bootloader prompt (seconds).
autoboot_delay="3"
# HaRdEniNg: 99% of users will never need
# destructive dtrace.
security.bsd.allow_destructive_dtrace="0"
# The defaults here are way too conservative
# for desktop stuff like web browsers.
kern.ipc.shmseg="1024"
kern.ipc.shmmni="1024"
kern.maxproc="100000"
# If your system supports Intel Speed Shift
# (check dmesg), then set this to 0. This will
# allow each core to set its own power state.
machdep.hwpstate_pkg_ctrl="0"
# Enable PCI power saving.
hw.pci.do_power_nodriver="3"
# Enable faster soreceive() implementation.
# Don't use this if you run a BIND DNS server.
net.inet.tcp.soreceive_stream="1"
# Increase network interface queue length.
net.isr.defaultqlimit="2048"
net.link.ifqmaxlen="2048"
# For laptops: increase ZFS transaction timeout
# to save on battery life.
vfs.zfs.txg.timeout="10"Enable querying CPU information and temperature:
sysrc -v kld_list+="cpuctl coretemp"The H-TCP congestion control algorithm is designed to perform better over fast, long-distance networks (like the Internet). You might consider using it:
sysrc -v kld_list+="cc_htcp"If you’re using a ThinkPad, you’ll need this module to get all your buttons working:
sysrc -v kld_list+="acpi_ibm"Next, open up /etc/sysctl.conf and consider setting some of the following sysctls.
You can view the description of a sysctl using sysctl -d.
# /etc/sysctl.conf
# ==================
# sEcuRitY HaRdeNinG
# ==================
# These settings are pretty common sense for
# the majority of people:
hw.kbd.keymap_restrict_change=4
kern.coredump=0
kern.elf32.aslr.pie_enable=1
kern.random.fortuna.minpoolsize=128
kern.randompid=1
net.inet.icmp.drop_redirect=1
net.inet.ip.process_options=0
net.inet.ip.random_id=1
net.inet.ip.redirect=0
net.inet.ip.rfc1122_strong_es=1
net.inet.tcp.always_keepalive=0
net.inet.tcp.drop_synfin=1
net.inet.tcp.icmp_may_rst=0
net.inet.tcp.syncookies=0
net.inet6.ip6.redirect=0
security.bsd.unprivileged_read_msgbuf=0
# Some guides will tell you use these.
# More trouble than they're worth, IMO!
#
#kern.elf32.allow_wx=0
#kern.elf64.allow_wx=0
#security.bsd.hardlink_check_gid=1
#security.bsd.hardlink_check_uid=1
#security.bsd.see_other_gids=0
#security.bsd.see_other_uids=0
#security.bsd.unprivileged_proc_debug=0
# ==========================
# Network Performance Tuning
# ==========================
# The default values for many of these sysctls
# are optimized for the TCP latencies of a LAN.
#
# The modifications below should give you
# better TCP performance over connections with
# a larger RTT (like the Internet), at the
# expense of higher memory utilization.
#
# Source: it came to me in a dream
kern.ipc.maxsockbuf=2097152
kern.ipc.soacceptqueue=1024
kern.ipc.somaxconn=1024
net.inet.tcp.abc_l_var=44
net.inet.tcp.cc.abe=1
net.inet.tcp.cc.algorithm=htcp
net.inet.tcp.cc.htcp.adaptive_backoff=1
net.inet.tcp.cc.htcp.rtt_scaling=1
net.inet.tcp.ecn.enable=1
net.inet.tcp.fast_finwait2_recycle=1
net.inet.tcp.fastopen.server_enable=1
net.inet.tcp.finwait2_timeout=5000
net.inet.tcp.initcwnd_segments=44
net.inet.tcp.keepcnt=2
net.inet.tcp.keepidle=62000
net.inet.tcp.keepinit=5000
net.inet.tcp.minmss=536
net.inet.tcp.msl=2500
net.inet.tcp.mssdflt=1448
net.inet.tcp.nolocaltimewait=1
net.inet.tcp.recvbuf_max=2097152
net.inet.tcp.recvspace=65536
net.inet.tcp.sendbuf_inc=65536
net.inet.tcp.sendbuf_max=2097152
net.inet.tcp.sendspace=65536
net.local.stream.recvspace=65536
net.local.stream.sendspace=65536
# =====================
# Desktop Optimizations
# =====================
# Prevent shared memory from being swapped
# to disk.
kern.ipc.shm_use_phys=1
# Increase scheduler preemption threshold for
# a snappier GUI experience.
kern.sched.preempt_thresh=224
# Allow unprivileged users to mount things.
vfs.usermount=1
# ===================
# Laptop Power Saving
# ===================
# Decrease audio responsiveness to save power.
hw.snd.latency=7Poor WiFi support is mostly a thing of the past, thanks to LinuxKPI and the new iwlwifi driver. If you have one of the common Intel cards, chances are it will just work.
First, install the necessary firmware package for your wireless card:
fwget -vTo use the newer iwlwifi driver on an older card, you might need to block the old iwm
driver from loading:
# /boot/loader.conf
devmatch_blocklist="if_iwm"802.11n and 802.11ac are disabled by default. You’ll need another loader.conf tweak to unlock higher speeds:
# /boot/loader.conf
compat.linuxkpi.iwlwifi_11n_disable="0"
compat.linuxkpi.iwlwifi_disable_11ac="0"You might also want to try power saving mode:
# /boot/loader.conf
compat.linuxkpi.iwlwifi_power_save="1"Update rc.conf to create a wlan0 device on boot:
sysrc -v wlans_iwlwifi0="wlan0" \
create_args_wlan="wlanmode sta country US regdomain FCC" \
ifconfig_wlan0="WPA DHCP powersave"With those settings, wpa_supplicant(8)
will manage your WiFi networks. You can either edit
wpa_supplicant.conf(5) by hand, or use the graphical interface provided by networkmgr:
pkg install networkmgr sudoNote that networkmgr requires superuser privileges. You can allow all members of the operator
group to run networkmgr without a password using sudo:
# /usr/local/etc/sudoers.d/networkmgr
%operator ALL=NOPASSWD: /usr/local/bin/networkmgrInstall the latest CPU microcode:
pkg install cpu-microcodeEdit loader.conf to load the microcode on boot:
# /boot/loader.conf
cpu_microcode_load="YES"
cpu_microcode_name="/boot/firmware/intel-ucode.bin"You can save a lot of battery (and heat) by enabling lower CPU C-states:
sysrc -v \
performance_cx_lowest=Cmax \
economy_cx_lowest=CmaxWith modern Intel processors, it is no longer necessary to run powerd(8).
Install the Intel graphics driver and make sure it’s loaded on boot:
pkg install drm-kmod
sysrc -v kld_list+="i915kms"For desktop systems, you’ll need a custom devfs(8) ruleset to allow unprivileged users to control common hardware devices. Create devfs.rules(5) with the following:
# /etc/devfs.rules
[localrules=1000]
add path 'drm/*' mode 0660 group operator
add path 'backlight/*' mode 0660 group operator
add path 'video*' mode 0660 group operator
add path 'usb/*' mode 0660 group operatorAnd set your default ruleset like so:
sysrc -v devfs_system_ruleset=localrulesGive devfs a kick to fix those permissions:
service devfs restartThe Linuxulator allows you to run Linux binaries on FreeBSD:
sysrc -v linux_enable=YESIf you run Linux binaries, you will probably need to mount some Linux filesystems as well:
# /etc/fstab
devfs /compat/linux/dev devfs rw,late 0 0
tmpfs /compat/linux/dev/shm tmpfs rw,late,size=1g,mode=1777 0 0
fdescfs /compat/linux/dev/fd fdescfs rw,late,linrdlnk 0 0
linprocfs /compat/linux/proc linprocfs rw,late 0 0
linsysfs /compat/linux/sys linsysfs rw,late 0 0If you ever want to mount filesystems like exFAT or NTFS, you’ll need fusefs(4):
sysrc -v kld_list+="fusefs"With any luck, your webcam will be supported by webcamd(8) without any fuss:
pkg install \
webcamd \
v4l-utils \
v4l_compat
sysrc -v webcamd_enable=YESIf you want to print on FreeBSD, you’ll need CUPS:
pkg install cups cups-filters
sysrc -v cupsd_enable=YESYou’ll want to give members of the operator group the ability to configure printers:
# /usr/local/etc/upcs/cups-files.conf
SystemGroup operator
AccessLog syslog
ErrorLog syslog
PageLog syslogNow you can start the daemon:
service cupsd startYou can access the CUPS configuration GUI in your browser at localhost:631.
If you’re using a laptop, you’ll want to power down inactive USB devices to save battery life.
Add the following to /etc/rc.local:
# /etc/rc.local
usbconfig | awk -F: '{ print $1 }' | xargs -rtn1 -I% usbconfig -d % power_saveI had to do a bit of work to get the backlight keys working on my ThinkPad.
First, make sure the acpi_ibm(4) kernel module is loaded:
kldload acpi_ibmThen, set the following sysctl to allow devd(8) to handle events for the backlight buttons:
sysctl dev.acpi_ibm.0.handlerevents="0x10 0x11"Make sure you add that to /etc/sysctl.conf.
Now we can receive the button events, but we’ll need a devd rule
to handle them. Create /etc/devd/thinkpad-brightness.conf with the following:
# /etc/devd/thinkpad-brightness.conf
notify 20 {
match "system" "ACPI";
match "subsystem" "IBM";
match "notify" "0x10";
action "/usr/local/libexec/thinkpad-brightness up";
};
notify 20 {
match "system" "ACPI";
match "subsystem" "IBM";
match "notify" "0x11";
action "/usr/local/libexec/thinkpad-brightness down";
};Finally, create the following script at /usr/local/libexec/thinkpad-brightness:
#!/bin/sh
#
# /usr/local/libexec/thinkpad-brightness
cur=$(/usr/bin/backlight -q)
case $1 in
up)
if [ "$cur" -ge 50 ]; then
delta=10
elif [ "$cur" -ge 10 ]; then
delta=5
else
delta=2
fi
/usr/bin/backlight incr "$delta"
;;
down)
if [ "$cur" -le 10 ]; then
delta=2
elif [ "$cur" -le 50 ]; then
delta=5
else
delta=10
fi
/usr/bin/backlight decr "$delta"
;;
esacDon’t forget to make it executable:
chmod 755 /usr/local/libexec/thinkpad-brightnessNow is a good time to reboot and make sure your changes haven’t broken anything!
rebootI try to run a firewall on all of my systems. A basic configuration can block all incoming connections except for SSH.
Create /etc/pf.conf:
# /etc/pf.conf
# Replace this with the names of your network
# interfaces.
egress = "{ em0, wlan0 }"
# Allow inbound ssh.
allowed_tcp_ports = "{ ssh }"
# Allow RTP traffic for voice and video calls.
allowed_udp_ports = "{ 1024:65535 }"
set block-policy return
set skip on lo
scrub in on $egress all fragment reassemble
antispoof quick for $egress
block all
pass out quick on $egress inet
pass in quick on $egress inet proto icmp all icmp-type { echoreq, unreach }
pass in quick on $egress inet proto tcp to port $allowed_tcp_ports
pass in quick on $egress inet proto udp to port $allowed_udp_portsStart the firewall on boot:
sysrc -v pf_enable=YES
service pf startOut of the box, FreeBSD includes a lot of periodic(8) scripts that churn through your hard disk, reach out to the Internet, and send emails. You can check periodic.conf(5) for a full list.
Some of these jobs are useful, but for a typical desktop user, most of them can be safely disabled:
sysrc -v -f /etc/periodic.conf \
daily_backup_aliases_enable=NO \
daily_backup_gpart_enable=NO \
daily_backup_passwd_enable=NO \
daily_clean_disks_verbose=NO \
daily_clean_hoststat_enable=NO \
daily_clean_preserve_verbose=NO \
daily_clean_rwho_verbose=NO \
daily_clean_tmps_verbose=NO \
daily_show_info=NO \
daily_show_success=NO \
daily_status_disks_enable=NO \
daily_status_include_submit_mailq=NO \
daily_status_mail_rejects_enable=NO \
daily_status_mail_rejects_enable=NO \
daily_status_mailq_enable=NO \
daily_status_network_enable=NO \
daily_status_security_enable=NO \
daily_status_uptime_enable=NO \
daily_status_world_kernel=NO \
daily_status_zfs_zpool_list_enable=NO \
daily_submit_queuerun=NO \
monthly_accounting_enable=NO \
monthly_show_info=NO \
monthly_show_success=NO \
monthly_status_security_enable=NO \
security_show_info=NO \
security_show_success=NO \
security_status_chkmounts_enable=NO \
security_status_chksetuid_enable=NO \
security_status_chkuid0_enable=NO \
security_status_ipf6denied_enable=NO \
security_status_ipfdenied_enable=NO \
security_status_ipfwdenied_enable=NO \
security_status_ipfwlimit_enable=NO \
security_status_kernelmsg_enable=NO \
security_status_logincheck_enable=NO \
security_status_loginfail_enable=NO \
security_status_neggrpperm_enable=NO \
security_status_passwdless_enable=NO \
security_status_pfdenied_enable=NO \
security_status_tcpwrap_enable=NO \
weekly_locate_enable=NO \
weekly_show_info=NO \
weekly_show_success=NO \
weekly_status_security_enable=NO \
weekly_whatis_enable=NOYou’ll need a local user account. Be sure to add yourself to the operator
and wheel groups:
pw useradd \
-n gsarto \
-c 'Giuseppe M. Sarto' \
-s /bin/sh \
-M 700 \
-d /home/gsarto \
-G operator,wheelYou’ll probably want to install sudo:
pkg install sudoUpdate the sudoers file to empower the wheel group:
# /usr/local/etc/sudoers
%wheel ALL=(ALL:ALL) ALLEnvironment variables for login shells are set in login.conf(5). Modify this file to set your preferred locale:
--- /etc/login.conf
+++ /etc/login.conf
@@ -23,7 +23,9 @@
:umtxp=unlimited:\
:priority=0:\
:ignoretime@:\
- :umask=022:
+ :umask=022:\
+ :charset=UTF-8:\
+ :lang=en_US.UTF-8:You’ll need to rebuild the login database to apply this change:
cap_mkdb /etc/login.confFor non-login shells, you can set the same variables in a profile.d script:
# /etc/profile.d/locale.sh
export LANG=en_US.UTF-8
export CHARSET=UTF-8You’ll need ntpd(8) to keep your system clock up to date.
Edit ntp.conf with your preferred NTP servers:
# /etc/ntp.conf
tos minclock 3 maxclock 6
pool 0.freebsd.pool.ntp.org iburst
pool 1.freebsd.pool.ntp.org iburst
pool 2.freebsd.pool.ntp.org iburst
restrict default limited kod nomodify notrap noquery nopeer
restrict source limited kod nomodify notrap noquery
restrict 127.0.0.1
restrict ::1
leapfile "/var/db/ntpd.leap-seconds.list"In case you didn’t do this during the installation, set your timezone:
ln -sfhv /usr/share/zoneinfo/America/New_York /etc/localtimeThe ssh in FreeBSD’s base system is heavily patched. I prefer to use the vanilla
openssh-portable from ports:
pkg install openssh-portableIf you run sshd, the configuration file now lives in /usr/local/etc/ssh:
# /usr/local/etc/ssh/sshd_config
PermitRootLogin prohibit-password
UsePAM yes
UseDNS no
Subsystem sftp /usr/local/libexec/sftp-serverYou’ll need to swap your sshd in /etc/rc.conf to run the new version:
sysrc -v sshd_enable=NO openssh_enable=YES
service sshd stop
service openssh startThe ssh command will continue using /usr/bin/ssh from the base system unless you
update your $PATH.
You can edit login.conf to make this change for all users:
--- /etc/login.conf
+++ /etc/login.conf
@@ -4,7 +4,7 @@
:welcome=/var/run/motd:\
:setenv=BLOCKSIZE=K:\
:mail=/var/mail/$:\
- :path=/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin ~/bin:\
+ :path=/sbin /bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin ~/bin:\
:nologin=/var/run/nologin:\
:cputime=unlimited:\
:datasize=unlimited:\As before, rebuild the login database to apply this change:
cap_mkdb /etc/login.confThe termcap(5) database in FreeBSD is simpler than you might find on Linux. In particular, I noticed that bright colors would not render on XTerm-like terminals.
You can fix this by installing terminfo-db:
pkg install terminfo-dbFreeBSD trusts only a subset of the standard certificate authorities out of the box. You’ll want to make sure Mozilla’s full CA bundle is installed:
pkg install ca_root_nssD-Bus is required for KDE and pretty much everything else these days:
sysrc -v dbus_enable=YES
service dbus startTypically you’d install a graphical display manager like SDDM to launch your desktop sessions.
Unfortunately, at the time of this writing, none of those display managers are able to reliably start a Wayland session on FreeBSD.
SDDM can almost do it, but there is a bug that causes various key combinations to exit your session.
The current wisdom is to use the console-based Ly display manager to launch Wayland sessions:
pkg install lyLy doesn’t run as a daemon. Instead, you’ll need to update /etc/ttys to launch it on a virtual console after system boot:
--- /etc/ttys 2026-06-15 09:11:43.272063000 -0400
+++ /etc/ttys 2026-06-15 09:12:23.756283000 -0400
@@ -2,7 +2,7 @@
#
ttyv0 "/usr/libexec/getty Pc" xterm onifexists secure
# Virtual terminals
-ttyv1 "/usr/libexec/getty Pc" xterm onifexists secure
+ttyv1 "/usr/libexec/getty Ly" xterm onifexists secure
ttyv2 "/usr/libexec/getty Pc" xterm onifexists secure
ttyv3 "/usr/libexec/getty Pc" xterm onifexists secure
ttyv4 "/usr/libexec/getty Pc" xterm onifexists secureNow we just need to update gettytab(5) with an entry for Ly:
--- /etcgettytab 2026-06-15 09:31:56.348452000 -0400
+++ /etc/gettytab 2026-06-11 20:37:58.000000000 -0400
@@ -234,3 +234,8 @@
:np:nc:sp#115200:
3wire.230400|230400-3wire:\
:np:nc:sp#230400:
+
+# Ly login manager
+Ly:\
+ :lo=/usr/local/bin/ly_wrapper:\
+ :al=root:You should see the Ly login prompt after your next reboot. Or, just give init
a little kick:
kill -HUP 1Ly has many options you can configure in config.ini. For example:
# /usr/local/etc/ly/config.ini
# Force the use of wayland sessions:
xinitrc = null
xsessions = null
shell = false
waylandsessions = /usr/local/share/wayland-sessionsMake sure to install all the standard fonts so websites render properly:
pkg install \
cantarell-fonts \
droid-fonts-ttf \
inconsolata-ttf \
noto-basic \
noto-emoji \
roboto-fonts-ttf \
ubuntu-font \
webfontsGrab a cup of coffee while you install KDE and other must-have desktop stuff:
pkg install \
en-aspell \
en-hunspell \
freedesktop-sound-theme \
kde \
kdegraphics \
kdemultimedia \
kdeutils \
phonon-mpv \
pipewire \
plasma6-breeze-gtk \
pulseaudio \
wireplumberYou’ll also want your favorite desktop apps. For example:
pkg install \
chromium \
digikam \
dino \
elisa \
emacs-wayland \
firefox \
fooyin \
git \
gnupg \
haruna \
kid3-kf6 \
konversation \
libreoffice \
linux-widevine-cdm \
mpv \
neofetch \
password-store \
ripgrep \
rsync \
signal-desktop \
stow \
thunderbird \
tmux \
wineSome desktop functionality now depends on pipewire.
For example, taskbar previews don’t seem to work unless pipewire is running.
You can start it automatically with an autostart file:
# /usr/local/etc/xdg/autostart/pipewire.desktop
[Desktop Entry]
Comment=Pipewire wayland thing
Exec=/usr/local/bin/pipewire -v
Name=pipewire
StartupNotify=false
Terminal=false
Type=Application
X-KDE-AutostartScript=true
X-KDE-SubstituteUID=falseIf you want kwallet to store your SSH key passphrases, then you’ll need
to export some environment variables:
# /etc/profile.d/kde.sh
if [ "$XDG_CURRENT_DESKTOP" = KDE ]; then
export SSH_ASKPASS_REQUIRE=prefer
export SSH_ASKPASS=/usr/local/bin/ksshaskpass
fiWith the right packages installed, most Intel GPUs support hardware video acceleration. This will give you much smoother video playback and better battery life!
pkg install \
libva-intel-media-driver \
libva-utils \
libvdpau-va-gl \
vdpauinfoSome applications may need additional configuration to take advantage of the hardware offload.
Chrome used to require a scary incantation of command line flags to get hardware video decoding working on FreeBSD.
But at the time of this writing, it just works.
The following mpv.conf gives me HD video playback with minimal CPU usage:
# /usr/local/etc/mpv/mpv.conf
hwdec=vaapi-copy
vo=gpu-next
vd-lavc-dr=yes
audio-channels=stereoThis section describes the issues I encountered while getting everything working. Your mileage may vary, depending on your hardware!
Once KDE is running, the desktop environment listens for ACPI lid events and should handle suspend and resume for you out of the box.
Unfortunately, this functionality has a very annoying bug on my ThinkPad, where after I would open the lid, the laptop would immediately suspend itself again!
As a workaround, I disabled the lid switch behavior in KDE’s power settings and configured
suspend on lid close natively using devd. This has the added benefit of being able to
close the laptop lid when KDE isn’t running.
First, write a small script to handle locking the screen and suspending the device:
#!/bin/sh
#
# /usr/local/libexec/kde-suspend
# This is a big ugly shell pipeline that does
# two things:
#
# 1. Find anyone currently logged into KDE.
# 2. Lock their screen.
/usr/local/bin/qdbus6 --literal --system \
org.freedesktop.ConsoleKit \
/org/freedesktop/ConsoleKit/Manager \
org.freedesktop.ConsoleKit.Manager.GetSessions \
| /usr/bin/sed 's/^.*\(Session[0-9]*\).*$/\1/' \
| /usr/bin/xargs -rtn1 -I% \
/usr/local/bin/qdbus6 --system \
org.freedesktop.ConsoleKit \
/org/freedesktop/ConsoleKit/% \
org.freedesktop.ConsoleKit.Session.Lock
# Sleep for a moment to make sure the lock
# screen comes up.
/bin/sleep 0.5
# Suspend the device to state S3.
/usr/sbin/acpiconf -s3Make the script executable:
chmod +x /usr/local/libexec/kde-suspendNow just write a devd rule to call your script on lid close:
# /etc/devd/kde-suspend.conf
notify 10 {
match "system" "ACPI";
match "subsystem" "Lid";
match "notify" "0x00";
action "/usr/local/libexec/kde-suspend";
};Restart devd to apply the change:
service devd restartOn FreeBSD, I’ve found that some processes keep running indefinitely after logging out of a KDE session.
Chromium is especially annoying: it sometimes gets trapped in a crazy state where it consumes 100% of a CPU core forever.
I imagine the KDE developers are mostly concerned with systemd-based Linux distributions, where systemd-logind ensures all processes associated with a user session are terminated when a session is closed.
Luckily, KDE has the ability to run a cleanup script whenever anyone logs out. Create the following directory:
mkdir -p /usr/local/etc/xdg/plasma-workspace/shutdownThen create a cleanup script in there, like so:
#!/bin/sh
#
# /usr/local/etc/xdg/plasma-workspace/shutdown/cleanup.sh
# Various processes seem to hang around after
# logging out of KDE sessions.
#
# Clean them up here!
pkill \
baloo_file \
chrome \
dirmngr \
pipewire \
plasma_waitforname \
signal-desktop \
wireplumber
# "agent" is too nondescript of a process name,
# so match on the full path
pkill -f /usr/local/libexec/geoclue-2.0/demos/agentDon’t forget to make it executable:
chmod +x /usr/local/etc/xdg/plasma-workspace/shutdown/cleanup.shDesktop user switching is broken on FreeBSD due to a longstanding ConsoleKit2 bug.
To prevent users from even attempting it, you can disable KDE user
switching globally in the kdeglobals file:
# /usr/local/etc/xdg/kdeglobals
[KDE Action Restrictions]
action/start_new_session=false
action/switch_user=falseUnfortunately, there is an iwlwifi bug present in 15.1-RELEASE that results in broken WiFi after resuming from sleep.
Luckily, there is a simple workaround: disable the interface before suspend, and
enable it after resume. This can be done automatically with a custom
rc.d script:
#!/bin/sh
#
# /usr/local/etc/rc.d/iwlwifi_fix
#
# PROVIDE: iwlwifi_fix
# KEYWORD: suspend resume
. /etc/rc.subr
name="iwlwifi_fix"
extra_commands="suspend resume"
suspend_cmd="iwlwifi_fix_suspend"
resume_cmd="iwlwifi_fix_resume"
iwlwifi_fix_suspend(){
/usr/sbin/service netif stop wlan0
}
iwlwifi_fix_resume(){
/usr/sbin/service netif start wlan0
}
load_rc_config "$name"
run_rc_command "$1"Make sure it’s enabled:
chmod +x /usr/local/etc/rc.d/iwlwifi_fix
sysrc -v iwlwifi_fix_enable="YES"A fix has already been committed to 15-STABLE, so hopefully this workaround will be unnecessary once FreeBSD 15.2 is released.
There is an i915 bug
on some laptops that results in hard lockups. The problem is accompanied by dmesg errors that
look like this:
hdac0: Command timeout 2
The solution is a simple loader tunable:
compat.linuxkpi.i915_disable_power_well=0With FreeBSD 15.1, the default DRM driver was bumped from version 6.6 to version 6.12.
Unfortunately, the new version appears to have a bug
on some Intel chips that causes graphical freezes accompanied by GPU HANG messages in dmesg.
A reliable workaround is to simply continue using the previous version:
pkg install drm-66-kmodA few years ago, FreeBSD switched from the old syscons(4) console driver to the new UEFI-native vt(4) driver.
Unfortunately, no one bothered
to add blanktime support to the vt console, so there’s effectively no way
to blank the screen on FreeBSD unless you’re running an X11 or Wayland session.
Because the Ly display manager runs on the TTY console, this means that when no one is logged in, your screen stays on forever. This isn’t much of an issue on single-user laptops, but if you’re building a multi-user workstation, you might burn the login prompt into your LCD panel!
The only GTK4 app I use is the Dino IM XMPP client. I noticed that many icons failed to render, and the app didn’t respect my KDE font settings.
After way too much debugging, I discovered that disabling portals fixed the problem immediately:
export GDK_DEBUG=no-portalsI try my best to avoid GTK apps, so I’m happy with this hacky workaround.
Pulseaudio would occasionally give me crackling and skipping when playing audio files.
This was easily fixed by bumping up some default values in pulseaudio’s daemon.conf:
default-fragments = 8
default-fragment-size-msec = 5