Myon#

Myon is a small BuyVM (Las Vegas) KVM slice — 1 GB RAM, 20 GB disk — whose only job is to be the tailnet exit node (100.70.92.129). It is not a cache or builder. Config: hosts/x86_64-nixos/myon.

It advertises the exit node via tsunaminoai.tailscale.advertiseExit = true (server routing + --advertise-exit-node); clients such as ereshkigal consume it with useExit.

Why the install is unusual#

The 1 GB slice OOMs any RAM-disk installer — the installer ISO and nixos-anywhere’s kexec both load a root tmpfs into memory and run out before the closure finishes writing to disk. So myon is installed by building its closure on a real builder and copying it over, which keeps almost nothing in myon’s RAM.

Its sops-nix age identity is its existing ed25519 SSH host key (modules/nixos/security/pubkeys/myon.pub, already a recipient in .sops.yaml), so as long as /etc/ssh/ssh_host_ed25519_key is preserved through the install, sops-nix decrypts on first boot with nothing to bootstrap.

Install runbook — what actually worked (2026-08-07)#

The general shape held (no kexec/ISO installer; closure built on a builder, pushed to the box, switch-to-configuration boot), but the details differed from the plan in ways worth keeping:

  1. Getting in: the old DebOps/Ubuntu install was fully locked out (console passwords unknown, and even with a key in authorized_keys, two hardening layers rejected SSH):
    • pam_access with accessfile=/etc/security/access-sshd.conf denied root from any origin not on its list (“Access denied by PAM account configuration” — connection closes after the key is accepted).
    • a ferm xt_recent SSH rate limiter (ipt-recent-ssh-new in dmesg) REJECTed bursts of connections — and re-armed on every retry, so probing kept the ban alive. iptables -I INPUT -s <src> -p tcp --dport 22 -j ACCEPT + flushing /proc/net/xt_recent/* fixed it. Recovery was via the BuyVM rescue ISO (Debian Live): mount /dev/vda1, add the key, set a root password for console fallback, patch PAM.
  2. Copying the closure: nix copy --to ssh:// from mokou kept dying mid-stream on the old box. What worked: push the closure to ereshkigal’s binary cache (it already had it as the builder), then pull FROM myon over tailscale HTTP under systemd-run: nix-store -r <toplevel> --option extra-substituters http://100.82.7.19 --option require-sigs false.
  3. Multi-user Nix (--daemon) installed fine on the 1 GB box (root can’t run the single-user installer); symlink /nix/var/nix/profiles/default/bin/nix* into /usr/local/bin so non-interactive SSH finds nix-store.
  4. ⚠️ NIXOS_LUSTRATE does NOT work with systemd stage-1 (boot.initrd.systemd.enable = true, this flake’s default): the classic stage-2 move never runs, and NixOS boots cohabiting with the old distro — leftover units collide and the console /bin/login is broken. The fix is a manual lustrate from the rescue ISO: move everything except /nix, /boot, /swapfile, and mountpoint dirs into /old-root; recreate a skeleton (etc with a NIXOS marker, root, var/lib, proc, sys, dev, run, tmp 1777); restore etc/ssh, var/lib/tailscale, and root/.ssh/authorized_keys from /old-root; reboot.
  5. Preserving /var/lib/tailscale matters as much as /etc/ssh: the node rejoined with the SAME identity — same tailnet IP 100.70.92.129 (which the netns-exit module targets), still approved as an exit node, and still signed under Tailnet Lock — zero admin-console work post-install.

After reboot: nixos-version, systemctl --failed (expect none), secrets under /run/secrets, tailscale status (same IP, advertising), and from ereshkigal ip netns exec vpn curl -4 ifconfig.me45.61.186.219.

/old-root (the old Ubuntu system, ~10 GB) can be deleted after a soak period.

Ongoing#

Once NixOS is up, deploy changes normally: build on a builder and nix copy + switch-to-configuration, or nix run .#deploy -- .#myon if the low-RAM constraint allows the deploy-rs path. Admin access is over Tailscale (tailscale ssh); public port 22 stays open key-only as a fallback and can be tightened to specific source IPs later.

  • Media — the acquisition netns exits through this host.
  • Deployment — closures are pushed here, never built on-box.