Ansible Config Management — Project Guide
← Back to Intake Hub
Overview
This project automates server setup and WordPress deployment using
Ansible. The workflow is:
- Client fills out the intake form (this app)
- Data is saved and fetched by the Ansible control machine (Raspberry Pi)
- Ansible playbooks are generated and run against the production VPS
flowchart LR
A[Client Browser] --> B[Intake VPS
Port 8877]
B --> C[Submission YAML]
C -- Ansible fetch --> D[Raspberry Pi 4
Ansible Control]
D --> E[Production VPS
Contabo]
D -.-> F[Docker Staging
Tier 1]
D -.-> G[Dev-Env
Tier 1.5]
Inventory Tiers
Playbooks are tested across four tiers before touching production:
flowchart TD
subgraph Tier1["Tier 1 — Docker Staging"]
T1["Docker container
ansible-staging
SSH key auth
No systemd"]
end
subgraph Tier15["Tier 1.5 — Dev-Env"]
T15["dev-01 (10.0.0.6)
Ubuntu 22.04
Docker, no UFW"]
end
subgraph Tier2["Tier 2 — VM Staging (planned)"]
T2["Full Ubuntu VM
systemd, UFW, Docker
Not yet deployed"]
end
subgraph Tier3["Tier 3 — Production"]
T3["Contabo VPS
Real websites
⚠️ DANGER ZONE"]
end
T1 --> T15 --> T2 --> T3
| Tier | Target | Validates | Safety |
| 1 | Docker container | SSH, facts, syntax, basic tasks | Safe |
| 1.5 | dev-01 (10.0.0.6) | Docker, packages, configs | Mostly safe |
| 2 | VM Staging (planned) | UFW, Fail2Ban, full baseline | Safe |
| 3 | Production VPS | Real deployment | ⚠️ DANGER |
Playbook Execution Order
Playbooks are numbered and run in sequence. Each phase builds on the previous one.
flowchart LR
P0["00-root-bootstrap"] --> P1["01-admin-baseline"]
P1 --> P2["server-status"]
P1 --> P3["validate"]
P1 --> P4["01-server-baseline"]
P4 --> P5["03-wordpress-full-deploy"]
P4 --> P6["04-ssl-proxy"]
P4 --> P7["05-gh-cli"]
P4 --> P8["06-ftp"]
P4 --> P9["07-opencode"]
P4 --> P10["08-wp-cli"]
P4 --> P11["10-docker-app-nginx-proxy"]
| # | Playbook | Purpose |
| 00 | root-bootstrap | Create admin user, add SSH key, set up sudo |
| 01 | admin-baseline | Wrapper: runs 01-server-baseline + utility playbooks |
| — | server-status | Read-only health check (CPU, RAM, disk, Docker) |
| — | validate | Validate UFW, Fail2Ban, unattended-upgrades |
| 01 | server-baseline | Full server setup: UFW, Fail2Ban, Docker, backups, MOTD |
| 03 | wordpress-full-deploy | Deploy WordPress + MySQL + NPM + phpMyAdmin |
| 04 | ssl-proxy | Nginx Proxy Manager for SSL termination |
| 05 | gh-cli | Install GitHub CLI and authenticate |
| 06 | ftp | FTP server for WordPress file access |
| 07 | opencode | Install OpenCode AI assistant |
| 08 | wp-cli | Install WP-CLI for command-line WordPress management |
| 10 | docker-app-nginx-proxy | Reverse proxy stack for Docker app tenants |
How to Use the Agent (OpenCode)
This project uses OpenCode — an AI agent that runs in your terminal.
You talk to it in natural language, and it reads/writes files, runs commands, and
manages the Ansible workflow.
Common commands
opencode | Start a session in the project directory |
ansible -i inventories/staging/hosts.ini vps -m ping | Test staging connectivity |
ansible-playbook -i ... playbooks/... --check --diff | Dry-run a playbook (safe) |
Workflow
- Agent reads the intake data from the client submission
- Agent proposes a deployment plan
- User approves the plan
- Agent runs dry-runs against staging, then production
Safety Rules
NEVER run these without explicit approval:
- Production inventory:
-i inventories/production/hosts.ini
- WordPress deploy:
03-wordpress-full-deploy.yml or 03-wordpress-existing-deploy.yml
- SSL proxy:
04-ssl-proxy.yml
- FTP:
06-ftp.yml
- Baseline without
--check: 01-server-baseline.yml
Always do this first:
- Use explicit
-i inventories/staging/... for testing
- Run
--check --diff before every real apply
- Verify with
server-status.yml and validate.yml
- Stage changes locally before production
Branch Strategy
gitGraph
commit id: "initial"
branch dev
commit id: "Phase 1c-1f"
branch feature/phase-2a-staging-hygiene
commit id: "Phase 2A"
checkout dev
merge feature/phase-2a-staging-hygiene
branch feature/phase-3-client-intake
commit id: "Flask intake app + playbooks"
checkout dev
merge feature/phase-3-client-intake
branch feature/phase-4-deployment
commit id: "Production deploy"
All feature work happens on feature/* branches from dev.
PRs merge into dev. Production releases are tagged from dev.