Ansible
Post-provision configuration and hardening for every host - idempotent roles applied in a deliberate order, because the order is what keeps a firewall change from locking the box out.
What it is & why I use it
Ansible is the configuration-management layer of AutomationLab. Terraform brings a VM into existence; Ansible turns that bare VM into a configured, hardened, monitored host. It runs as the configure stage of the provisioning pipeline, after the machine exists and before it is handed over as ready.
I use it because configuration should be declarative and idempotent: the same play run twice leaves the host in the same state, so "converge the host to what the role says" replaces a pile of one-off setup commands nobody can reproduce.
How I use it in the lab
- Roles, not scripts. Each concern is a role with documented defaults - a firewall role, a time-sync role, a monitoring-agent role - composed into a single host-configuration play.
- Runs from the pipeline, as an unprivileged user. The configure stage runs Ansible from the CI agent under a dedicated automation user, not root, with the collection path pinned so runs are reproducible regardless of which agent picks up the job.
- Secrets pulled at runtime. Anything sensitive a role needs comes from the secrets manager during the run - nothing sensitive is stored in inventory or vars in the repo.
- Deliberate role order. The play applies firewall, then time-sync, then the monitoring agent - and that order is load-bearing, not cosmetic (see the gotcha).
Architecture
In action
Lessons learned & gotchas
- Idempotence is a feature you have to test. A role is only trustworthy once a second run reports zero changes. A task that keeps reporting "changed" is usually lying about convergence and will fight you later.
- Pin the collection path. If roles depend on collections, the path they load from must be fixed and owned by the run user - not left to whatever happens to be installed on a given agent - or the same play behaves differently on different runners.
- Run as a real service account, not root. Least privilege applies to configuration management too; a role that needs elevation should ask for it explicitly, so "what can this play change?" stays answerable.
Impact
Ansible is what makes "provisioned" mean "actually configured and hardened," every time, the same way. The firewall-ordering lesson is the one I keep closest: automation that can lock itself out of the very host it is configuring is a trap, and the defense is encoding the safe order into the roles so it cannot be got wrong by accident.
Code & further reading
Published roles are scrubbed of internal addresses, hostnames, inventory, and any secret references before they go public.