System Administration

04

Package Management

krypt/sh has three layers of package management: low-level tools (addpkg, delpkg, infopkg) that operate on binary archives and the package database, the build tool (mkpkg) that compiles ports into packages, and the high-level manager (pkg) that resolves dependencies and orchestrates everything.

Binary package tools

CommandDescription
addpkg pkg.tar.gzInstall a binary package archive
addpkg -u pkg.tar.gzUpgrade an installed package
delpkg nameRemove an installed package
infopkg -iList all installed packages
infopkg -l nameList files owned by a package
infopkg -o patternFind which package owns a file

Configuration files under /etc are preserved on upgrade by default. See addpkg.conf(5) for details.

The pkg package manager

CommandDescription
pkg add pkgInstall a package and all dependencies
pkg update pkgUpdate a package to the ports tree version
pkg del pkgRemove an installed package
pkg sysupUpdate all outdated packages
pkg diffShow version differences (installed vs ports)
pkg depends pkgShow the dependency tree
pkg rdepends pkgShow reverse dependencies
pkg autoremoveRemove orphaned dependency packages
pkg lock pkgPrevent a package from being updated

pkg searches port directories in the order defined in /etc/pkg.conf. When multiple ports provide the same package name, the last match wins. See pkg(8) and pkg.conf(5).

Typical workflow

# Sync the ports tree
# ports -u
# See what's outdated
# pkg diff
# Update everything
# pkg sysup
# Install something new
# pkg add firefox
# Clean up
# pkg autoremove

Reverse dependency checking (revdep)

When a shared library is updated, binaries linked against the old version will break — the dynamic linker cannot find the previous .so name. The revdep tool scans every installed binary and reports packages with broken library links.

Here is a real-world example: upgrading libvpx and nettle bumps their soname versions. Any package linked against the old libraries will fail to start:

$ firefox
XPCOMGlueLoad error for file /usr/lib/firefox/libxul.so:
Error loading shared library libvpx.so.11: No such file or directory
Couldn't load XPCOM.

Instead of guessing which packages are affected, run revdep to find them all:

# 1. Update the libraries
# addpkg -u libvpx#1.15.1-1.pkg.tar.gz
# addpkg -u nettle#3.10.1-1.pkg.tar.gz
# 2. Find every package with broken links
# revdep
firefox
thunderbird
ffmpeg
mpv
rdfind
# 3. Clean, rebuild, and upgrade each one
# cd /usr/ports/opt/firefox && mkpkg -c && mkpkg -d && addpkg -u firefox#*.pkg.tar.gz
# cd /usr/ports/opt/thunderbird && mkpkg -c && mkpkg -d && addpkg -u thunderbird#*.pkg.tar.gz
# cd /usr/ports/opt/ffmpeg && mkpkg -c && mkpkg -d && addpkg -u ffmpeg#*.pkg.tar.gz
# cd /usr/ports/opt/mpv && mkpkg -c && mkpkg -d && addpkg -u mpv#*.pkg.tar.gz
# cd /usr/ports/opt/rdfind && mkpkg -c && mkpkg -d && addpkg -u rdfind#*.pkg.tar.gz
# 4. Verify — should produce no output
# revdep

Note the use of mkpkg -c (clean) before rebuilding — the package version has not changed, only its library dependencies have. Without cleaning first, mkpkg sees the existing binary as current and skips the build. Clean removes it, forcing a full rebuild.

Always run revdep after upgrading core libraries such as libressl, libvpx, nettle, icu, libpng, or anything in /lib. A single library bump can silently break dozens of packages — revdep catches them all in one pass.
05

Building Ports

Every package in krypt/sh is defined by a MAKEPKG file — a shell-like recipe that describes how to fetch, build, and package software. See MAKEPKG(5) for the full specification.

Syncing ports

# Sync all port collections
# ports -u
# Sync a specific collection
# ports -u core
# List all available ports
# ports -l

