infra/ansible/findings.md
Graham McIntire 5e8823f4dd
fix: resolve all logic bugs
- 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
2026-06-04 14:43:06 -05:00

8.3 KiB

Ansible Repo Audit — Findings

Generated 2026-06-04 after auditing ~70 role files, 7 playbooks/configs, 21 host_vars, and 50+ templates.

Completed Fixes

  • Removed all Forgejo references — deleted roles/forgejo/, removed forgejo play from playbook.yml, removed forgejo_servers group from hosts, removed forgejo vars from host_vars/git.mcintire.me.yml, removed docker-mirror CNAME from DNS zone.
  • Fixed hardcoded SSH private key paths — replaced all 20 occurrences of /Users/graham/.ssh/id_ed25519 and /Users/graham/.ssh/ansible with ansible_ssh_private_key_file: "{{ lookup('env', 'ANSIBLE_SSH_PRIVATE_KEY_FILE') | default('~/.ssh/ansible', true) }}" in group_vars/all/all.yml. Set ANSIBLE_SSH_PRIVATE_KEY_FILE env var to override.
  • Fixed community.mysql collection — added to requirements.yml and installed (fixes monitor role crash).
  • Removed broken setup-user Makefile target — referenced non-existent setup-user.sh.
  • Fixed tracking issuesgit rm --cached for 5 .DS_Store files and .vscode/settings.json; added .ansible/ to .gitignore.
  • Fixed stale documentation — updated CLAUDE.md and README.md to reflect actual playbook structure, roles, inventory groups, and collections.
  • Fixed non-FQCN module references — converted ~290 short module names (apt:, service:, template:, etc.) to FQCNs (ansible.builtin.apt:, etc.) across all roles and playbooks.
  • Fixed become:/gather_facts: boolean formsbecome: yesbecome: true, gather_facts: nogather_facts: false in all plays.
  • Removed deprecated inject_facts_as_vars from ansible.cfg.
  • Added missing task namesimport_tasks/include_role calls in base/tasks/main.yml and general/tasks/main.yml now have descriptive names.
  • Fixed partial-become bug — added become: yes to librenms clone task.
  • Added pipefail to risky shell command in udp-gro-fix.yml.
  • Quoted octal mode valuesmode: 0755mode: '0755', etc.
  • Hardened .ansible-lint config — set profile: production, added exclude paths, removed all skip_list entries.
  • Added defaults for 4 undefined template variablesntpserver, template_run_date, deb_mirror, sshd.* all have safe fallbacks now.
  • Removed Alpine role referenceinclude_role: name=alpine in roles/base/tasks/main.yml was pointing to a non-existent role.
  • Fixed SSH -t flag placement — Moved before hostname in both bootstrap-reboot and reboot Makefile targets.
  • Fixed general.yml referencesbootstrap-network, run-all, qc-web Makefile targets now use playbook.yml; removed qc-web target (qc_web group doesn't exist).
  • Removed all Docker targetsbuild-*, run-*, push-*, base-*, latest, local, clean, dirs — no Dockerfile at repo root ever existed.
  • Fixed install-collections — removed references to deleted roles/requirements.yml and scripts/fix-deprecated-imports.sh.
  • Deleted orphaned host_vars/db.aprs.me.yml — host not in inventory; db.w5isp.com already serves as the single database server.
  • Deleted unreferenced roles — removed icinga2-container/, debug/, mailcow/, syncthing/ (no plays applied them).
  • Removed unused Galaxy dependencies — deleted geerlingguy.docker, geerlingguy.kubernetes from requirements.yml; deleted entire roles/requirements.yml (graylog2.graylog, bertvv.bind, artis3n.tailscale); merged netbox.netbox into root file.
  • Cleaned fact_cache — removed 56 stale files.
  • Removed unused inventory groupshome_cluster and dns_servers (defined but never targeted).

🔴 Security (fix immediately)

# Issue Location
1 Plaintext secrets in .envrc — Tailscale auth key, PowerDNS API key, PostgreSQL password, Proxmox root password in plaintext on disk. Use ansible-vault or a secrets manager. .envrc:3,6,9,14
2 Hardcoded cloud-init passwordcipassword in plaintext for BIND9 VM. Anyone with repo access can SSH in as debian. playbook.yml:159
3 Hardcoded SSH public key — Same ed25519 key in playbook, setup-host.sh, and base/files/ansible.pub. Not vaulted. Rotate + move to vault. playbook.yml:106, setup-host.sh:17, base/files/ansible.pub

🔴 Broken Infrastructure (will fail at runtime)


🔴 Runtime Crashes (undefined template variables)

All template variable defaults have been added. See Completed Fixes for details.


🟡 Previously Fixed

# Issue Fix
4 Hardcoded Forgejo runner token in host_vars Deleted with forgejo cleanup
7 setup-user.sh doesn't exist Removed broken Makefile target
11 community.mysql.mysql_db module not found Added community.mysql to requirements.yml and installed
45 5 .DS_Store files tracked by git git rm --cached
46 .vscode/settings.json tracked despite gitignore git rm --cached
47 .ansible/ directory not in .gitignore Added to .gitignore
48 Stale CLAUDE.md (references general.yml, missing roles, wrong commands) Rewritten with accurate playbooks, roles, collections, commands
49 Stale README.md (wrong directory tree, incomplete groups) Rewritten with accurate structure and inventory groups
29 Non-FQCN module references (~290 instances) Converted all to FQCNs across all roles and playbooks
30 Unquoted octal mode values (9 instances) All quoted with single quotes
31 become: yes / gather_facts: no Changed to become: true / gather_facts: false
32 inject_facts_as_vars deprecated Removed from ansible.cfg
33 Missing task names on import_tasks/include_role Added descriptive names
34 partial-become bug in librenms Added become: yes
35 risky-shell-pipe without pipefail Added set -o pipefail
36 Minimal .ansible-lint config Set profile: production, added exclude paths, empty skip_list
37 Unreferenced icinga2-container/ and debug/ roles Deleted
38 Unreferenced mailcow/ and syncthing/ roles Deleted
39 geerlingguy.docker and geerlingguy.kubernetes never used Removed from requirements.yml
40 graylog2.graylog and bertvv.bind never used Deleted roles/requirements.yml
41 collections/requirements.yml redundant Merged into root file, deleted
42 Stale fact_cache files (56 files) Deleted all
43 home_cluster and dns_servers groups never targeted Removed from hosts
9 alpine role referenced but doesn't exist Removed include_role from roles/base/tasks/main.yml
5 general.yml does not exist Makefile targets updated to use playbook.yml; docker/build targets removed
6 No Dockerfile at repo root All docker/build/push targets removed from Makefile
8 geerlingguy.postgresql not in requirements.yml Added with version pin 3.4.3
10 Orphaned host_vars/db.aprs.me.yml with no inventory entry Deleted (superseded by db.w5isp.com)
12-15 Undefined template variables (ntpserver, template_run_date, deb_mirror, sshd.*) Added `
-- SSH -t flag after hostname in Makefile Moved before hostname
18 Firewall role runs twice on non-Proxmox hosts Removed duplicate include_role from base role
19 SSH -t flag in wrong position Already fixed above (same as -- entry)
20 ansible_user in [ssh_connection] silently ignored Moved remote_user = ansible to [defaults]
21 run.sh masks playbook failures via tee Added set -euo pipefail
22 playbook_handlers.yml orphaned and never imported Deleted file
23 changed_when: true on idempotent commands Changed to changed_when: false in debian role; udp-gro-fix fixed; mailcow deleted
24 run-local mounts wrong path Target no longer exists (docker targets removed)
25 TAILSCALE_AUTHKEY vs TAILSCALE_KEY mismatch Added env var lookup fallback in group_vars/all/all.yml
26 bootstrap.yml second play unconditional become_method: sudo Documented -K requirement
27 mail.mcintire.me and git.mcintire.me bare ansible_host Replaced with IP addresses

  1. Rotate all 4 plaintext secrets in .envrc and move to ansible-vault