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.