From f22ff7db7967f09eb619f215c7656a2dab7a4485 Mon Sep 17 00:00:00 2001 From: beatzaplenty Date: Wed, 29 Jul 2026 12:37:54 +1000 Subject: [PATCH] refactor(beszel): move KEY and TOKEN fully into enable-agent.nix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KEY (hub's SSH public key) is now stored in variables.nix as beszelHubKey and set by enable-agent.nix — no host file ever needs to touch it. TOKEN was already universal; this removes the last per-host beszel config. Importing enable-agent.nix in a build type is now the only step needed to add a new host to beszel monitoring. Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 3 +- docs/beszel.md | 92 +++++++++------------------------ hosts/ha-server-1/host.nix | 3 -- hosts/ha-server-2/host.nix | 3 -- hosts/nix-cache/host.nix | 4 -- hosts/server/host.nix | 1 - hosts/tailscale-router/host.nix | 4 -- hosts/tor-relay/host.nix | 4 -- modules/beszel/enable-agent.nix | 1 + variables.nix | 5 ++ 10 files changed, 32 insertions(+), 88 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 6351261..983cade 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,8 +21,7 @@ machines when deployed. `modules/installer/common.nix` (the auto-installer's own root/nixos login — a deliberate, documented choice, see `docs/auto-installer.md`, not accidental tech debt) and **SSH public keys** in `variables.nix` - (`vars.adminSshKey`, `vars.remoteBuilderAuthorizedKeys`) plus per-host - `KEY` values for beszel-agent auth (see `docs/beszel.md`). Don't use the installer's hardcoded hash as a + (`vars.adminSshKey`, `vars.remoteBuilderAuthorizedKeys`, `vars.beszelHubKey`). Don't use the installer's hardcoded hash as a template for a *real* host — every other host uses sops-nix (`hashedPasswordFile`, see "Security Notes" in `README.md`). Flag any *new* secret-like string you encounter instead of committing it. diff --git a/docs/beszel.md b/docs/beszel.md index d52d490..b95d51f 100644 --- a/docs/beszel.md +++ b/docs/beszel.md @@ -14,13 +14,16 @@ Everything is handled by a single module: **`modules/beszel/enable-agent.nix`** — imported by a build type. It: - Enables `beszel-agent` - Sets `HUB_URL` to `docker.sweet.home:8090` -- Reads the universal `beszel-token` from `secrets/common.yaml` via sops and - passes it to the agent as `TOKEN` in an env file +- Sets `KEY` from `vars.beszelHubKey` (`variables.nix`) — the hub's SSH + public key, shared by every agent. Update `beszelHubKey` if the docker + host is ever rebuilt and the hub generates a new keypair. +- Reads the universal `beszel-token` from `secrets/common.yaml` via sops + and passes it to the agent as `TOKEN` in an env file - Fixes an upstream bug where the agent couldn't persist its hub-pairing fingerprint across restarts (adds a real `StateDirectory`) -The only thing a host file ever needs to add is `KEY` — the hub's public key -for that agent slot, which comes from the beszel hub UI after first pairing. +A host file needs no beszel configuration at all — just import the module +in the build type and add the system in the hub UI. --- @@ -36,30 +39,23 @@ imports = [ ]; ``` -That's the only build-type change required. +That's the only change required. The host file needs nothing. --- -## Wiring the host file +## Adding a new system to the hub -No `imports` are needed in the host file. Just set `KEY` once you've paired -the agent with the hub: - -```nix -services.beszel.agent.environment = { - KEY = "ssh-ed25519 AAAA..."; -}; -``` - -Leave `KEY` commented out until after the first pairing (see "Pairing with -the hub" below). +1. Rebuild and deploy the host with its build type importing `enable-agent.nix`. +2. Open the beszel hub (`http://docker.sweet.home:8090`). +3. Go to **Systems → Add system**, enter the host's IP and the default port + (45876). The agent will connect and the system will appear as active. --- ## One-time setup: add the token to `secrets/common.yaml` The universal token is stored once in the common secrets file, shared by all -agents. You only need to do this once, not per-host: +agents. Only needed once, not per-host: ```sh sops secrets/common.yaml @@ -67,26 +63,21 @@ sops secrets/common.yaml Add: ```yaml -beszel-token: +beszel-token: ``` -The token is found in the beszel hub under **Settings → Keys** or in the -"Add system" flow. - `secrets/common.yaml` is already a sops recipient for every host via their -SSH host keys, so no additional sops recipient setup is needed for hosts that -are already provisioned. +SSH host keys, so no additional sops recipient setup is needed. --- ## Optional: monitoring extra filesystems To report disk usage for a mount beyond the root filesystem, add -`EXTRA_FILESYSTEMS` alongside `KEY` in the host file: +`EXTRA_FILESYSTEMS` in the host file: ```nix services.beszel.agent.environment = { - KEY = "ssh-ed25519 AAAA..."; EXTRA_FILESYSTEMS = "/mnt/data"; # colon-separated for multiple paths }; ``` @@ -94,7 +85,10 @@ services.beszel.agent.environment = { The `server` host uses this to expose its ZFS data pool: ```nix -EXTRA_FILESYSTEMS = "${vars.storageRoot}/${vars.nfsShares.dockerVolumes.subpath}"; +services.beszel.agent.environment = { + EXTRA_FILESYSTEMS = "${vars.storageRoot}/${vars.nfsShares.dockerVolumes.subpath}"; + LOG_LEVEL = "debug"; +}; ``` --- @@ -112,44 +106,8 @@ stats. Hosts without Docker should leave it commented out. --- -## Pairing with the hub +## If the hub key changes -1. Deploy the host with its build type importing `enable-agent.nix`. Leave - `KEY` unset (commented out) for now. -2. Open the beszel hub (`http://docker.sweet.home:8090`). -3. Go to **Systems → Add system**. The new host should appear as an unpaired - entry — copy the `KEY` value shown there. -4. In `hosts//host.nix`, set: - ```nix - services.beszel.agent.environment.KEY = ""; - ``` -5. Rebuild and deploy the host. The agent will now pair permanently. - ---- - -## Example: complete host file - -Minimal case (`hosts/tor-relay/host.nix` — one filesystem, no Docker, LXC): - -```nix -{ vars, ... }: -{ - networking = { ... }; - - services.beszel.agent.environment = { - KEY = "ssh-ed25519 AAAA..."; - }; - - system.stateVersion = "26.05"; -} -``` - -Fuller case (`hosts/server/host.nix` — extra filesystem, debug logging): - -```nix -services.beszel.agent.environment = { - KEY = "ssh-ed25519 AAAA..."; - EXTRA_FILESYSTEMS = "${vars.storageRoot}/${vars.nfsShares.dockerVolumes.subpath}"; - LOG_LEVEL = "debug"; -}; -``` +If the docker host is ever rebuilt and beszel generates a new SSH keypair, +update `beszelHubKey` in `variables.nix` and rebuild all beszel-enabled hosts. +The new key is visible in the beszel hub under **Settings → Keys**. diff --git a/hosts/ha-server-1/host.nix b/hosts/ha-server-1/host.nix index f923f5d..1f90737 100644 --- a/hosts/ha-server-1/host.nix +++ b/hosts/ha-server-1/host.nix @@ -16,8 +16,5 @@ nameservers = [ vars.domainControllerIp ]; }; - # Set KEY after pairing this host with the beszel hub (see docs/beszel.md). - # services.beszel.agent.environment.KEY = ""; - system.stateVersion = "26.05"; } diff --git a/hosts/ha-server-2/host.nix b/hosts/ha-server-2/host.nix index 5dc038a..baccfea 100644 --- a/hosts/ha-server-2/host.nix +++ b/hosts/ha-server-2/host.nix @@ -16,8 +16,5 @@ nameservers = [ vars.domainControllerIp ]; }; - # Set KEY after pairing this host with the beszel hub (see docs/beszel.md). - # services.beszel.agent.environment.KEY = ""; - system.stateVersion = "26.05"; } diff --git a/hosts/nix-cache/host.nix b/hosts/nix-cache/host.nix index e886fb5..439985f 100644 --- a/hosts/nix-cache/host.nix +++ b/hosts/nix-cache/host.nix @@ -12,10 +12,6 @@ nameservers = [ vars.domainControllerIp ]; }; - services.beszel.agent.environment = { - KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG"; - }; - # Preserved from the pre-refactor `nix-cache` target — stateVersion must # never be bumped on an already-installed machine. system.stateVersion = "25.05"; diff --git a/hosts/server/host.nix b/hosts/server/host.nix index 775e451..3c58a39 100644 --- a/hosts/server/host.nix +++ b/hosts/server/host.nix @@ -14,7 +14,6 @@ }; services.beszel.agent.environment = { - KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG"; EXTRA_FILESYSTEMS = "${vars.storageRoot}/${vars.nfsShares.dockerVolumes.subpath}"; LOG_LEVEL = "debug"; }; diff --git a/hosts/tailscale-router/host.nix b/hosts/tailscale-router/host.nix index 9f3dae7..1608810 100644 --- a/hosts/tailscale-router/host.nix +++ b/hosts/tailscale-router/host.nix @@ -12,10 +12,6 @@ nameservers = [ vars.domainControllerIp ]; }; - services.beszel.agent.environment = { - KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG"; - }; - # No networking.hostId: only ZFS-touching hosts (server, docker) need one # for pool-import safety, and this host does neither. diff --git a/hosts/tor-relay/host.nix b/hosts/tor-relay/host.nix index 7e894ce..f8ce6ab 100644 --- a/hosts/tor-relay/host.nix +++ b/hosts/tor-relay/host.nix @@ -15,10 +15,6 @@ # No networking.hostId: only ZFS-touching hosts need one for pool-import # safety, and this host does neither. - services.beszel.agent.environment = { - KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG"; - }; - # A genuinely new host (not a pre-refactor carry-over), so it tracks the # flake's current nixpkgs release rather than being pinned to an older one. system.stateVersion = "26.05"; diff --git a/modules/beszel/enable-agent.nix b/modules/beszel/enable-agent.nix index 8e97657..1f207df 100644 --- a/modules/beszel/enable-agent.nix +++ b/modules/beszel/enable-agent.nix @@ -16,6 +16,7 @@ environment = { #DOCKER_HOST = "tcp://docker-socket-proxy:2375"; HUB_URL = "http://${vars.dockerHost}.${vars.homeDomain}:${toString vars.ports.beszelHub}"; + KEY = vars.beszelHubKey; }; }; diff --git a/variables.nix b/variables.nix index 9802a8a..0f6f9cd 100644 --- a/variables.nix +++ b/variables.nix @@ -40,6 +40,11 @@ # from scratch. nixCacheHostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICuHUxGNH6ei3BZD+EfZs3l4X8uJNcjQiOsM/G4yo4O/ lxc-nix-cache"; + # Beszel hub's SSH public key — used by every agent to authenticate the + # hub's incoming connection. Update if the docker host is ever rebuilt and + # the hub generates a new keypair. + beszelHubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG"; + # Public keys authorized to SSH in as remoteBuilderUser on the nix-cache # host (modules/nix-cache/server.nix) — one per client host that's allowed # to use it as a distributed builder.