Skip to content

Playbooks and roles

A reference list. For what a playbook or a role is, see Ansible concepts.

Playbooks

Playbook Targets Restarts Use when
site.yml all services, if a role changed everyday; runs everything in order
preflight.yml monitored nothing before a first rollout, or to debug access
onboard.yml one host, --limit required alloy adding a new host; installs the collector and proves data landed centrally
collectors.yml monitored alloy, systemd-journald Alloy config, container metrics, journal caps
update-metrics.yml monitored nothing meaningful the apt/reboot exporter
dashboards.yml central only if the provider config changed Grafana dashboards; prunes ones deleted from git
central-alerting.yml central grafana-server alert rules, Matrix relay
unattended-upgrades.yml autoupdate nothing patching policy
docker-updates.yml autoupdate containers, only with run_now container update schedule
rotate-collector-password.yml central nginx, central alloy rotating collector auth
force-updates.yml monitored services, via apt installing pending updates NOW; never reboots

Common invocations

cd ansible

ansible-playbook playbooks/site.yml                        # everything
ansible-playbook playbooks/site.yml --limit rpi5           # one host
ansible-playbook playbooks/site.yml --limit pi             # one group
ansible-playbook playbooks/site.yml --limit 'lan_guests,!matrix'
ansible-playbook playbooks/site.yml --check --diff         # dry run
ansible-playbook playbooks/site.yml -e lan_use_jump_host=false   # from the LAN

central-alerting.yml restarts Grafana

Grafana reads provisioning only at startup, so the restart is the point. There is a short gap in evaluation and dashboards.

Roles

alloy_collector

Installs Alloy from the Grafana APT repo and owns /etc/alloy/config.alloy on every native install.

Does Note
Adds the Grafana APT repo and installs alloy state: present, never latest
Grants alloy the groups it needs systemd-journal, adm, docker
Runs Alloy as root on Docker hosts drop-in, for cAdvisor
Templates the config validate: alloy fmt %s: a bad config never lands
Writes /etc/alloy/.ansible-managed stops lxc-install.sh reverting it
Caps the journal where set journald_system_max_use
Waits for /-/ready proof of life, not just "started"

update_metrics

The apt and reboot textfile exporter, plus its timer.

Installs needrestart in non-interactive list mode ($nrconf{restart} = 'l'). Its default APT hook prompts during upgrades, which would hang an unattended run indefinitely.

The service carries [Install] WantedBy=multi-user.target so a reboot refreshes metrics immediately rather than waiting out the timer jitter.

unattended_upgrades

Applied by group membership only. Ends with a validation gate: unattended-upgrade --dry-run --debug, asserting no Traceback and no blacklisted package appears.

docker_updates

Compose-based container updates. Checks for a Docker socket (capability gate) and for Compose v2, then installs the script, unit and timer.

The docker_update_run_now variable triggers a supervised run and asserts the result.

matrix_webhook

The Grafana-to-Matrix relay: a system user, a venv, a systemd unit and a smoke test. Refuses to deploy with placeholder credentials.

grafana_alerting

Copies the committed alerting files, templates rules-availability.yaml from the inventory, injects secrets into Grafana's EnvironmentFile, restarts Grafana, then asserts one known uid per rules file.

Why one assert per file

Grafana aborts alerting provisioning for all files when any single one fails to parse, without failing startup. Probing one uid per file turns a silent total failure into a red play.

Ad-hoc commands

# what is the fleet made of
ansible-inventory --graph
ansible-inventory --host rpi5

# reachability
ansible monitored -m ping

# force a metrics refresh
ansible monitored -m systemd -a 'name=fleet-update-metrics.service state=started' --become

# check a timer everywhere
ansible monitored -m shell -a 'systemctl list-timers <unit> --no-pager' --become

# assert the never-reboot policy
ansible autoupdate -m shell \
  -a 'apt-config dump | grep "Unattended-Upgrade::Automatic-Reboot "' --become

Jinja eats Go template braces

docker ps --format '{{.Names}}' fails in -m shell because Ansible templates the argument first. Put the command in a file and use -m script instead.