FreeBSD setup notes for older MacBook Air / Mac systems

This note summarizes the main settings and commands used during the setup.
Device names can differ between machines, so always check the actual hardware first:

pciconf -lv
ifconfig
cat /dev/sndstat
ls /dev/backlight/
sysctl -a | grep -i light
dmesg | tail


=============================================================================
1. Base system and package management
=============================================================================

Update third-party packages:

su -
pkg update
pkg upgrade

Remove unused dependencies:

pkg autoremove

Clean the downloaded package cache:

pkg clean

Security audit for installed packages:

pkg audit -F

Update the FreeBSD base system / kernel / userland:

su -
freebsd-update fetch
freebsd-update install
reboot

After reboot, check versions:

freebsd-version -kru

If freebsd-update shows a long file list and a ":" prompt at the bottom, press:

q

Then continue with:

freebsd-update install

Note:
The pkg tool manages third-party software only. The FreeBSD base system and kernel are updated with freebsd-update.


=============================================================================
2. Xorg, XFCE, and keyboard layout
=============================================================================

Start XFCE through startx:

startx

User ~/.xinitrc example:

setxkbmap hu
exec startxfce4

Edit it as the regular user:

ee ~/.xinitrc

Temporary keyboard layout change under X:

setxkbmap hu

Optional system-wide X keyboard configuration:

su -
mkdir -p /usr/local/etc/X11/xorg.conf.d
ee /usr/local/etc/X11/xorg.conf.d/00-keyboard.conf

File content:

Section "InputClass"
Identifier "Keyboard Defaults"
MatchIsKeyboard "on"
Option "XkbLayout" "hu"
EndSection

The command below only disables the X11 bell/beep and is optional:

xset b off


=============================================================================
3. Graphics / DRM kernel modules
=============================================================================

Identify the GPU:

pciconf -lv | grep -B3 -A5 -Ei "display|vga|3d|amd|radeon|nvidia|intel"

Add the user to the video group:

su -
pw groupmod video -m <username>

Then log out and back in, or reboot.

Check group membership:

id


-------------------------------------------------------------------------------
3/A. Intel graphics on MacBook Air
-------------------------------------------------------------------------------

Install:

su -
pkg install drm-kmod

Load the module:

kldload i915kms

Load it automatically at boot:

sysrc kld_list+=i915kms

Check:

kldstat | grep i915


-------------------------------------------------------------------------------
3/B. AMD Radeon Baffin / Polaris11 graphics on desktop Mac
-------------------------------------------------------------------------------

Observed GPU family:
Baffin [Radeon RX 460/560 / Pro 450/455/460/555/555X/560/560X]

This needs amdgpu, not radeonkms.

Install:

su -
pkg install drm-kmod xf86-video-amdgpu
pkg install gpu-firmware-amd-kmod-polaris11

Load the module:

kldload amdgpu

Load it automatically at boot:

sysrc kld_list+=amdgpu

Check:

kldstat | grep -E "amdgpu|drm"
ls /dev/dri

Expected devices:

/dev/dri/card0
/dev/dri/renderD128

If Xorg still fails with an scfb/framebuffer error, create a manual BusID configuration:

su -
mkdir -p /usr/local/etc/X11/xorg.conf.d
ee /usr/local/etc/X11/xorg.conf.d/20-amdgpu.conf

File content:

Section "Device"
Identifier "AMD Radeon"
Driver "amdgpu"
BusID "PCI:1:0:0"
EndSection


=============================================================================
4. Display brightness
=============================================================================

Check available backlight devices:

ls /dev/backlight/

Typical devices:

/dev/backlight/backlight0
/dev/backlight/intel_backlight0

Show current brightness:

backlight

Set brightness:

su -
backlight 50
backlight incr 10
backlight decr 10

If multiple devices exist:

backlight -f /dev/backlight/intel_backlight0 50
backlight -f /dev/backlight/backlight0 50

Examples for XFCE keyboard shortcuts:

sudo /usr/sbin/backlight incr 10
sudo /usr/sbin/backlight decr 10

To run these as a regular user without a password, allow the required command through sudoers.


=============================================================================
5. Keyboard backlight / Apple SMC
=============================================================================

Apple SMC module:

su -
kldload asmc

Load it automatically at boot:

sysrc kld_list+=asmc

