Ansible¶
Terraform and cloud-init get a host to first boot. Ansible handles everything after: pushing configs, updating peers in a WireGuard mesh, rotating certificates, and keeping a cluster of hosts consistent without logging into each one.
The operational rule is the same as for Terraform: run Ansible from the bouncer, not from the operator’s workstation. The SSH connections the playbooks make originate from the bouncer’s IP, which already sits behind whatever opsec the operation uses.
Inventory¶
A static inventory file on the encrypted volume is enough for a small operation. One group per role:
[redirectors]
redir-01 ansible_host=<ip> ansible_user=op ansible_ssh_private_key_file=./op_ed25519
[frontends]
front-01 ansible_host=<ip> ansible_user=op ansible_ssh_private_key_file=./op_ed25519
[backends]
back-01 ansible_host=10.8.0.10 ansible_user=op ansible_ssh_private_key_file=./op_ed25519
Backend hosts on the WireGuard overlay use the overlay address; the bouncer is already a peer on that network.
Pushing a redirector config¶
A template per host type lets the same playbook serve a fleet of redirectors with different domain names:
- hosts: redirectors
become: true
vars_files:
- vars/{{ inventory_hostname }}.yml # per-host domain, upstream
tasks:
- name: nginx redirector config
template:
src: redir.conf.j2
dest: /etc/nginx/conf.d/redir.conf
mode: "0640"
notify: reload nginx
- name: nginx running
service:
name: nginx
state: started
enabled: true
handlers:
- name: reload nginx
service:
name: nginx
state: reloaded
redir.conf.j2 is the nginx redirector config with {{ domain }} and
{{ upstream }} in place of the hardcoded values. Per-host variable files on the encrypted volume keep the
mapping of host to role out of the playbook itself.
Running it¶
ansible-playbook -i inventory.ini redirectors.yml
Adding a new redirector: provision the host (via cloud-init or Terraform), add it to the inventory, re-run the playbook. Removing one: destroy the host, drop it from the inventory. No manual SSH required at any step.
What Ansible does not replace¶
Ansible is idempotent and fast for config distribution, but it touches the host over SSH, which leaves an
authentication event in auth.log. For hosts that are genuinely ephemeral and only live a few hours, Packer
images and cloud-init may be preferable to avoid any post-boot remote access at all.