Ansible playbooks to deploy Beszel monitoring across the makerspace infrastructure.
- Hub: Runs on the Proxmox laptop (Tailscale), accessible at port 8090
- Agents: Lightweight containers on Debian/Ubuntu VMs, listening on port 45876
- Connection: Hub SSHs into agents (not the other way around)
Install Ansible and pre-commit:
# Arch Linux
sudo pacman -S --needed ansible pre-commit
# Debian / Ubuntu
sudo apt update && sudo apt install -y ansible pre-commitThen enable the git hooks (secret detection, YAML linting, and a guard that refuses to commit/push an unencrypted vault — this repo is public):
pre-commit install --hook-type pre-commit --hook-type pre-pushYou also need:
ansible-vaultpassword in.vault_pass- SSH access (as root) to all target hosts
# Deploy the hub
ansible-playbook playbooks/deploy-hub.yaml
# Copy the SSH public key from hub UI → "Add System" dialog
ansible-vault edit inventory/group_vars/all.yaml
# Set beszel_hub_key to the copied key
# Deploy agents
ansible-playbook playbooks/deploy-agents.yaml-
Add the host's address to
inventory/group_vars/all.yaml(vault-encrypted):ansible-vault edit inventory/group_vars/all.yaml
Add an entry under
host_addresses. -
Add the host to
inventory/hosts.yamlunder theagentsgroup:new-host: ansible_host: "{{ host_addresses['new-host'] }}"
-
Deploy:
ansible-playbook playbooks/deploy-agents.yaml --limit new-host -
Register the host in the Beszel hub UI (hostname + port 45876).
Beszel sends alerts via shoutrrr URLs, configured in the hub
UI (Settings → Notifications); the alerts themselves (status/down, CPU, memory, disk) are
enabled per system. The notification URLs are recorded in the vault (beszel_notify_*,
beszel_signal_apprise_url) so they are not lost.
Not a shoutrrr service — Beszel's built-in email uses the PocketBase SMTP server. Log in to
PocketBase at <hub>/_/ (superuser = beszel_admin_email / beszel_admin_password; reset with
docker exec beszel /beszel superuser upsert <email> <password>), go to Settings → Mail,
enable the SMTP server, and send a test email. Then toggle Email on per-system alerts; mail is
sent to each user's account email. SMTP creds live in PocketBase's DB, not the vault.
Supported natively by shoutrrr. Convert a Discord webhook
https://discord.com/api/webhooks/<id>/<token> into:
discord://<token>@<id>
The generic:// URL has been removed from Settings → Notifications, so no Signal alerts are
sent. The apprise-api sidecar is still deployed while beszel_signal_apprise_url is set in the
vault; unset it to drop the sidecar. To re-enable, re-add the URL below in the UI.
shoutrrr has no Signal service, so the hub role runs an apprise-api sidecar — deployed only
when beszel_signal_apprise_url is set in the vault. deploy-hub.yaml starts it next to the hub
and seeds it with the Apprise Signal URL under the config key beszel. Beszel then posts to it
with a generic webhook:
generic://apprise:8000/notify/beszel?disabletls=yes&template=json&messagekey=body
apprise:8000— the sidecar, reached by container name on the hub's compose network.disabletls=yes— this hop is plain HTTP but never leaves the Pi (container-to-container) and carries only the alert text, no credentials.template=json&messagekey=body— builds{"title": ..., "body": ...}, which apprise-api requires.
beszel_signal_apprise_url is an Apprise Signal URL
— scheme signals://, then HTTP basic-auth credentials, the bridge host, a +<from> number, and a
group.<id> recipient — pointing at the makerspace signal-cli-rest-api bridge (on koorax, behind
traefik basic-auth). It lives only in apprise-api's config, never in Beszel.
Put every secret in inventory/group_vars/all.yaml — the single ansible-vault-encrypted file
(passwords, the hub SSH key, notification URLs, host addresses, Tailscale IPs). Edit it with
ansible-vault edit inventory/group_vars/all.yaml; reference its values from elsewhere (e.g.
hosts.yaml uses {{ host_addresses[...] }}) rather than copying secrets into other files.
This repo is public, so two hooks guard it:
- A
pre-commitandpre-pushhook refuses to commit/pushall.yamlunless it is ansible-vault encrypted (scripts/check-vault-encrypted.sh). detect-secretsscans for stray credentials in any other file.
The encryption check matches all.yaml by path, so keeping all secrets in that one file is what
keeps the guard effective — a secret placed in some other new file is only caught by
detect-secrets (pattern-based, not guaranteed). No hook catches everything: when in doubt, encrypt.