4.6 KiB
4.6 KiB
servers
Homelab infrastructure managed with Ansible and tested against local QEMU VMs. Two production VPS hosts (proxy and IDP) are connected via WireGuard and run everything behind Apache reverse proxies with Let's Encrypt TLS.
Architecture
┌─────────────────────────────────────────────────┐
│ Proxy (10.0.0.1) │
│ ┌───────────┐ ┌──────────┐ ┌────────────────┐ │
│ │ Apache │ │ Prosody │ │ Docker Registry│ │
│ │ (reverse │ │ (XMPP) │ │ (pull-through) │ │
│ │ proxy) │ │ │ │ │ │
│ ├───────────┤ ├──────────┤ ├────────────────┤ │
│ │ ConverseJS│ │ Bugzilla │ │ Comentario │ │
│ │ Kellnr │ │ DevPI │ │ dnsmasq │ │
│ └───────────┘ └──────────┘ └────────────────┘ │
│ WireGuard ─────────────────────────┐ │
└─────────────────────────────────────┼────────────┘
│
┌─────────────────────────────────────┼────────────┐
│ IDP (10.0.0.2) │ │
│ ┌──────────────────────────────────┘ │
│ │ Authentik (identity provider) │
│ │ PostgreSQL + Redis │
│ └───────────────────────────────────────────────┘
└──────────────────────────────────────────────────┘
Clients (phone, workstation) connect over WireGuard and resolve names via dnsmasq on the proxy.
Quick start
# Install Python dependencies
pipenv install
# Install Ansible collection dependencies
pipenv run ansible-galaxy collection install -r ansible/requirements.yml
# Deploy to production
pipenv run ansible-playbook -i ansible/inventories/prod/hosts.ini ansible/playbooks/setup.yml
# Deploy a single service (e.g. bugzilla)
pipenv run ansible-playbook -i ansible/inventories/prod/hosts.ini ansible/playbooks/setup.yml --tags bugzilla
# Deploy a service without its dependencies
pipenv run ansible-playbook -i ansible/inventories/prod/hosts.ini ansible/playbooks/setup.yml --tags bugzilla --skip-tags docker,apache
See DEVELOPMENT.md for the full local development workflow.
Available tags
| Tag | What it deploys | Host |
|---|---|---|
host |
Base host config (SSH keys, users, swap) | all |
docker |
Docker engine + registry mirrors | docker_hosts |
wireguard |
WireGuard tunnels | proxy, idp |
apache |
Apache + Let's Encrypt certs | proxy |
dnsmasq |
DNS resolver | proxy |
docker-registry |
Pull-through registry mirrors | proxy |
restic |
Backup infrastructure | proxy, idp |
prosody |
XMPP server + upload proxy | proxy |
conversejs |
Web XMPP client | proxy |
kellnr |
Rust crate registry | proxy |
devpi |
Python package index | proxy |
comentario |
Comment system | proxy |
bugzilla |
Bug tracker | proxy |
authentik |
Identity provider + reverse proxy | idp, proxy |
blog |
Static blog site | proxy |
spec |
Static spec site | proxy |
Backups
# Run backup
pipenv run ansible-playbook -i ansible/inventories/prod/hosts.ini ansible/playbooks/backup.yml
# Restore
pipenv run ansible-playbook -i ansible/inventories/prod/hosts.ini ansible/playbooks/restore.yml
Automated backups run via systemd timer (bi-weekly by default).
Vault
Sensitive variables live in ansible/inventories/prod/group_vars/all/vault.yml,
encrypted with ansible-vault. The vault password file is .vault-pass
(not committed).
# Edit vault
pipenv run ansible-vault edit ansible/inventories/prod/group_vars/all/vault.yml
Authentik notes
App passwords with more than 30 minutes expiration require a user or group attribute:
goauthentik.io/user/token-maximum-lifetime: days=365