- Remove duplicate firewall include_role from base role (#18)
- Move remote_user from [ssh_connection] to [defaults] in ansible.cfg (#20)
- Add set -euo pipefail to run.sh (#21)
- Delete orphaned playbook_handlers.yml (#22)
- Fix changed_when: true in debian tasks (#23)
- Add tailscale_authkey env var lookup with TAILSCALE_KEY fallback (#25)
- Document -K requirement in bootstrap.yml (#26)
- Replace bare ansible_host=mail/git with IP addresses (#27)
- Update findings.md
- Convert ~290 short module names to FQCNs across all roles
- Change become: yes/no to become: true/false, gather_facts: no to false
- Remove deprecated inject_facts_as_vars from ansible.cfg
- Add missing task names to import_tasks/include_role calls
- Add become: yes to librenms clone task (partial-become fix)
- Add pipefail to risky shell command in udp-gro-fix.yml
- Quote all octal mode values
- Harden .ansible-lint with production profile and empty skip_list
- Update findings.md with all fixes
- grafana role: empty grafana_admin_password by default, and only emit
admin_password into grafana.ini when the var is set. Previously the
default 'admin' was rewritten on every run, clobbering passwords
rotated via the Grafana UI.
- bootstrap.yml: probe for sudo state before attempting su-as-root.
The first play was using become_method=su unconditionally; on hosts
where graham already has passwordless sudo (or where -K isn't passed),
ansible blocked indefinitely waiting for a root password prompt.
Now the install-via-su task only runs when sudo is actually missing,
and the python3 task uses sudo when available.
Also bring in latest microwaveprop dashboard tweaks.