Port collections are configured via /etc/ports/*.rsync files and synced from rsync.krypt.sh. See ports(8).

Building a package

# Navigate to a port
# cd /usr/ports/opt/nftables
# Install build dependencies
# pkg prepare
# Download and build
# mkpkg -d
# Install the built package
# addpkg name#*.pkg.tar.gz
# Upgrade an existing package
# addpkg -u name#*.pkg.tar.gz

MAKEPKG anatomy

#!/bin/mkpkg
# *** krypt/sh ***
# description: Shows the full path of shell commands
# url: https://www.gnu.org/software/which/
name=which
version=2.21
release=1
depends=()
source=(https://ftp.gnu.org/gnu/$name/$name-$version.tar.gz)
sha256sums=(abc123...)
build() {
    cd $name-$version
    ./configure --prefix=/
    make
    make DESTDIR=$PKG install
}

Key arrays: depends=() for runtime dependencies, makedeps=() for build-time dependencies, groups=() for declarative user/group creation, services=() for runit service enablement, and permissions=() for file ownership. Note: krypt/sh uses makedeps=(), not makedepends=().

Build configuration

Compiler flags and build settings live in /etc/mkpkg.conf. Only the shell(), build(), and post_build() hooks source this file — extract() and patch() do not need build flags so they skip it. See mkpkg.conf(5).

06

Services & Init

krypt/sh uses runit as its init system with a vanilla setup. The supervised service directory is /service — not /var/service like some other distributions. Service definitions live in /etc/sv/ and are activated by symlinking into /service/.

That said, krypt/sh is not bound to runit. The ports tree ships it as the default, but you are free to build and use the init system of your choice — the system has no hard dependency on any specific init.

Managing services

# Enable a service
# ln -s /etc/sv/dhcpcd /service/
# Check status
# sv status dhcpcd
# Stop / start / restart
# sv stop dhcpcd
# sv start dhcpcd
# sv restart dhcpcd
# Disable a service
# rm /service/dhcpcd
# List enabled services
# ls /service/
# List available services
# ls /etc/sv/

Service file structure

Each service directory under /etc/sv/ contains a run script and optionally a log/run for logging via svlogd. Packages that ship runit services declare them in the services=() array of their MAKEPKG file, and addpkg creates the /service symlink automatically.

Example: simple daemon

A typical service run script for a daemon like dhcpcd:

#!/bin/sh
exec 2>&1
exec dhcpcd -B -M

The corresponding log script sends output to svlogd:

#!/bin/sh
mkdir -p /var/log/dhcpcd
exec svlogd -tt /var/log/dhcpcd

Example: nftables (one-shot)

Services that load configuration and exit (like a firewall) use a finish script and sv once:

#!/bin/sh
exec 2>&1
nft -f /etc/nftables.conf
exec pause

Example: seatd with cleanup

Services that create runtime files can use a finish script for cleanup:

#!/bin/sh
exec 2>&1
exec seatd -g seat
#!/bin/sh
rm -f /run/seatd.sock
Key points: All run, finish, and log/run scripts must be executable (chmod 755). Daemons should run in the foreground — runit supervises the process directly. Use exec so the daemon replaces the shell process.
08

Networking

krypt/sh uses simple, traditional networking tools — no NetworkManager, no systemd-networkd. Network interfaces are configured through dhcpcd for DHCP, manual ip commands or boot scripts for static addressing, and wpa_supplicant for WiFi. All network services run under runit supervision.

Static IP

For a static IP configuration, create a boot script that brings up the interface. This runs at boot via the /etc/boot.d/ mechanism:

#!/bin/sh
ip addr add 192.168.1.100/24 dev eth0
ip link set eth0 up
ip route add default via 192.168.1.1

Make it executable with chmod +x /etc/boot.d/network. Note that krypt/sh uses net.ifnames=0 on the kernel command line by default, so interfaces use classic names like eth0 and wlan0 rather than predictable names like enp3s0.

DHCP

dhcpcd handles DHCP for both wired and wireless interfaces. Enable it as a runit service:

# Enable the dhcpcd service
# ln -s /etc/sv/dhcpcd /service/
# Check it's running
# sv status dhcpcd
# Or run manually for a specific interface
# dhcpcd eth0

By default, dhcpcd will configure all available interfaces. To restrict it to a specific interface, edit /etc/dhcpcd.conf and add allowinterfaces eth0.

WiFi (wpa_supplicant)

WiFi is handled by wpa_supplicant. For a persistent setup that survives reboots, create a configuration file and a runit service.

First, generate the configuration:

# Generate a config with your network credentials
# wpa_passphrase "MyNetwork" "MyPassword" > /etc/wpa_supplicant.conf
# Verify it looks right
# cat /etc/wpa_supplicant.conf

Then create a runit service to start it at boot:

#!/bin/sh
exec 2>&1
exec wpa_supplicant -i wlan0 -c /etc/wpa_supplicant.conf
# chmod 755 /etc/sv/wpa_supplicant/run
# ln -s /etc/sv/wpa_supplicant /service/

With both wpa_supplicant and dhcpcd running as services, WiFi will connect and obtain an address automatically at boot. For multiple networks, add additional network={} blocks to /etc/wpa_supplicant.confwpa_supplicant will choose the best available one.

WiFi firmware: Most WiFi chipsets require firmware files in /lib/firmware. The linux-firmware package provides these. Intel chips (iwlwifi) also need the driver loaded via /etc/rc.modules — see the Loading modules section.

DNS resolution

DNS is configured in /etc/resolv.conf. When using dhcpcd, this file is updated automatically. For static setups, set it manually:

nameserver 1.1.1.1
nameserver 9.9.9.9

If dhcpcd overwrites your manual settings, you can prevent this by adding nohook resolv.conf to /etc/dhcpcd.conf, or simply make the file immutable with chattr +i /etc/resolv.conf.

Firewall (nftables)

krypt/sh uses nftables for firewalling — not iptables. A sensible default configuration that blocks incoming connections while allowing outbound traffic:

#!/sbin/nft -f
flush ruleset
table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        # Allow established/related connections
        ct state established,related accept
        # Allow loopback
        iif lo accept
        # Allow ICMP (ping)
        meta l4proto icmp accept
        # Allow SSH
        tcp dport 22 accept
        # Drop everything else
    }
    chain forward {
        type filter hook forward priority 0; policy drop;
    }
    chain output {
        type filter hook output priority 0; policy accept;
    }
}

The nftables service loads this configuration at boot as a one-shot service (see Services & Init):

# Enable the nftables service
# ln -s /etc/sv/nftables /service/
# Verify rules are loaded
# nft list ruleset
# Reload after editing nftables.conf
# nft -f /etc/nftables.conf
Adding services: To expose a web server, add tcp dport { 80, 443 } accept to the input chain. For more complex setups, nftables supports sets, maps, rate limiting, and logging — see man nft.
09

Users & Permissions

krypt/sh does not use Linux-PAM. User management is handled by traditional shadow utilities — useradd, usermod, userdel, passwd, and groupadd. Authentication goes through /etc/shadow directly.

Adding users

Create a regular user with a home directory and login shell:

# Create a user with home directory
# useradd -m -s /bin/bash username
# Set password
# passwd username
# Add to supplementary groups
# usermod -aG wheel,audio,video,seat username
# Verify
# id username

The -m flag creates /home/username. The XDG runtime directory at /run/user/UID is created at boot by the /etc/boot.d/xdg-runtime script for any user with a UID ≥ 1000 (see Filesystem Layout).

Groups & privileges

Group membership controls hardware and service access. The important groups on an krypt/sh system:

GroupPurpose
wheelCan use su / doas for root access
audioDirect access to ALSA sound devices
videoDirect access to GPU and framebuffer devices
seatAccess to seatd for Wayland compositors
inputAccess to /dev/input devices
kvmAccess to /dev/kvm for virtualization
diskRaw disk device access (use with caution)

Packages that need system groups declare them in the groups=() array of their MAKEPKG file. addpkg creates the groups automatically during installation.

Privilege escalation

Without PAM, sudo does not work out of the box. krypt/sh provides two alternatives:

su — the traditional tool. Members of the wheel group can switch to root:

# Switch to root (enter root password)
$ su -
# Run a single command as root
$ su -c 'pkg sysup'

doas — a minimal sudo replacement from OpenBSD. Install it from the ports tree and create a configuration:

# pkg add doas
# Allow wheel group members to run commands as root
# echo 'permit :wheel' > /etc/doas.conf
# Optionally persist authentication for 5 minutes
# echo 'permit persist :wheel' > /etc/doas.conf
# Set restrictive permissions
# chmod 600 /etc/doas.conf
Why not sudo? The standard sudo package has a hard dependency on PAM for session and authentication handling. Since krypt/sh does not ship PAM, doas is the recommended alternative — it works directly with /etc/shadow and has a much smaller attack surface.

Login shell & environment

The default login shell is set per-user in /etc/passwd and can be changed with usermod -s /bin/bash username. Environment setup happens through /etc/profile and drop-in scripts in /etc/profile.d/.

krypt/sh ships two profile scripts by default: /etc/profile.d/xdg.sh (XDG base directories) and /etc/profile.d/path.sh (PATH additions). You can add your own by dropping executable .sh files in /etc/profile.d/ — they are sourced in alphabetical order on login.

10

Graphics & Wayland

krypt/sh is a pure Wayland system — X11 is not part of the core. The graphics stack consists of kernel DRM drivers, Mesa for userspace OpenGL/Vulkan, seatd for seat management, and a Wayland compositor of your choice.

The graphics stack

The layers involved in getting pixels on screen:

LayerComponent
KernelDRM driver (amdgpu, i915, nouveau)
Userspace driverMesa (radeonsi, iris, nouveau, llvmpipe)
Seat managementseatd — grants GPU/input access
Wayland protocolwayland, wayland-protocols
Compositorlabwc, sway, or other wlroots-based
ToolkitGTK4, Qt6 (with Wayland backend)

There is no display manager — you launch the compositor directly from a TTY login. The compositor handles window management, input, and output all in one process.

Seat management (seatd)

seatd is a minimal seat management daemon that replaces elogind and systemd-logind. It grants unprivileged users access to GPU, input, and DRM devices through the seat group.

# Ensure your user is in the seat group
# usermod -aG seat username
# Enable the seatd service
# ln -s /etc/sv/seatd /service/
# Verify it's running
# sv status seatd

The seatd runit service runs with -g seat, restricting access to members of the seat group. The socket at /run/seatd.sock is cleaned up by the service's finish script.

seatd must be running before the compositor starts. If you see errors about Failed to connect to seat or libseat: Could not connect, check that seatd is active and your user is in the seat group.

GPU drivers

GPU drivers are kernel modules loaded via /etc/rc.modules (see Loading modules). Mesa provides the userspace OpenGL and Vulkan implementations:

GPUKernel moduleMesa driver
AMD Radeon (GCN+)amdgpuradeonsi (GL), radv (Vulkan)
Intel (Gen 8+)i915iris (GL), anv (Vulkan)
Intel (Arc)xe / i915iris (GL), anv (Vulkan)
NVIDIA (open)nouveaunouveau (GL, limited)
Softwarellvmpipe (CPU fallback)

Add the appropriate modprobe line to /etc/rc.modules. AMD and Intel GPUs work well with the open-source stack. For NVIDIA, the proprietary driver is not available on musl — nouveau provides basic support but lacks reclocking on most cards.

Hybrid graphics (AMD + Intel): On laptops with both a discrete and integrated GPU, both kernel modules should be loaded. The compositor will typically use the discrete GPU. Power management for the discrete GPU can be controlled via /sys/bus/pci/devices/.../power/control.

Compositors (labwc / sway)

krypt/sh ships labwc and sway in the ports tree — both are wlroots-based Wayland compositors. Launch them directly from a TTY after logging in:

# Option A: labwc (stacking compositor, openbox-like)
$ labwc
# Option B: sway (tiling compositor, i3-like)
$ sway

labwc is a stacking window manager similar to Openbox. Configuration lives in ~/.config/labwc/ with files for rc.xml (keybinds, window rules), menu.xml (right-click menu), and autostart (programs to launch). It is a good choice if you prefer a traditional floating window experience.

sway is an i3-compatible tiling compositor. Configuration lives in ~/.config/sway/config. If you are familiar with i3, the transition is seamless — most configuration directives work identically.

Both compositors need the XDG_RUNTIME_DIR environment variable set and seatd running. If you followed the installation guide, both are already in place.

Auto-start from login: To launch the compositor automatically when you log in on TTY1, add this to the end of your ~/.profile or ~/.bash_profile:

[ "$(tty)" = "/dev/tty1" ] && exec labwc

Troubleshooting

Common graphics issues and how to diagnose them:

SymptomCause / fix
Permission denied on /dev/driUser not in video and seat groups
Failed to connect to seatseatd not running — check sv status seatd
No XDG_RUNTIME_DIRMissing /etc/profile.d/xdg.sh or /etc/boot.d/xdg-runtime
Black screen on launchGPU module not loaded — check /etc/rc.modules
Software rendering onlyMesa not finding GPU — run LIBGL_DEBUG=verbose glxinfo
Compositor crashes on exitNormal if seatd.sock isn't cleaned — the finish script handles it

For debugging, run the compositor with verbose output: WLR_RENDERER=vulkan sway or WAYLAND_DEBUG=1 labwc. Check dmesg for DRM/GPU errors and lsmod to confirm the right driver is loaded.

LLVM musl libc libressl Independent