refactor(beszel): move KEY and TOKEN fully into enable-agent.nix #98

Merged
beatzaplenty merged 1 commits from worktree-docs-beszel-guide into main 2026-07-29 02:38:19 +00:00
10 changed files with 32 additions and 88 deletions
+1 -2
View File
@@ -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.
+25 -67
View File
@@ -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: <token from the beszel hub UI>
beszel-token: <token from the beszel hub Settings → Keys>
```
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/<name>/host.nix`, set:
```nix
services.beszel.agent.environment.KEY = "<copied 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**.
-3
View File
@@ -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";
}
-3
View File
@@ -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";
}
-4
View File
@@ -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";
-1
View File
@@ -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";
};
-4
View File
@@ -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.
-4
View File
@@ -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";
+1
View File
@@ -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;
};
};
+5
View File
@@ -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.