Ansible playbook for provisioning and deploying the Parlor platform to a single VPS. Handles server hardening, Docker setup, reverse proxy, databases, and application deployment via containerized services.
Internet
│
▼
Traefik (ports 80/443, TLS via Let's Encrypt)
├── landing.parlorharpia.tech → Landing Page (:80)
└── api.parlorharpia.tech → API Core (:8080)
Internal (parlor-network)
├── PostgreSQL (:5432, localhost only)
└── Redis (:6379, localhost only)
| Role | Description |
|---|---|
configure_server |
Creates deploy user (parloruser), configures SSH keys, disables root login |
docker_install |
Installs Docker CE from official repos, logs into GHCR |
traefik |
Reverse proxy with automatic HTTPS (Let's Encrypt), HTTP→HTTPS redirect |
postgresql |
PostgreSQL 18 container with persistent data volume |
redis |
Redis 7.4.3 container with AOF persistence |
deploy_apicore |
Go API backend — pulls image from GHCR, runs migrations, deploys |
deploy_landing |
Landing page — pulls image from GHCR and deploys |
deploy_frontend |
Placeholder for future frontend deployment |
Roles execute in order: server config → Docker → Traefik → PostgreSQL → Redis → API Core → Landing.
- Ansible installed locally
- SSH access to the target VPS via key-based auth
- Secrets file at
group_vars/secrets.yml(see below)
Create group_vars/secrets.yml (gitignored) with:
user_password: "<hashed password>"
ssh_authorized_keys:
- "<your public SSH key>"
postgres_password: "<password>"
redis_password: "<password>"
jwt_secret: "<secret>"
ghcr_user: "<github username>"
ghcr_token: "<github PAT with packages:read>"
mailtrap_token: "<token>"
google_client_id: "<oauth client id>"
google_client_secret: "<oauth client secret>"Or encrypt with Ansible Vault:
ansible-vault create group_vars/secrets.ymlDry run (check mode):
ansible-playbook -i inventory playbook.yml --check --diffDeploy:
ansible-playbook -i inventory playbook.ymlDeploy a specific role:
ansible-playbook -i inventory playbook.yml --tags traefikThe GitHub Actions workflow (.github/workflows/deploy.yml) runs automatically on pushes to main that modify deployment files. It:
- Runs the playbook in check mode
- Applies changes only if the dry run detected differences
Secrets are provided via GitHub Actions secrets. Manual runs are also supported via workflow_dispatch.