OctoPi#
Role#
Raspberry Pi 3B in the kitchen/workshop corner. Tagged rpi in
hosts/default.nix (aarch64 — deploy pushes closures; nothing builds
on-device).
The config path is misleading
octopi lives at hosts/x86_64-nixos/octopi/ although it is aarch64. The
path is historical; arch, class, and system come from its entry in
hosts/default.nix, not from the directory name (haxo, the other Pi, sits
under hosts/aarch64-nixos/). Moving it is a one-line registry edit that
needs an rpi cache-hit check afterwards — tracked in
In-flight work.
What it runs#
- OctoPrint (
services.octoprint) — the 3D-printer controller. - Kitchen barcode scanner (
tsunaminoai.barcodeScanner) — a Tera HW0009 wireless scanner bridged evdev → MQTT for Home Assistant / grocery intake. - Mail document scanner (
tsunaminoai.documentScanner) — the ScanSnap S1500M’s hardware button scans multipage PDFs straight into Paperless on ereshkigal. - clamav is force-disabled (
tsunaminoai.security.clamav.enable = false) — clamd’s resident signature database OOM-killed the 1 GB / no-swap box and starved sshd. (It was not the cause of the Wi-Fi failure; see below.)
Fast facts#
▗▄▄▄ ▗▄▄▄▄ ▄▄▄▖ tsunami@octopi
▜███▙ ▜███▙ ▟███▛ --------------
▜███▙ ▜███▙▟███▛ OS: NixOS 24.11.20250106.3f0a8ac (Vicuna) aarch64
▜███▙ ▜██████▛ Host: Raspberry Pi 3 Model B Rev 1.2
▟█████████████████▙ ▜████▛ ▟▙ Kernel: Linux 6.6.31
▟███████████████████▙ ▜███▙ ▟██▙ Uptime: 3 mins
▄▄▄▄▖ ▜███▙ ▟███▛ Packages: 879 (nix-system)
▟███▛ ▜██▛ ▟███▛ Shell: fish 3.7.1
▟███▛ ▜▛ ▟███▛ Display (Unknown-1): 656x416
▟███████████▛ ▟██████████▙ Terminal: /dev/pts/0
▜██████████▛ ▟███████████▛ CPU: BCM2837 (4) @ 1.20 GHz
▟███▛ ▟▙ ▟███▛ Memory: 281.50 MiB / 893.14 MiB (32%)
▟███▛ ▟██▙ ▟███▛ Swap: Disabled
▟███▛ ▜███▙ ▝▀▀▀▀ Disk (/): 9.51 GiB / 14.47 GiB (66%) - ext4
▜██▛ ▜███▙ ▜██████████████████▛ Local IP (wlan0): 192.168.0.163/24
▜▛ ▟████▙ ▜████████████████▛ Locale: en_US.UTF-8
▟██████▙ ▜███▙
▟███▛▜███▙ ▜███▙
▟███▛ ▜███▙ ▜███▙
▝▀▀▀ ▀▀▀▀▘ ▀▀▀▘
Snapshot age
The capture above is from 2025-02-04 (the old nixos-hardware raspberry-pi-4
image). octopi was reflashed on 2026-06-26 onto the nixos-raspberrypi
rpi-3 layout with the cached linux-rpi kernel; treat the numbers above as
historical colour.
Physical constraints#
- Raspberry Pi 3 Model B Rev 1.2, 1 GB RAM, no swap, 2.4 GHz-only
BCM43430 Wi-Fi on
brcmfmac. - Built-in Ethernet is USB-attached and enumerates as
enu1u1(notend0/eth0).networking.interfacesis force-cleared so systemd does not wait 90 s for theeno1the shared core module declares. - Power it from a real 5 V / 2.5–3 A supply, never a dock or hub USB port.
Undervoltage produces an escalating ladder that looks like a driver bug: first
Wi-Fi associates but the board hangs within ~20 s under transmit, then
wlan0stops appearing at boot withbrcmf_sdio_verifymemory: Downloaded RAM image is corrupted. That is a brownout signature (hwmon: Undervoltage detected!indmesg), not firmware. - ClamAV stays off (above). Docs, man pages, and glances are off for the same reason on both Pis.
Wi-Fi: the real root causes#
The long-running “wlan0 will not associate (status_code=16)” was not
memory starvation (it failed with 700 MiB free). Two fixes, both in
hosts/x86_64-nixos/octopi/default.nix:
- NixOS injects a global
pmf=1intowpa_supplicant.conf; this Pi’sbrcmfmacFullMAC firmware mishandles PMF and every association dies atConnect event (status=16). A per-networkieee80211w=0overrides it (the AP advertises no MFP, so nothing is lost). WPA2-Personal is forced because WPA3/SAE never associates on this chip. wpa_supplicant-wlan0.serviceruns as the unprivilegedwpa_supplicantuser (nixpkgs hardening), so the sopswifisecret must beowner = "wpa_supplicant"or the PSK file is unreadable and there is no key to associate with.
haxo carries the same two workarounds.
Deploying changes#
- Incremental changes go over the network, never by reflash:
nh os switch . -H octopi --target-host tsunami@<lan-ip>(use the LAN address; the Tailscale name is unreliable right after a reflash). - Reflash only for bootloader or partition changes.
switch-to-configurationcannot repartition an SD card. The nixos-raspberrypi layout uses a separate FAT/boot/firmwarepartition plus u-boot; switching across that boundary fails on a missing/boot/firmware, and if youmkdirit by hand u-boot writes firmware onto the ext4 root — which the Pi GPU never reads at power-on. The board comes up with no ping. That is how octopi was bricked once (2026-06). - Recovery: pull the SD card,
just flash-octopi(decrypts the host key from sops, builds the image with thenixos-raspberrypi.cachix.orgsubstituter so the kernel is a cache hit, flashes it), reinsert, boot. - After any reflash, Tailscale needs a fresh auth key. A flash wipes
tailscale state;
tailscale-autoconnectre-registers with the sopstailscale/auth-key, and a stale key fails withinvalid key: API key does not exist, leaving the node “Logged out” — which looks exactly like the Pi never came back if you only reach it by its tailnet name. Mint a reusable, tagged key in the Tailscale admin console,sops setit, rebuild. One-time fallback over the LAN:sudo tailscale up --ssh. Tailnet Lock then also needstailscale lock signfrom mokou (Adding a Host). - Do not “fix”
normaliseClassblind.modules/flake/nix/default.nixnever mapsrpi→nixos, so octopi lacksmodules/flake/nix/nixos.nix(experimental-features, substituters,nh, distributed builds). The host setsnix.settings.experimental-featuresitself as a workaround. Repairing the lookup changes octopi’s closure — verify the rpi kernel still substitutes (nix build --dry-run …octopi…toplevelshows nothinglinux-rpiunder “will be built”) before flashing.