# Ansible deploy One playbook does both jobs: the **first run** provisions the host (Docker, WireGuard, sysctl, firewall) and deploys the stack; **every later run is the update path** — it only touches what changed and restarts only the affected services. Deployed layout on the VPS (per-service dirs under `/opt`): | Path | Contents | |-----------------------|-------------------------------------------| | `/opt/vpnhub/` | `docker-compose.yml`, `.env` | | `/opt/openvpn/` | build context, `server.conf`, `pki/` | | `/opt/duo-authproxy/` | build context, cfg template, `certs/` | | `/opt/technitium/` | init-job build context + `config/` (live zone DB — never overwritten by the playbook) | The playbook renders the firewall and wg0 config from the same `host/rules.v4.template` / `host/wg0.conf.example` files the manual path uses — nothing is duplicated inside `ansible/`. ## Prerequisites A Linux control node (WSL is fine — this repo checked out inside WSL or accessed via `/mnt/c/...`), `ansible-core` >= 2.15, then: ```bash cd ansible ansible-galaxy collection install -r requirements.yml ``` ## First-time setup ```bash cp inventory.example.yml inventory.yml # set host/user cp group_vars/vpnhub.example.yml group_vars/vpnhub.yml $EDITOR group_vars/vpnhub.yml # DC IPs, Duo keys, secrets ansible-vault encrypt group_vars/vpnhub.yml # both files are gitignored anyway # Local key material (both gitignored, synced to /opt by the playbook): # ../openvpn/pki/ server.crt, server.key, ta.key (offline CA) # ../duo-authproxy/certs/ ad-ldaps-ca.pem ansible-playbook site.yml ``` The first run prints the **hub WireGuard public key** and stops short of starting `wg0` (site peer keys are still empty). Add the hub as a peer at both sites (docs/SITE-SIDE.md), paste each site's public key into `group_vars/vpnhub.yml` (`troch_wg_public_key` / `oswald_wg_public_key`), and run it again — wg0 comes up and the stack starts. ## Updating | What changed | Command | |---------------------------------------|------------------------------------------------------------| | Any config in the repo, `.env` values | `ansible-playbook site.yml` (affected services recreate) | | Just stack files, skip host checks | `ansible-playbook site.yml --tags stack` | | Base images / rebuild everything | `ansible-playbook site.yml -e vpnhub_force_rebuild=true` | | Duo Auth Proxy version | bump `duo_authproxy_version`, then force-rebuild as above | | Firewall only | `ansible-playbook site.yml --tags firewall` | | WireGuard peers/config | `ansible-playbook site.yml --tags wireguard` | Note on `duo_authproxy_version: latest`: Docker's layer cache means "latest" won't re-download a newer tarball on rebuild. Pin a real version (the cache busts when it changes) — that's the reliable update mechanism. ## Tags `docker`, `host` (packages + sysctl + firewall + wg), `firewall`, `wireguard`, `stack`.