- 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
8.3 KiB
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 fromplaybook.yml, removedforgejo_serversgroup fromhosts, removed forgejo vars fromhost_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_ed25519and/Users/graham/.ssh/ansiblewithansible_ssh_private_key_file: "{{ lookup('env', 'ANSIBLE_SSH_PRIVATE_KEY_FILE') | default('~/.ssh/ansible', true) }}"ingroup_vars/all/all.yml. SetANSIBLE_SSH_PRIVATE_KEY_FILEenv var to override. - Fixed
community.mysqlcollection — added torequirements.ymland installed (fixes monitor role crash). - Removed broken
setup-userMakefile target — referenced non-existentsetup-user.sh. - Fixed tracking issues —
git rm --cachedfor 5.DS_Storefiles and.vscode/settings.json; added.ansible/to.gitignore. - Fixed stale documentation — updated
CLAUDE.mdandREADME.mdto 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 forms —become: yes→become: true,gather_facts: no→gather_facts: falsein all plays. - Removed deprecated
inject_facts_as_varsfromansible.cfg. - Added missing task names —
import_tasks/include_rolecalls inbase/tasks/main.ymlandgeneral/tasks/main.ymlnow have descriptive names. - Fixed
partial-becomebug — addedbecome: yesto librenms clone task. - Added
pipefailto risky shell command inudp-gro-fix.yml. - Quoted octal mode values —
mode: 0755→mode: '0755', etc. - Hardened
.ansible-lintconfig — setprofile: production, added exclude paths, removed all skip_list entries. - Added defaults for 4 undefined template variables —
ntpserver,template_run_date,deb_mirror,sshd.*all have safe fallbacks now. - Removed Alpine role reference —
include_role: name=alpineinroles/base/tasks/main.ymlwas pointing to a non-existent role. - Fixed SSH
-tflag placement — Moved before hostname in bothbootstrap-rebootandrebootMakefile targets. - Fixed
general.ymlreferences —bootstrap-network,run-all,qc-webMakefile targets now useplaybook.yml; removedqc-webtarget (qc_webgroup doesn't exist). - Removed all Docker targets —
build-*,run-*,push-*,base-*,latest,local,clean,dirs— no Dockerfile at repo root ever existed. - Fixed
install-collections— removed references to deletedroles/requirements.ymlandscripts/fix-deprecated-imports.sh. - Deleted orphaned
host_vars/db.aprs.me.yml— host not in inventory;db.w5isp.comalready 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.kubernetesfromrequirements.yml; deleted entireroles/requirements.yml(graylog2.graylog, bertvv.bind, artis3n.tailscale); mergednetbox.netboxinto root file. - Cleaned fact_cache — removed 56 stale files.
- Removed unused inventory groups —
home_clusteranddns_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 password — cipassword 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 |
Recommended Fix
- Rotate all 4 plaintext secrets in
.envrcand move toansible-vault