5.5 KiB
Ansible Infrastructure
Private home infrastructure managed with Ansible: NAS (WD MyCloud, Asustor), Raspberry Pi 4, main workstation (acemagic), and MikroTik router.
The -i inventory/hosts.yml and --vault-password-file=vault.pass flags are pre-configured in ansible.cfg and can be omitted from all commands.
Inventory
| Host | IP | Role |
|---|---|---|
acemagic |
192.168.1.132 | Main workstation - backups, crons, autofs, FTP |
mycloud |
192.168.1.219 | WD MyCloud EX2 Ultra NAS (ARM32) |
asustor-lan1 |
192.168.1.10:8883 | Asustor NAS |
rpi4 |
192.168.1.151 | Raspberry Pi 4 (AdGuard Home) |
mikrotik |
192.168.1.1 | MikroTik router |
Host variables are encrypted with Ansible Vault in inventory/host_vars/.
Playbooks
common.yml - base server configuration
Hosts: acemagic, mycloud, rpi4 (excludes asustor and mikrotik)
- Sets hostname
- Installs apt packages (autofs, rsync, vim, net-tools, python3, ...)
- Stops and disables unnecessary systemd services
- Deploys SSH authorized keys (from
roles/common/vars/main.yml) - Updates
/etc/hostswith ~55 LAN entries (cameras, IoT devices, printers, switches) - Configures vsftpd + FTP user for Hikvision cameras (acemagic only, password from vault)
ansible-playbook playbooks/common.yml
# Update /etc/hosts only:
ansible-playbook playbooks/common.yml --tags update_hosts
# Target a single host:
ansible-playbook playbooks/common.yml -l rpi4
mycloud.yml - WD MyCloud EX2 Ultra
Hosts: mycloud
- Deploys authorized SSH keys to NAS
- Installs node_exporter (ARM32/armv7) - copies binary, starts via nohup (no systemd on MyCloud OS)
- Creates
/etc/init.d/S99node_exporterinit script for persistence across reboots - Verifies metrics are reachable from the Ansible controller
ansible-playbook -l mycloud playbooks/mycloud.yml
Note:
--check(dry-run) will incorrectly fail on thecopystep if the binary is not present locally in/tmp/. This is a check-mode limitation, not a real error.
asustor.yml - Asustor NAS
Hosts: asustor-lan1 (SSH port 8883)
- Deploys authorized SSH keys
- Checks if node_exporter is running, starts it if not
- Verifies port 9100 is accessible
ansible-playbook -l asustor-lan1 playbooks/asustor.yml
autofs.yml - NAS automount via autofs
Hosts: acemagic
- Configures
/etc/auto.master.d/asustor.autofsand/etc/auto.asustor - Configures
/etc/auto.master.d/mycloud.autofsand/etc/auto.mycloud - Restarts autofs service
ansible-playbook playbooks/autofs.yml
crons-only.yml - scheduled tasks on acemagic
Hosts: acemagic
- Cron: Frigate Docker container restart
- Cron: Bitwarden database backup
- Cron: HDD keep-alive for Seagate drives (5TB, 6TB, 16TB) - prevents spin-down
- hdparm: spin-down prevention for SDE and SDB
ansible-playbook playbooks/crons-only.yml
acemagic.backups.yml - backup scripts
Hosts: acemagic
- Deploys
backup.sh(rsync to Google Drive via rclone) - Deploys
backup_seagata16t.sh(rsync Seagate 16TB -> Asustor NAS) - Creates log file and cron for the 16TB backup
ansible-playbook playbooks/acemagic.backups.yml
mikrotik.backup.yml - router backup
Hosts: mikrotik
- Uploads SSH key to MikroTik if missing
- Sets up a local cron on acemagic to pull router backup daily at 03:30
ansible-playbook playbooks/mikrotik.backup.yml
setup_postgres_replication.yml - PostgreSQL logical replication
Hosts: acemagic (primary), asustor-lan1 (replica)
- Creates publications on primary
- Creates subscriptions on replica for selected databases
ansible-playbook playbooks/setup_postgres_replication.yml
override_properties.yml - patch .properties files on remote hosts
ansible-playbook playbooks/override_properties.yml \
-e "target_host=acemagic service_file=/path/to/app.properties"
Playbooks with missing roles (not yet implemented):
pureftpd_doorbell.yml- FTP for Ring doorbell (pureftpd_doorbellrole missing)rsync-mycloud.yml- rsync from MyCloud (rsync.mycloudrole missing)
Secret Management
Files in inventory/host_vars/*.yml and roles/*/vars/vault.yml are encrypted with Ansible Vault (AES256). The vault password is stored in vault.pass (excluded from git via .gitignore).
# Edit an encrypted file
ansible-vault edit inventory/host_vars/mycloud.yml
# Decrypt all files before editing
bash decrypt_vars.sh
# Re-encrypt all files after editing
bash encrypt_vars.sh
Pre-commit Security Hooks
Two layers of protection:
1. Custom git hook (.git/hooks/pre-commit) - always active:
- Blocks unencrypted
inventory/host_vars/*.ymlcommits - Blocks unencrypted
roles/*/vars/vault.ymlcommits - Scans staged files for hardcoded secrets (passwords, tokens, API keys)
2. pre-commit framework (.pre-commit-config.yaml) - requires one-time setup:
detect-secrets- entropy-based secret scanningdetect-private-key- blocks PEM/private key filescheck-yaml --unsafe- validates YAML (unsafe flag needed for Ansible vault tags)trailing-whitespace,end-of-file-fixer,check-merge-conflict- Blocks accidental
vault.passcommits
# One-time setup after cloning:
pip install pre-commit
pre-commit install
Run Logging
callback_plugins/json_logger.py appends all playbook run results to ansible_runs.jsonl (excluded from git).
Dependencies
geerlingguy.nfs- installed locally incollections/