Check light-related sysctl variables:

sysctl -a | grep -i light

Important variable:

dev.asmc.0.light.control

Set keyboard backlight as root:

sysctl dev.asmc.0.light.control=0
sysctl dev.asmc.0.light.control=128
sysctl dev.asmc.0.light.control=255

Note:
dev.asmc.0.light.left and dev.asmc.0.light.right may be read-only sensor values.
If they return a "read only" error, that is expected. The control variable is light.control.

Optional default value in /etc/sysctl.conf:

dev.asmc.0.light.control=128

Edit:

su -
ee /etc/sysctl.conf


=============================================================================
6. Passwordless sudo for selected commands
=============================================================================

Install sudo:

su -
pkg install sudo

Edit sudoers safely:

su -
visudo

Useful vi commands inside visudo:

G go to end of file
o open a new line below
Esc leave insert mode
:wq save and quit
:q! quit without saving
dd delete current line
u undo

Example: allow only the needed brightness commands, not full root access:

<username> ALL=(root) NOPASSWD: /usr/sbin/backlight, /sbin/sysctl dev.asmc.0.light.control=0, /sbin/sysctl dev.asmc.0.light.control=64, /sbin/sysctl dev.asmc.0.light.control=128, /sbin/sysctl dev.asmc.0.light.control=192, /sbin/sysctl dev.asmc.0.light.control=255

Do not use this unless you explicitly want full passwordless root access:

<username> ALL=(root) NOPASSWD: ALL


=============================================================================
7. Audio
=============================================================================

Check audio devices:

cat /dev/sndstat
mixer

On the tested MacBook Air 13-inch system:

pcm0: Intel Broadwell HDMI/DP audio
pcm1: Cirrus Logic CS4208 Analog
pcm2: Cirrus Logic CS4208 Analog Headphones

Set default output:

su -
sysctl hw.snd.default_unit=1 # internal analog
sysctl hw.snd.default_unit=2 # headphones

Mixer controls:

mixer -f /dev/mixer1
mixer -f /dev/mixer2

Internal speaker volume:

mixer -f /dev/mixer1 vol=80
mixer -f /dev/mixer1 pcm=80

Headphone volume:

mixer -f /dev/mixer2 vol=80
mixer -f /dev/mixer2 pcm=80

Incremental volume commands for XFCE shortcuts:

/usr/sbin/mixer -f /dev/mixer1 vol=+5%
/usr/sbin/mixer -f /dev/mixer1 vol=-5%
/usr/sbin/mixer -f /dev/mixer1 vol.mute=toggle

For headphones, use mixer2:

/usr/sbin/mixer -f /dev/mixer2 vol=+5%
/usr/sbin/mixer -f /dev/mixer2 vol=-5%

Cirrus Logic / MacBook speaker workaround:
If the headphone jack works but the internal speaker does not, this helped on the tested system:

su -
sysctl dev.hdaa.1.gpio_config=0=set

Noise test:

dd if=/dev/urandom of=/dev/dsp1 bs=4096 count=50

If it works, add this to /etc/sysctl.conf:

dev.hdaa.1.gpio_config=0=set

hdac0 timeout messages likely came from Intel HDMI/DP audio, not from the Cirrus internal analog audio. If internal sound and headphones work, it may be only noisy logging.


=============================================================================
8. USB Wi-Fi adapter
=============================================================================

Known working adapter:

TP-Link TL-WN725N
Realtek RTL8188EU
FreeBSD driver: rtwn_usb / rtwn
Interface: rtwn0 -> wlan0

Typical /etc/rc.conf configuration:

wlans_rtwn0="wlan0"
ifconfig_wlan0="WPA DHCP"

Multiple Wi-Fi networks in /etc/wpa_supplicant.conf:

su -
ee /etc/wpa_supplicant.conf

Example:

network={
ssid="HomeWifi"
psk="password"
priority=10
}

network={
ssid="PhoneHotspot"
psk="password"
priority=5
}

Restart Wi-Fi:

su -
service netif restart wlan0

If it does not get an IP address:

dhclient wlan0

Speed test:

speedtest-cli --simple

Measured results in this setup:

TP-Link TL-WN725N: about 12 Mbit/s download, 4-5 Mbit/s upload
Android USB tethering: about 200 Mbit/s download, 35 Mbit/s upload
Thunderbolt/Ethernet: about 764 Mbit/s download, 41 Mbit/s upload

