Ansible¶
Ansible is the configuration-management half of this build's automation. Python + VBoxManage brings VMs into existence; Ansible configures what runs inside them — SSH hardening, UFW, ZFS, Docker, services.
The same playbooks that configure the VirtualBox lab VM are designed to be run, with minimal changes, against the real MS-S1 MAX after Ubuntu 26.04 is installed.
Why Ansible for this build¶
- Agentless. SSH-only management is the only management plane on this server anyway. Ansible needs nothing on the target except OpenSSH and Python 3 (preinstalled).
- Idempotent by design. Every module is built around "make the system match this declared state". Re-running a playbook is safe.
- Auditable. Every change goes through a playbook in git. Drift detection is one
ansible-playbook --check --diffaway. - YAML, not bash. Encodes intent declaratively; the tooling handles "if not already set, do X".
- Mature ecosystem. Existing collections (e.g.
devsec.hardening) for CIS-style hardening if you want it, plus tens of thousands of modules for everything fromaptto ZFS.
What this section covers¶
| Page | Topic |
|---|---|
| Concepts | inventory, plays, tasks, roles, handlers, facts, idempotency — the mental model |
| Installation | Installing Ansible on a Mac/Linux control node; the target needs no agent |
| Inventory | INI vs YAML formats, groups, host_vars/group_vars, dynamic inventories |
| Playbooks | Anatomy: plays, tasks, loops, conditionals, blocks, error handling |
| Modules | The modules used in this build: apt, copy, template, systemd, ufw, community.general.zfs, etc. |
| Variables | Variable precedence, --extra-vars, register, facts, magic variables |
| Templates | Jinja2 syntax, filters, lookups, loops in templates |
| Roles | Role structure, dependencies, Galaxy collections |
| Vault | ansible-vault for secrets, integration with 1Password / sops |
| Handlers | Notify/listen, restart-service patterns, ordering guarantees |
| Connection | SSH transport, become/sudo, control-persist, jump-hosts |
| Testing | --check, --diff, ansible-lint, molecule, syntax checks |
| Integration | How Ansible fits with the lab automation in scripts/lab/ and the production server |
| Troubleshooting | Common errors and how to debug them with -vvv |
How this section pairs with scripts/lab/¶
The lab repository has working playbooks under scripts/lab/ansible/playbooks/. These docs are the reference manual; the playbooks are the worked examples. Read them side-by-side:
| Lab playbook | Demonstrates |
|---|---|
bootstrap.yml | apt, loops, copy with content, community.general.timezone, handlers |
ssh-hardening.yml | template-style config via copy with a Jinja2 body, command for validation |
ufw.yml | community.general.ufw module, loops, idempotent state |
zfs.yml | shell-script-style fact gathering, set_fact, assert, complex command invocations, community.general.zfs |
The full lab path:
# 1. provision the VM (downloads ISO, creates VM, kicks off install)
python3 scripts/lab/01_provision.py
# 2. configure it with Ansible
python3 scripts/lab/02_apply.py # default chain: bootstrap, ssh-hardening, ufw
python3 scripts/lab/02_apply.py zfs # just the ZFS playbook
python3 scripts/lab/02_apply.py zfs -e topology=mirror
See Integration for the full design.
A few opinions baked into this section¶
- Use
ansible-playbookoveransiblefor everything. The ad-hocansiblecommand is fine for "ping all hosts" but isn't where real work lives. Every example here is a playbook. - Prefer modules over
command/shell. A module knows when it's changed something;commanddoesn't. Useshellonly when no module fits and documentchanged_when. - Roles are valuable but not always necessary. For a homelab with ~10 playbooks, flat playbooks are simpler. Promote to roles when you have repeating patterns across many hosts/projects.
- Keep secrets in vault from day one. Even on a lab. Habits stick.
Where to start reading¶
If you're new to Ansible:
- Installation — install it locally
- Concepts — terminology and the loop
- Playbooks — read this carefully; it's the load-bearing page
- Inventory, Variables, Modules — fill in the gaps
- Integration — see how it ties to this specific build
If you already know Ansible and just want this build's specifics, jump straight to Integration.