From 99ba0ed52bd5cdca3878aba16df8bcd3e2a9503e Mon Sep 17 00:00:00 2001 From: beatzaplenty Date: Wed, 29 Jul 2026 10:41:03 +1000 Subject: [PATCH] docs: add beszel agent setup guide Documents how to wire beszel-agent into any flake build: the two-module split (enable-agent.nix in build types, host-token.nix in host files), sops secret creation, hub pairing flow, and optional EXTRA_FILESYSTEMS / Docker monitoring knobs. Co-Authored-By: Claude Sonnet 4.6 --- docs/beszel.md | 192 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 docs/beszel.md diff --git a/docs/beszel.md b/docs/beszel.md new file mode 100644 index 0000000..67f4962 --- /dev/null +++ b/docs/beszel.md @@ -0,0 +1,192 @@ +# Beszel agent + +[Beszel](https://github.com/henrygd/beszel) is the monitoring dashboard used +in this LAN. The hub runs as a Docker container on `docker.sweet.home` (port +`vars.ports.beszelHub`, 8090). Each monitored NixOS host runs a +`beszel-agent` that connects back to the hub. + +This document explains how to wire beszel-agent into any build in the flake. + +--- + +## How it is split across modules + +There are two modules and they have separate jobs: + +| Module | What it does | Where it goes | +|---|---|---| +| `modules/beszel/enable-agent.nix` | Enables the systemd service, sets `HUB_URL`, fixes upstream StateDirectory bug | **Build type** (`modules/build-types/*.nix`) | +| `modules/beszel/host-token.nix` | Declares the sops secret + env-file template that holds `TOKEN` | **Host file** (`hosts//host.nix`) | + +`KEY` (the hub's public key for this agent slot) is a plain string set +directly on the host under `services.beszel.agent.environment.KEY` — it comes +from the hub UI, not from sops, so it belongs in the host file rather than a +secret. + +--- + +## Adding beszel to a new build type + +Open `modules/build-types/.nix` and add `../beszel/enable-agent.nix` to +the `imports` list: + +```nix +imports = [ + ../beszel/enable-agent.nix + # ... other imports +]; +``` + +That is the only change needed at the build-type level. The module sets: +- `services.beszel.agent.enable = true` +- `HUB_URL` pointing at `docker.sweet.home:8090` +- a persistent `StateDirectory` for the hub-pairing fingerprint + +--- + +## Wiring the host file + +Every host whose build type includes `enable-agent.nix` needs two things in +its `hosts//host.nix`: + +### 1 — Import `host-token.nix` + +```nix +imports = [ + (import ../../modules/beszel/host-token.nix { + name = ""; # must match the sops secret file name below + sopsFile = ../../secrets/.yaml; + }) +]; +``` + +This creates a sops-managed env file at runtime containing `TOKEN=` and +passes it to the agent via `environmentFile`. The `name` argument also becomes +the sops template name (`-beszel.env`), so it must be unique per host. + +### 2 — Set `KEY` once the hub has paired the agent + +```nix +services.beszel.agent.environment = { + KEY = "ssh-ed25519 AAAA..."; +}; +``` + +`KEY` is the hub's SSH public key for this agent slot — copy it from the hub +UI after the agent first connects (see "Pairing with the hub" below). + +Until the hub has been paired, leave `KEY` commented out or omit it. The agent +will still start and appear in the hub as an unpaired entry; fill in the key +after that first connection. + +--- + +## Adding the sops secret + +The `beszel-token` value in `secrets/.yaml` is the token the agent +uses to authenticate to the hub. To add it for a new host: + +1. Decrypt and edit the host's secrets file: + ```sh + sops secrets/.yaml + ``` +2. Add the token: + ```yaml + beszel-token: + ``` +3. Save and close — sops re-encrypts the file on exit. + +If the host does not yet have a `secrets/.yaml`, create one using +the same sops recipients as the other secrets files (check `.sops.yaml`), or +run `scripts/secrets/sync-host-keys.sh ` first so the host's own +SSH key is already a valid recipient. + +The token is found in the beszel hub under **Settings → Keys** or when you +add a new system via the hub UI. + +--- + +## Optional: monitoring extra filesystems + +To have the agent report disk usage for a mount point that is not the root +filesystem, add `EXTRA_FILESYSTEMS` in the host file alongside `KEY`: + +```nix +services.beszel.agent.environment = { + KEY = "ssh-ed25519 AAAA..."; + EXTRA_FILESYSTEMS = "/mnt/data"; # colon-separated if more than one +}; +``` + +The `server` host uses this to expose the ZFS data pool: + +```nix +EXTRA_FILESYSTEMS = "${vars.storageRoot}/${vars.nfsShares.dockerVolumes.subpath}"; +``` + +--- + +## Optional: monitoring Docker containers + +The `enable-agent.nix` module has a commented-out line for Docker monitoring: + +```nix +#DOCKER_HOST = "tcp://docker-socket-proxy:2375"; +``` + +Uncomment it if the host runs docker-socket-proxy and you want per-container +stats in the hub. Hosts that do not run Docker should leave this commented out. + +--- + +## Pairing with the hub + +1. Deploy the host with `host-token.nix` imported and `enable-agent.nix` + present in the build type. Leave `KEY` unset 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 with the + hub. + +--- + +## Example: complete host file + +For reference, `hosts/tor-relay/host.nix` is the minimal case — one +filesystem, no Docker, LXC platform: + +```nix +{ vars, ... }: +{ + imports = [ + (import ../../modules/beszel/host-token.nix { + name = "tor-relay"; + sopsFile = ../../secrets/tor-relay.yaml; + }) + ]; + + networking = { ... }; + + services.beszel.agent.environment = { + KEY = "ssh-ed25519 AAAA..."; + }; + + system.stateVersion = "26.05"; +} +``` + +`hosts/server/host.nix` is the fuller case — extra filesystem path, debug +logging: + +```nix +services.beszel.agent.environment = { + KEY = "ssh-ed25519 AAAA..."; + EXTRA_FILESYSTEMS = "${vars.storageRoot}/${vars.nfsShares.dockerVolumes.subpath}"; + LOG_LEVEL = "debug"; +}; +```