Before unplugging the USB Wi-Fi adapter, stop it first. Live removal caused a freeze/panic once:

su -
service netif stop wlan0
ifconfig wlan0 down
sync

Then unplug it.

After plugging it back in:

service netif restart wlan0
dhclient wlan0


=============================================================================
9. Android USB tethering
=============================================================================

Android USB tethering on FreeBSD:

1. Connect the phone with a USB cable.
2. Enable USB tethering / USB internet sharing on Android.
3. Load the RNDIS driver on FreeBSD:

su -
kldload if_urndis

4. Check the interface:

ifconfig

Usually it appears as:

ue0

5. Bring it up and request an IP address:

ifconfig ue0 up
dhclient ue0

6. Test:

ping -c 3 freebsd.org
speedtest-cli --simple

To load the driver automatically at boot, add this to /boot/loader.conf:

if_urndis_load="YES"

Edit:

su -
ee /boot/loader.conf

Note:
It is fine to load if_urndis permanently. It is a small driver and only creates an interface when an Android USB tethering device is attached.


=============================================================================
10. Wired Ethernet with Apple Thunderbolt adapter
=============================================================================

The tested adapter looked like an Apple Thunderbolt to Gigabit Ethernet adapter.
Expected FreeBSD interface:

bge0

Check:

dmesg | tail -50
ifconfig

Manual setup:

su -
ifconfig bge0 up
dhclient bge0

Test:

ping -c 3 freebsd.org
speedtest-cli

Persistent /etc/rc.conf setting:

sysrc ifconfig_bge0="DHCP"

If multiple network connections are active, check the default route:

netstat -rn | grep default

Stop Wi-Fi if wired Ethernet should be used:

service netif stop wlan0

Switch back to Wi-Fi:

service netif stop bge0
service netif start wlan0


=============================================================================
11. Multiple network interfaces in rc.conf
=============================================================================

It is possible to configure all three:

wlans_rtwn0="wlan0"
ifconfig_wlan0="WPA DHCP"

ifconfig_ue0="DHCP"
ifconfig_bge0="DHCP"

However, if several are active at once, the default route may not be the one you expect.

Practical use:

wlan0 = default everyday network
ue0 = Android USB tethering when fast mobile internet is needed
bge0 = wired Ethernet when a cable is available


=============================================================================
12. Suspend / lid close sleep
=============================================================================

Manual suspend test:

su -
acpiconf -s 3

If it works, enable sleep on lid close:

su -
ee /etc/sysctl.conf

Add:

hw.acpi.lid_switch_state=S3

Apply immediately without reboot:

sysctl hw.acpi.lid_switch_state=S3

Disable lid-close sleep:

sysctl hw.acpi.lid_switch_state=NONE

Note:
There was one kernel panic during the first suspend test. The log suggested a USB Wi-Fi / networking race around detach/resume. Later lid-close suspend/resume worked correctly.


=============================================================================
13. Battery / charger
=============================================================================

Battery information:

acpiconf -i 0

Relevant lines only:

acpiconf -i 0 | grep -E "State|Remaining capacity|Remaining time|Present rate"

AC adapter state:

acpiconf -a

or:

sysctl hw.acpi.acline

Meaning:

1 = on AC power
0 = on battery

Battery states:

charging charging
discharging discharging
high battery is OK / not low or critical; not necessarily an error
low low battery
critical critical battery

Observation:
At one point the MagSafe LED was orange, but FreeBSD showed "discharging". Powered off, the machine charged. In such cases, check acpiconf -a and hw.acpi.acline, and observe whether the percentage increases over 10-15 minutes.


=============================================================================
14. USB flash drive / external SSD / external HDD mounting
=============================================================================

Find the device:

dmesg | tail
ls /dev/da*
gpart show

Detect filesystem:

fstyp /dev/da1
fstyp /dev/da1s1
fstyp /dev/da1p1

It is fine if some commands fail. Use the device node that actually reports a filesystem.

MBR partitions:

/dev/da1s1

GPT partitions:

/dev/da1p1

No partition table / whole-disk filesystem:

/dev/da1


-------------------------------------------------------------------------------
14/A. FAT / FAT32
-------------------------------------------------------------------------------

If fstyp reports:

