Skip to content

Infrastructure

The infrastructure is a single-server Docker Swarm deployment managed through Ansible for server provisioning, GitHub Actions for CI/CD, and Terraform for GitHub repository and environment configuration.

Tech Stack

CategoryTechnologyPurpose
OrchestrationDocker SwarmContainer scheduling, networking, restarts
ProvisioningAnsibleIdempotent server setup (Docker, UFW, Fail2ban)
IaC (GitHub)Terraform (GitHub provider)Repo settings, branch protection, environments, secrets
CI/CDGitHub ActionsLint, build, deploy workflows
Reverse ProxyNginxSSL termination, subdomain routing
SSLCertbot / Let's EncryptAuto-renewed TLS certificates
MetricsPrometheus + GrafanaMonitoring and dashboards
Container RegistryGitHub Container Registry (GHCR)Docker image storage

Infrastructure Topology

Domain Routing

SubdomainServiceInternal Target
alumni.example.comFrontend (Nuxt SSR)frontend:3000
api.alumni.example.comBackend (FastAPI)backend:8080
mobile.alumni.example.comMobile Web (Flutter)mobile:80
grafana.alumni.example.comGrafana dashboardsgrafana:3000
portainer.alumni.example.comDocker Swarm UIportainer:9000

All HTTP traffic is redirected to HTTPS. TLS terminates at Nginx using Let's Encrypt certificates.

Services Inventory

ServiceImageResourcesPersistence
nginxnginx:alpine0.5 CPU / 256 MBnginx configs volume
certbotcertbot/certbot/data/certbot/
postgrespostgres:16pinned to manager/data/postgres/
postgres-backupprodrigestivill/postgres-backup-local:16/data/backups/
portainerportainer/portainer-ce:latestportainer data volume
prometheusprom/prometheus:v2.52.0pinned to manager/data/prometheus/ (30-day retention)
grafanagrafana/grafana:11.0.0grafana provisioning configs
node-exporterprom/node-exporter:v1.8.0global (all nodes)
postgres-exporterprometheuscommunity/postgres-exporter:v0.15.0

CI/CD Pipeline

Workflow Files

WorkflowTriggerPurpose
ci.ymlPR / push to mainLint YAML, Ansible, shell; validate Docker configs
setup-server.ymlManual / Ansible file changesRun Ansible playbook to provision server
deploy.ymlPush to main (infra files changed)Redeploy infrastructure stack
deploy-service.ymlReusable workflowDeploy a specific app service (backend, frontend, mobile)
update-env.ymlManual dispatchUpdate server .env without full redeploy
mobile.ymlManual / repository_dispatchBuild Flutter web + deploy

Deployment Detail (per service)

Server Provisioning (Ansible)

The playbook is idempotent — safe to re-run at any time (e.g., after adding a new secret).

Terraform: GitHub Repository Management

Terraform manages GitHub configuration as code:

Repository enforcement:

  • Squash-merge only
  • Auto-delete head branches on merge
  • Required status checks before merging to main
  • Branch deletion protection

Monitoring Stack

Environment Structure

PropertyTestingProduction
Branchdevelopmain
Deploy triggerAuto on pushAuto on merge to main
Approval requiredNoYes (manual)
Domainconfigurable via secretsconfigurable via secrets
SecretsSeparate setSeparate set

Security

LayerMechanism
FirewallUFW — only ports 22, 80, 443 open
Brute-forceFail2ban — 5 SSH failures → 3600s ban
TLSLet's Encrypt (auto-renew every 12h via Certbot)
SecretsGitHub Actions environment secrets → .env via Ansible
Registry authGHCR — GitHub token-based pull access
DockerOverlay network (services not exposed to host by default)

Server Migration Pattern

The deployment is designed to be server-agnostic. To migrate to a new server:

  1. Update SERVER_HOST GitHub secret to new server IP
  2. Update DNS A-records to point to new IP
  3. Trigger "Setup Server" GitHub Actions workflow
  4. All services redeploy automatically — no code changes required

IU Alumni Platform Documentation