| POST-INSTALL(7) | Miscellaneous Information Manual | POST-INSTALL(7) |
post-install —
from a freshly installed rawnix to a working
desktop
This page picks up where installation(7) ends: the system boots, root has a password, and the ports tree is synced. What follows is the order that works, and the one place where the order matters: the graphics driver is chosen before wlroots is built, because wlroots and everything above it is built against it.
Everything here uses pkg(8),
which resolves dependencies and installs them. Add
-b to fetch prebuilt packages instead of building,
which is much faster and needs no compiler:
# pkg add -b footroot is for administration; log in as a user.
# useradd -m -G wheel,audio,video,input,plugdev zorz # passwd zorz
The groups are the ones a desktop needs:
video and input for the
compositor, audio for sound,
plugdev for
stik(8), and
wheel for doas(1).
# pkg add -b opendoas # echo 'permit persist :wheel' > /etc/doas.conf # chmod 640 /etc/doas.conf
Both are services; see SERVICES below.
# pkg add -b openntpd dhcpcd # ln -s /etc/sv/ntpd /service/ntpd # ln -s /etc/sv/dhcpcd /service/dhcpcd
A server with a static address configures it in /etc/dhcpcd.conf rather than by hand, so one service owns the interface.
On anything reachable from a network:
# pkg add -b nftables # vi /etc/nftables.conf # ln -s /etc/sv/nftables /service/nftables
The shipped /etc/nftables.conf drops
everything inbound except ssh; open what the machine serves. With sshd
reachable from the internet, add sshguard.
Choose the Mesa package before building wlroots. wlroots, the compositors and everything that draws are built against the Mesa that is installed, so installing the wrong one means building them all again.
There is one Mesa package per driver, and only one is installed at a time:
mesa-amdgpumesa-intelmesa-nouveaumesa-virtioWhich one, if you are not sure:
$ lspci | grep -i -E
'vga|3d|display'Then, for example:
# pkg add -b mesa-amdgpuThe LLVM target matters here too. Mesa's AMD driver compiles
shaders with LLVM, so llvm has to be built with
AMDGPU among its targets; the Intel driver does not,
and nouveau uses NVPTX. See
rawnix(7),
Clang and LLVM. If llvm was built
without the target your Mesa needs, rebuild llvm first, then Mesa.
The kernel is monolithic: every driver a machine needs to boot, mount its disks and reach the network is built in, so nothing has to be loaded for the system to come up. Two kinds of driver are the exception and are built as modules, because which one a machine needs is not known in advance:
These are loaded at boot from /etc/rc.modules, a shell script run early in /etc/runit/1. Create it with the modules this machine needs and make it executable:
#!/bin/sh modprobe jitterentropy_rng modprobe iwlmvm modprobe iwlwifi modprobe amdgpu
# chmod 755 /etc/rc.modules
Line by line:
jitterentropy_rngiwlmvm,
iwlwifiiwlwifi is the driver and
iwlmvm the operating mode it hands the device to.
Other chips need their own: ath9k or
ath11k for Atheros and Qualcomm,
rtw88_8822be and the like for Realtek,
mt7921e for MediaTek.amdgpuamdgpu for AMD, i915 or
xe for Intel, nouveau for
NVIDIA, virtio_gpu in a virtual machine.What a machine actually has, and what claims it once loaded:
$ lspci -k | grep -A3 -i -E 'network|vga|3d|display' $ lsmod $ dmesg | grep -i -E 'firmware|iwlwifi|amdgpu'
Wireless also needs its firmware, which is not in the kernel:
# pkg add -b
linux-firmwaredmesg about firmware that could not be found.
A server needs none of this: no wireless, no graphics.
jitterentropy_rng alone is still worth the one
line.
With Mesa in place:
# pkg add -b seatd # ln -s /etc/sv/seatd /service/seatd
seatd hands the compositor the graphics
and input devices, so it needs no privileges of its own. Its group is
seatd; add the user to it if the compositor refuses
to open the display.
Then one of the two:
swaylabwcBoth are wlroots compositors and can be installed side by side; pick one at login.
# pkg add -b labwc foot $ labwc
foot is the terminal. Without one, a
compositor starts into an empty screen with no way to type anything.
None of this is required; it is what most installs end up with.
footsfwbarfnottwl-clipboardgrim,
slurpimvmpvfirefox,
thunderbirdfont-dejavu,
font-jetbrains-monoSound is alsa-utils;
alsamixer unmutes what is muted by default.
A service is enabled by linking it into /service, and runit starts it within seconds.
# ln -s /etc/sv/nginx /service/nginx # enable, starts now # rm /service/nginx # disable, stops now # sv status /service/* # everything # sv restart nginx # one # sv down nginx ; sv up nginx # stop, start
It is /service, not /var/service and not /run/runit/service; see rawnix(7). Logs are under /var/log/service/current, written by each service's own log/run.
A package that ships a service is linked in by addpkg(8) at install time, so it is already running when the install finishes.
# ports -u # fetch the newest recipes # pkg diff # what is older than its port # pkg sysup -b # update everything, from prebuilt packages # revdep # anything broken afterwards
Without -b everything is built from
source, which needs llvm and the rest of the development tools. A server
usually wants -b and no compiler at all.
The kernel is never updated by pkg sysup:
it is installed by hand, so that a running machine does not get a new kernel
by surprise.
# pkg add -b linux-6.12.111 # ls /boot/efi/limine.conf
Installing a kernel runs limine-sync,
which writes the boot menu from what is in /boot.
The previous kernel stays in the menu; keep it until the new one has booted.
See bootloader(7).
https://audit.rawnix.org/ lists which ports are outdated and which have open CVEs, including the kernel.
To stop a package being updated, lock it:
# pkg lock rust # pkg locked
A locked port keeps its own copy of the recipe, so
ports -u cannot change it; see
pkg(8).
doas(1), bootloader(7), installation(7), rawnix(7), mkpkg(8), pkg(8), ports(8), revdep(8), stik(8)
| October 1, 2026 | setup 1.4 |