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.
Files
nixos/docs/beszel.md
T
beatzaplentyandClaude Sonnet 4.6 99ba0ed52b
Check NixOS configurations / eval-hosts (pull_request) Successful in 10m37s
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 <noreply@anthropic.com>
2026-07-29 10:41:03 +10:00

5.4 KiB

Beszel agent

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/<name>/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/<type>.nix and add ../beszel/enable-agent.nix to the imports list:

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/<name>/host.nix:

1 — Import host-token.nix

imports = [
  (import ../../modules/beszel/host-token.nix {
    name = "<hostname>";            # must match the sops secret file name below
    sopsFile = ../../secrets/<hostname>.yaml;
  })
];

This creates a sops-managed env file at runtime containing TOKEN=<value> and passes it to the agent via environmentFile. The name argument also becomes the sops template name (<name>-beszel.env), so it must be unique per host.

2 — Set KEY once the hub has paired the agent

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/<hostname>.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:
    sops secrets/<hostname>.yaml
    
  2. Add the token:
    beszel-token: <token from the beszel hub UI>
    
  3. Save and close — sops re-encrypts the file on exit.

If the host does not yet have a secrets/<hostname>.yaml, create one using the same sops recipients as the other secrets files (check .sops.yaml), or run scripts/secrets/sync-host-keys.sh <target> 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:

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:

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:

#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/<name>/host.nix, set:
    services.beszel.agent.environment.KEY = "<copied 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:

{ 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:

services.beszel.agent.environment = {
  KEY = "ssh-ed25519 AAAA...";
  EXTRA_FILESYSTEMS = "${vars.storageRoot}/${vars.nfsShares.dockerVolumes.subpath}";
  LOG_LEVEL = "debug";
};