Automating My VPS Setup with Ansible
Table of Contents
🧩 Infrastructure Overview#
Here’s a high-level view of the services I run:
- Docker: Everything is containerized for isolation
- Nginx: Reverse proxy + TLS termination
- Certbot: Automatic SSL with Let’s Encrypt
- OAuth2 Proxy + Keycloak: Centralized authentication
- Grafana + Prometheus + Node Exporter: Monitoring stack
- GitHub Actions Runner: Self-hosted CI
- UFW + Fail2Ban: Firewall and brute-force protection
- Watchtower: Automatically updates Docker containers
Why Ansible?#
Using Ansible allows me to:
- Define everything as code
- Avoid configuration drift
- Make re-deployments easy and predictable
All roles are modular and idempotent. I can rebuild the entire server from scratch in minutes.
Attempted Security-First#
OAuth2 Proxy + Keycloak#
Sensitive apps are protected via oauth2-proxy
in front of containers, authenticating through Keycloak. Each app config includes OAuth toggles:
nginx_apps:
- domain: subdomain.smikic.com
port: 69420
oauth: true
This generates a custom Nginx config with an embedded OAuth2 block. Only authenticated users can reach the app.
Let’s Encrypt + Certbot#
SSL certificates are automatically requested and renewed using Certbot with the Nginx plugin. Ansible automates this, requiring only a domain and email.
Firewall Rules via UFW#
UFW is configured dynamically:
- Allows only required ports
- OAuth2-protected apps get UFW rules only if enabled
- Node Exporter listens only to localhost
Fail2Ban is also installed and enabled for SSH brute-force protection.
Monitoring with Grafana & Prometheus#
Monitoring runs on its own Docker network:
- Prometheus scrapes data from Node Exporter and itself
- Grafana visualizes metrics, using Keycloak SSO
- Node Exporter exposes host metrics with hardened volumes
All of this is deployed via Docker containers with Watchtower watching for updates.
GitHub Actions Runner#
I added a self-hosted GitHub runner to offload builds from GitHub’s shared runners.
Deployment is a Single Command#
Once the inventory and vars are set, provisioning the whole VPS is as easy as:
ansible-playbook -i inventory site.yml
It’s safe to re-run this command anytime. Ansible only makes the necessary changes.
📌 What’s Next?#
- Add automatic backup/restore routines for volumes and secrets
- Integrate alerting (Alertmanager?) for Prometheus
- Extend Monitoring
- Maybe explore and implementing zero-trust?
There are no articles to list here yet.