msdosfs

Mount:

su -
mkdir -p /mnt/usb
mount -t msdosfs /dev/da1s1 /mnt/usb

For easier regular-user access:

mount_msdosfs -u <username> -g <username> /dev/da1s1 /mnt/usb


-------------------------------------------------------------------------------
14/B. exFAT
-------------------------------------------------------------------------------

Install:

su -
pkg install fusefs-exfat
kldload fusefs

Mount:

mkdir -p /mnt/usb
mount.exfat /dev/da1s1 /mnt/usb

If it says "exFAT file system is not found", the device is probably not exFAT or the wrong device node was used. Check:

fstyp /dev/da1
fstyp /dev/da1s1
fstyp /dev/da1s2


-------------------------------------------------------------------------------
14/C. NTFS
-------------------------------------------------------------------------------

Install:

su -
pkg install fusefs-ntfs
kldload fusefs

Mount:

mkdir -p /mnt/usb
ntfs-3g /dev/da1s1 /mnt/usb

Read-only mount if Windows did not cleanly detach it:

ntfs-3g -o ro /dev/da1s1 /mnt/usb


-------------------------------------------------------------------------------
14/D. UFS
-------------------------------------------------------------------------------

mount /dev/da1p1 /mnt/ssd


-------------------------------------------------------------------------------
14/E. ZFS
-------------------------------------------------------------------------------

zpool import

If the pool is named backup:

zpool import backup

Detach/export:

zpool export backup


-------------------------------------------------------------------------------
14/F. Unmounting
-------------------------------------------------------------------------------

sync
umount /mnt/usb

If it says "Device busy":

1. Close the Thunar/file-manager window that is showing /mnt/usb.
2. Make sure the terminal is not inside the mount point:

cd ~

3. Check what is using it:

fstat | grep /mnt/usb

4. Then retry:

umount /mnt/usb


=============================================================================
15. Thunar / graphical ZIP extraction
=============================================================================

If Thunar says:

Failed to extract files. No suitable archive manager found.

Then unzip is not the problem. A graphical archive manager is missing.

Install:

su -
pkg install thunar-archive-plugin xarchiver

Restart Thunar:

pkill thunar
thunar &

or log out and back in.

ZIP from terminal:

unzip file.zip


=============================================================================
16. Screenshots with a keyboard shortcut in XFCE
=============================================================================

Install:

su -
pkg install xfce4-screenshooter

XFCE path:

Settings -> Keyboard -> Application Shortcuts

Commands:

Full screen:

xfce4-screenshooter -f

Active window:

xfce4-screenshooter -w

Selected region:

xfce4-screenshooter -r

Suggested shortcuts:

Print Screen -> xfce4-screenshooter -f
Alt + Print Screen -> xfce4-screenshooter -w
Shift + Print Screen -> xfce4-screenshooter -r


=============================================================================
17. Window switching in XFCE
=============================================================================

Default:

Alt + Tab

Useful panel items:

Window Buttons
Window Menu

Panel right click:

Panel -> Add New Items...

XFCE does not include a macOS-style Mission Control / Expose overview by default.


=============================================================================
18. Bluetooth / webcam / Spotify
=============================================================================

Bluetooth hardware was visible as:

ubt0: Apple Inc. Bluetooth USB Host Controller

However, Bluetooth headphones require more than pairing: A2DP audio support is also needed. This was not worth the effort for this setup; wired headphones were the practical solution.

Bluetooth command tried:

service bluetooth start ubt0

Observed error:

Unable to setup Bluetooth stack for device ubt0

The blued package was not available from pkg in this setup.

Webcam:
The FaceTime Camera was visible on USB, but FreeBSD support was not straightforward. It was not pursued.

Spotify:
The Spotify web player opened, but playback/audio was not reliable. It was abandoned.

Local audio players:

pkg install audacious
pkg install vlc


=============================================================================
19. Internet speed test
=============================================================================

Install:

su -
pkg install py311-speedtest-cli

Run:

speedtest-cli
speedtest-cli --simple

Example measurements:

TL-WN725N USB Wi-Fi: 12.18 Mbit/s down, 4.71 Mbit/s up
Android USB tethering: 200.14 Mbit/s down, 34.99 Mbit/s up
Thunderbolt Ethernet: 764.36 Mbit/s down, 41.05 Mbit/s up


