This repository has been archived on 2026-07-30. You can view files and clone it. You cannot open issues or pull requests or push a commit.
beatzaplentyandClaude Sonnet 4.6 7779f3e137
Check NixOS configurations / eval-hosts (pull_request) Successful in 10m18s
fix: prefix Proxmox commands with sudo for non-root SSH user
PROXMOX_SSH_USER was changed from root to wayne, but all remote pvesh/qm/pct
invocations assumed root. When run as a non-root user these commands fail with
ipcc_send_rec errors because they can't reach the pve-cluster IPC socket.

Adds a global sudo_prefix (empty when PROXMOX_SSH_USER=root, "sudo" otherwise)
and applies it to every remote Proxmox command in the script, including the
duplicate-host heredoc check, pvesh nextid, vmid existence checks, resource
destruction, and all create/start commands. Removes the now-redundant local
sudo_prefix definition that was previously only in the VM image build branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-23 08:47:00 +10:00
2026-07-20 17:49:35 +00:00
2026-07-23 08:38:36 +10:00
2026-07-23 06:59:37 +10:00
2026-07-22 01:36:32 +00:00
2026-07-22 01:36:32 +00:00
2026-07-21 20:07:30 +00:00
2026-07-21 23:48:06 +00:00
2025-07-16 13:33:23 +10:00
2025-07-16 03:22:31 +00:00

NixOS LAN Configurations

Flake-based NixOS configuration repository for Wayne's LAN servers and workstation.

Hosts

