Clone this repository
For self-hosted knots, clone URLs may differ based on your setup.
The whole system lives on one btrfs-on-LUKS-on-NVMe device, so downloads
and builds were starving latency-sensitive reads — launching a terminal
would freeze for seconds (PSI full IO pressure spikes, near-zero CPU/mem
pressure). Three independent fixes:
- mq-deadline scheduler on nvme0n1: the default "none" gives no read/write
fairness, so reads queued behind up to 1023 writes.
- vm.dirty_bytes/dirty_background_bytes as small fixed values instead of
the ratio defaults (~6/12 GB on 62 GB RAM) that caused multi-GB flush
bursts.
- bypassWorkqueues on the LUKS device to drop the kcryptd serialization
point (safe: AES-NI is present).
Assisted-by: Claude Code (claude-fable-5)
The clan bump removes the `clan.core.vars.generators.<name>.migrateFact`
option, which made every host fail to evaluate. Fact migration is a
one-time step that's long complete, so drop the now-removed option from
all generators (retiolum, syncthing, shadowsocks, hedgedoc, mycelium,
hotdog/orange containers, nextcloud, wiregrill, nix-serve, matrix).
Assisted-by: Claude Code (claude-fable-5)
Level 3 maps to per-packet Trace logging in tincr, which flooded
journald (tens of thousands of suppressed messages per minute) and
rotated all other units' logs out of the journal within hours,
leaving nothing to debug the whatsapp bridge with.
Assisted-by: Claude Code (claude-fable-5[1m])
Outgoing messages went unbridged silently from 2026-05-28 to 2026-06-08
(WhatsApp rejecting sends from the outdated client; fixed by the bridge
update) and no error ever reached the client. Positive per-message
confirmation makes a broken send path visible.
Assisted-by: Claude Code (claude-fable-5[1m])
simple-nixos-mailserver now stores per-user Sieve scripts in each user's
Dovecot home (~/sieve, active link ~/.dovecot.sieve) instead of the old
global /var/sieve, and asserts stateVersion >= 5 when enableManageSieve is
set. Existing scripts were migrated with migration #5 on neoprism.
Assisted-by: Claude Code (claude-opus-4-8[1m])
Run an n2n v3 supernode and point n2n.lassul.us at neoprism.
- Listens on UDP 7654 (main n2n protocol) and TCP 7654 (aux listener used
by edges started with -S2 when their network blocks UDP); both opened in
the firewall.
- Starts as root: the supernode unconditionally drops privileges to nobody
(uid/gid 65534) and aborts if the setuid() fails, so DynamicUser does not
work. It ends up running as uid 65534 with the remaining hardening.
- Sets the federation name with -F krebs (n2n prepends '*', yielding the
federation community '*krebs') to avoid the default '*Federation', which
n2n warns is for testing only. This only scopes supernode-to-supernode
federation, not the community (-c) edges use.
Assisted-by: Claude Code (claude-opus-4-8[1m])
Firefox started from the systemd user manager (firefox.service) only got
DISPLAY but not XDG_SESSION_TYPE. With DISPLAY set and XDG_SESSION_TYPE
unset, its WebRTC capturer takes the X11/XWayland screencast path, which
captures a black screen under sway. Exporting XDG_SESSION_TYPE=wayland
makes it use the PipeWire portal instead, fixing screen sharing.
Assisted-by: Claude Code (claude-opus-4-8[1m])
The hardcoded `export SWAYSOCK=/run/user/$(id -u)/sway-ipc.sock` in
extraSessionCommands is ignored by sway >=1.11, which creates its own per-pid
socket (sway-ipc.$uid.$pid.sock). The dead path got baked into the firefox and
workspace-manager user services, so every swaymsg call failed and the extension
silently skipped tab restore on each workspace switch. Drop the export and let
the existing import-environment propagate the real socket sway advertises.
Also:
- workspace-menu: "Restore tabs" used pkgs.firefox (upstream stable) instead of
the wrapped Dev Edition daemon, launching a separate browser/profile
- workspace-tabs: never overwrite a saved workspace with an empty tab list, so
the transient blank window after a Firefox restart can't wipe real tabs
Assisted-by: Claude Code (claude-opus-4-8[1m])