=============================================================================
20. Useful diagnostic commands
=============================================================================

System / boot log:

dmesg | tail
dmesg | grep -i ac
dmesg | grep -i battery
dmesg | grep -i ubt

PCI devices:

pciconf -lv
pciconf -lv | grep -B3 -A5 -Ei "display|vga|network|wireless|broadcom|amd|radeon|intel"

USB devices:

usbconfig
usbconfig | grep -i bluetooth
usbconfig | grep -i -E "realtek|wireless|wifi|802.11"

Network:

ifconfig
netstat -rn | grep default
sysctl net.wlan.devices

Audio:

cat /dev/sndstat
mixer
mixer -f /dev/mixer1
mixer -f /dev/mixer2

Graphics:

kldstat | grep -E "i915|amdgpu|drm"
ls /dev/dri

Battery:

acpiconf -i 0
acpiconf -a
sysctl hw.acpi.acline

Display brightness:

backlight
ls /dev/backlight/

Keyboard backlight:

sysctl -a | grep -i light


=============================================================================
21. General notes
=============================================================================

FreeBSD desktop setup has improved a lot, but it is still more manual than a typical Linux desktop distribution.

Best practical compromise on the older MacBook Air:

- XFCE
- Intel DRM / i915kms
- USB Wi-Fi left plugged in
- Android USB tethering or Thunderbolt Ethernet for fast networking
- wired headphones
- working suspend on lid close
- manual but functional display brightness and keyboard backlight

Problematic or not worth pursuing:

- built-in Broadcom Wi-Fi
- Bluetooth headphones
- FaceTime webcam
- Spotify web playback on FreeBSD
 
Do you have steps to setup Nvidia drivers?
I do not have a tested NVIDIA-specific write-up from this machine, because my setup was done on Intel and AMD graphics hardware. NVIDIA on FreeBSD is a different path: it normally uses NVIDIA's proprietary driver, not the drm-kmod setup used for Intel i915kms or AMD amdgpu.

For a modern NVIDIA card, the usual starting point is:

su -
pkg install nvidia-drm-kmod

Then enable DRM modesetting in /boot/loader.conf:

hw.nvidiadrm.modeset="1"

and load the NVIDIA DRM module automatically:

sysrc kld_list+=nvidia-drm

Then reboot:

reboot

Basic checks after reboot:

kldstat | grep -i nvidia
pciconf -lv | grep -B3 -A5 -i nvidia

For older NVIDIA cards, the correct package may be one of the legacy driver branches instead of the current driver, for example the 470, 390, 340 or 304 series, depending on the GPU generation. The exact package and module name can differ between driver generations.

For a desktop machine with a single NVIDIA GPU, this is usually manageable. On laptops with hybrid graphics, such as Intel + NVIDIA Optimus systems, it can be much more complicated and may require a more machine-specific setup.

Also, after FreeBSD kernel upgrades, it is worth checking that the installed NVIDIA kernel module still matches the running kernel.
 
No, I did not test DRM-protected video playback on this setup.

My setup was mainly focused on getting the old MacBook Air usable under FreeBSD: XFCE, graphics acceleration, audio, Wi-Fi, Ethernet, printing, suspend, brightness, etc. I did not try Widevine/EME playback.

As far as I know, Firefox on FreeBSD does not have native Widevine support. For DRM-protected course videos, the realistic FreeBSD options seem to be:

1. Chromium with foreign-cdm + linux-widevine-cdm, if you are willing to set that up.
2. A Linux browser running under the Linux compatibility layer / Linux chroot.
3. Use a Linux, macOS or Windows system for DRM-heavy online courses if reliability is important.

There is a FreeBSD port called foreign-cdm, described as a Linuxulator-based CDM agent for Chromium, and a linux-widevine-cdm port that provides the Linux Widevine CDM binary. Another practical route is linux-browser-installer, which installs Linux versions of Chrome/Brave/Vivaldi/etc. under a Linux chroot on FreeBSD.

So: possible, but I would not call it a simple or guaranteed part of a normal FreeBSD desktop setup. For online classes where the video must work reliably, I would keep a Linux/macOS/Windows fallback.
 
I got Widevine component to show up but MSE is not there when Udemy does a scan on Chromium so there could be more than just needing widevine for this.
 
Back
Top