Targets are named <platform>-<buildtype>, generated from two orthogonal pieces composed in flake.nix:

  • Platforms (what it runs on): linode, proxmox, lxc, baremetal
  • Build types (what it's for): minimal, nix-cache, server, docker, gui, pxe-boot, tailscale-exit-node, tor-relay

Not every combination exists — pxe-boot has no linode variant, since PXE/DHCP/TFTP need LAN L2 adjacency that a Linode VPS doesn't have, tor-relay currently only exists as lxc-tor-relay, and baremetal currently only exists as baremetal-gui (the real gui-host hardware). The full list:

Target Purpose
linode-minimal Minimal NixOS host profile on a Linode VPS
proxmox-minimal Minimal NixOS host profile on Proxmox — previously the flat nix-minimal target
lxc-minimal Minimal NixOS host profile in a Proxmox LXC container
linode-nix-cache / proxmox-nix-cache / lxc-nix-cache Local Nix binary cache and remote builder — previously the flat nix-cache target
linode-server / proxmox-server / lxc-server Storage, NFS, backup, and monitoring exporter host — previously the flat server target
linode-docker / proxmox-docker / lxc-docker Docker host for the main container stack — previously the flat docker target
linode-gui / proxmox-gui / lxc-gui Cinnamon desktop workstation — previously the flat nixos target
baremetal-gui Same Cinnamon desktop workstation, on the real gui-host hardware — ZFS RAID0 root, systemd-boot
proxmox-pxe-boot / lxc-pxe-boot HTTP/iPXE boot asset host — previously the flat pxe-boot target
linode-tailscale-exit-node / proxmox-tailscale-exit-node / lxc-tailscale-exit-node Tailscale exit node
lxc-tor-relay Tor middle relay

Which variant of a given buildtype is actually deployed isn't tracked anywhere in this repo — that's live infrastructure state, not something a committed file can keep accurate, and it changes independently of the code. Check the Proxmox node itself, or /etc/flake-target on a running host (see below), if you need to know what's really out there right now. scripts/proxmox/create-proxmox-resource.sh's duplicate-host guard works the same way: it checks the Proxmox node directly rather than any file here. Real, production deployments live on pve1.sweet.home; there's a second node, pve-test.sweet.home, set aside purely for scratch/test resources — see scripts/env.sh (PVE1_HOST / PVE_TEST_HOST, and the --node/PROXMOX_HOST targeting they feed into) and CLAUDE.md's Proxmox section for which is which.

Each buildtype's hosts/<name>/host.nix carries the per-machine identity (hostname, hostId, per-machine secrets, system.stateVersion) that must stay fixed regardless of which platform it's built for — see flake-target-refactor-spec.md for the full rationale. Every deployed host stamps its own active target name into /etc/flake-target at build time, so nixos-rebuild switch --flake .#$(cat /etc/flake-target) always picks up the right one even after a platform migration changes the flake attribute name.

List hosts with:

nix eval --json .#nixosConfigurations --apply builtins.attrNames | jq -r '.[]'

Layout

Path Purpose
flake.nix Flake inputs, the mkTarget platform × build-type generator, and nixosConfigurations outputs
variables.nix Single source of truth for shared values (LAN domain/CIDR, hostnames, timezone, primary username, storage root, NFS share subpaths/mountpoints, service ports, ...) — passed to every module and Home Manager config as the vars argument via specialArgs/extraSpecialArgs
hosts/<name>/host.nix Per-machine identity: hostname, hostId, per-machine secrets, system.stateVersion
hosts/nixos/home.nix Workstation-specific Home Manager config (used by the gui build type)
modules/platforms/ Platform-specific config: virtualisation guest tools, boot method, hardware config (linode.nix, proxmox.nix, lxc.nix, baremetal.nix)
modules/build-types/ Build-type-specific config: what makes a system minimal/server/docker/gui/pxe-boot/nix-cache
modules/common/ Shared NixOS config, Home Manager, aliases imported by every host
modules/nix-cache/ Binary cache and remote builder client/server modules
modules/installer/ Auto-installer environment (ISO, also served as PXE netboot) — see docs/auto-installer.md
host-keys/ Gitignored, locally-generated SSH host keys for the auto-installer — see docs/auto-installer.md
docs/ Operational notes for cache, builders, lock updates, boot services, the auto-installer, and Proxmox image builds
scripts/ Codex setup, validation, host-key, release-bump, and Proxmox resource helpers

Validation

Safe validation commands for Codex and local review:

bash scripts/codex-setup.sh
bash scripts/codex-maintenance.sh

codex-maintenance.sh with no flags (what CI runs on every push/PR) scopes fmt-check/statix/eval to files changed against a base ref — fast, but only as thorough as the diff. For the full sweep (every host, every package, fmt-check and statix over the whole tree — slow, CI never runs this):

bash scripts/codex-maintenance.sh --full-check
bash scripts/codex-maintenance.sh --full-check --dry-run

For individual host evaluation:

nix eval .#nixosConfigurations.<host>.config.system.build.toplevel.drvPath --raw

Use nix build --dry-run --no-link when build planning is needed. Do not run deployment, install, disk formatting, mount, or reboot commands from automated review sessions.

Operations

  • Host rebuilds should consume the committed flake.lock.
  • Routine dependency updates should happen through the flake lock automation described in docs/flake-lock-automation.md.
  • nix-cache serves substitutes over HTTP and can act as a remote builder for client hosts.
  • pxe-boot serves iPXE boot files over HTTP from /srv/pxe.

Deploying a new host

Three different paths depending on target, none of them involving a manual nixos-rebuild switch from this repo:

  • Most hosts: boot the auto-installer, pick the target from its menu — see docs/auto-installer.md. Every menu target has a Disko config the installer formats unconditionally (docs/auto-installer.md's "Storage" section covers how this stays non-destructive for linode-*, whose disks Linode itself provisions ahead of time).
  • lxc-* targets: not installed at all — build a ready-to-run container tarball and pct create it as a CT template directly. docs/auto-installer.md covers why (and the installer's menu excludes them for the same reason).
  • proxmox-* targets: can alternatively be built as a standalone .raw disk image and attached to a new VM with no install step — see docs/proxmox-images.md.

scripts/proxmox/create-proxmox-resource.sh --type lxc|vm --host <name> automates either of the last two end to end (host-key registration, building the image directly on the Proxmox node itself, pct create/qm create), with --dry-run and a guard against duplicating an already-deployed host's identity. See its --help.

Security Notes

Do not commit tokens, private keys, live credentials, or new password hashes as plaintext. Secrets are managed with sops-nix: encrypted files live under secrets/, recipients (per-host age keys derived from each host's existing SSH host key, plus an admin key) are declared in .sops.yaml. To add or edit a secret:

nix-shell -p sops --run "sops secrets/<file>.yaml"

then reference it from a module via config.sops.secrets."<name>".path (or sops.templates for values that need to be embedded in a rendered config file, e.g. nix.conf's access-tokens). Never write a secret value directly into a tracked .nix file. A pre-commit hook (.githooks/, enabled via git config core.hooksPath .githooks, done automatically by scripts/codex-setup.sh) runs gitleaks protect --staged to catch mistakes before they're committed.

The auto-installer environment is the one deliberate exception to sops-nix-everywhere: it has a hardcoded login password instead (no stable per-boot host key for sops-nix to derive from on ephemeral media) — see "Host keys" in docs/auto-installer.md for why, and how the private keys it does pre-seed for target hosts stay out of git via the gitignored host-keys/ directory.

This repository's git history still contains secrets committed before this migration (see remove-sensetive-info-refactor.md) — those are being scrubbed and rotated separately; don't treat the repo as safe to make public until that's finished.

S
Description
No description provided
Readme MIT
17 MiB
Languages
Shell 64.5%
Nix 32.9%
Python 2.6%