Playbooks¶
site.yml — Master playbook¶
Runs all host-specific playbooks in sequence via import_playbook. This is the standard entry point for a full configuration apply.
Execution order (current as of 2026-05-05):
proxmox-host.yml→ proxfoldarrstack.yml→ arrstackplex.yml→ plexpbs.yml→ pbs (Phase 5A)beszel.yml→ beszel (Phase 5B)n8n.yml→ n8n (Phase 5C)vintage.yml→ vintageedge.yml→ edge (Phase 5D)forgejo.yml→ forgejo (Phase 6A)control.yml→ control (local connection)auto-updates.yml→ fleet-wide unattended-upgrades pass
New host bring-up convention¶
For new hosts: prefer ansible-playbook playbooks/site.yml --limit <newhost> over running the per-host playbook directly (playbooks/<host>.yml).
Per-host playbooks intentionally exclude the fleet-wide policy plays at the bottom of site.yml (auto-updates.yml, today; future cross-cutting roles likely too). Bringing up via the per-host playbook leaves the new host outside fleet policy until a human notices — typically the daily drift check the next morning, which is the safety net but adds noise.
site.yml --limit <newhost> runs the same per-host stages plus the fleet plays scoped to the new host. Same blast radius as the per-host run, plus the policy. Verified clean during the Phase 6A.1 reconcile (2026-05-05).
The single-source-of-policy structure (each fleet-wide role in its own hosts: all play imported once at the foot of site.yml) is kept deliberately — folding auto_updates into per-host playbooks or into common would scatter policy review across N files for a one-line saving on bring-up.
Host playbooks¶
proxmox-host.yml¶
Configures the Proxmox VE host. Roles apply in this order (per roles/proxmox orchestration):
| Role | Purpose |
|---|---|
| proxmox | deb822 repos, kernel pin, nouveau blacklist, sysctl migration, stash import, nasbackup CIFS, PBS client (pvesm add pbs), notification target |
| common | Timezone, locale, base packages, SSH keys, NTP |
| security | SSH hardening, Fail2ban |
| zfs | ARC tuning, pool health check, scrub timer, ZED Discord webhook |
| nfs | NFS server exports |
| nvidia | GPU driver, NVENC patch, persistence daemon, IPMI fan fix |
| nut | UPS monitoring (CyberPower PR1500ERT2U) |
| beszel_agent | Per-host metrics agent with SMART enabled |
arrstack.yml¶
Configures the Docker VM and deploys the media stack.
| Role | Purpose |
|---|---|
| common | Base config |
| security | SSH hardening, Fail2ban |
| nfs | NFS client mount (/stash) |
| docker | Docker CE installation |
| beszel_agent | Per-host metrics agent |
| arrstack | Compose file deployment, MediaBot setup |
nginx.yml¶
Configures the reverse proxy VM (NPM UI manages proxy rules).
| Role | Purpose |
|---|---|
| common | Base config |
| security | SSH hardening, Fail2ban |
| docker | Docker CE (for NPM + Hawser containers) |
| beszel_agent | Per-host metrics agent |
Hawser on this host is currently a pre-existing manual install (RO socket, monitor-only) — codification deferred to a future cycle. See the hawser role for the deferred-follow-up note.
plex.yml¶
Configures the Plex LXC container.
| Role | Purpose |
|---|---|
| common | Base config |
| security | SSH hardening, Fail2ban |
| beszel_agent | Per-host metrics agent |
| plex | Plex install, media symlink, GPU passthrough check |
pbs.yml¶
Configures the Proxmox Backup Server LXC. Roles apply on top of the standard baseline:
| Role | Purpose |
|---|---|
| common, security | Baseline |
| beszel_agent | Per-host metrics agent |
| pbs | PBS install, NFS datastore mount, prune/verify/GC schedules, API token |
beszel.yml¶
Configures the Beszel hub LXC.
| Role | Purpose |
|---|---|
| common, security | Baseline |
| beszel_hub | Hub install via upstream installer, systemd unit, listen port, Discord shoutrrr |
n8n.yml¶
Configures the n8n Docker host VM.
| Role | Purpose |
|---|---|
| common, security | Baseline |
| docker | Docker CE + overlay2 storage driver pin |
| beszel_agent | Per-host metrics agent |
| hawser | Dockhand remote-host agent (per-host vault token, RW socket, REQUEST_TIMEOUT=600s) |
vintage.yml¶
Configures the Vintage Story dedicated server LXC. Host-level only — VS install + mods are deliberately out of scope (see Vintage Story service page).
| Role | Purpose |
|---|---|
| common, security | Baseline |
| beszel_agent | Per-host metrics agent |
control.yml¶
Configures the Ansible control node LXC against itself via ansible_connection: local.
| Role | Purpose |
|---|---|
| common, security | Baseline |
| beszel_agent | Per-host metrics agent — adds the drift runner itself to observability |
auto-updates.yml¶
Fleet-wide unattended-upgrades pass that runs after the per-host playbooks. Wraps hifis.toolkit.unattended_upgrades. Security-only origins; Proxmox repo added on proxfold + pbs; hypervisor kernels blocklisted on proxfold; manual reboot with optional Discord nag for /var/run/reboot-required. See the auto_updates role page.
Common usage patterns¶
# Dry run — see what would change without applying
ansible-playbook playbooks/site.yml --check --diff
# Single host
ansible-playbook playbooks/site.yml --limit proxfold
ansible-playbook playbooks/site.yml --limit arrstack
# Single role across all hosts that support it
ansible-playbook playbooks/site.yml --tags security
# Single role on a single host
ansible-playbook playbooks/proxmox-host.yml --tags nvidia
# Health check only (no config changes)
ansible-playbook playbooks/arrstack.yml --tags health
Tags reference¶
| Tag | Role | What it does |
|---|---|---|
common |
common | All base config tasks |
timezone |
common | Set system timezone |
locale |
common | Set system locale |
packages |
common | Install base packages |
ssh |
common, security | SSH key deployment + hardening |
ntp |
common | NTP/timesyncd config |
security |
security | All hardening tasks |
fail2ban |
security | Fail2ban install + config |
auto_updates |
auto_updates | All unattended-upgrades tasks |
proxmox |
proxmox | All proxmox host baseline tasks |
proxmox,repos |
proxmox | deb822 repo management only |
proxmox,kernel |
proxmox | Kernel pin only |
proxmox,nouveau |
proxmox | Nouveau blacklist only |
proxmox,sysctl |
proxmox | sysctl migration only |
proxmox,storage |
proxmox | stash import + nasbackup CIFS + PBS client only |
proxmox,notifications |
proxmox | Discord webhook target + match-all matcher only |
docker |
docker | All Docker tasks |
zfs |
zfs | All ZFS tasks |
zfs,tuning |
zfs | ARC config only |
zfs,health |
zfs | Pool health check only |
zfs,scrub |
zfs | Scrub timer config only |
zfs,zed |
zfs | ZED Discord webhook only |
nvidia |
nvidia | All GPU tasks |
nvidia,driver |
nvidia | Driver install only |
nvidia,nvenc |
nvidia | NVENC patch only |
nvidia,ipmi |
nvidia | IPMI fan fix only |
nvidia,lxc |
nvidia | LXC passthrough check only |
nfs |
nfs | All NFS tasks |
arrstack |
arrstack | All media stack tasks |
arrstack,compose |
arrstack | Deploy compose + env only |
arrstack,mediabot |
arrstack | MediaBot deploy only |
arrstack,health |
arrstack | Container health check only |
nut |
nut | All NUT tasks |
nut,install |
nut | Package install only |
nut,config |
nut | Render /etc/nut/* only |
nut,service |
nut | Enable/start services only |
pbs |
pbs | All PBS tasks |
pbs,install |
pbs | Package + datastore creation only |
pbs,config |
pbs | Schedules (prune/verify/GC) + token only |
beszel |
beszel_hub, beszel_agent | All Beszel tasks (hub or agent depending on host) |
beszel,install |
beszel_* | Installer-script tasks only |
beszel,config |
beszel_agent | SMART + extra-filesystems drop-ins only |
hawser |
hawser | All Hawser tasks |
plex |
plex | All Plex tasks |