Traefik — Operations Workbook

Traefik v2 reverse proxy on Hostinger VPS (vps-h1). Handles TLS termination and HTTP/S routing for all services on vps-h1.


Architecture

Hostinger VPS (72.60.32.61)
└── Container: root-traefik-1         image: traefik:v2.x
    ├── port 80   HTTP (redirect to HTTPS)
    ├── port 443  HTTPS (TLS termination)
    ├── ACME provider: Let's Encrypt (HTTP-01 challenge)
    └── volume: traefik_acme  (/etc/traefik/acme.json — TLS cert store)
 
Routing (label-based, per-container):
  n8n.vps-h1.infra.zintegrowana.online          → root-n8n-1 :5678
  waha2.vps-h1.infra.zintegrowana.online        → waha :13000
  claude-proxy.vps-h1.infra.zintegrowana.online → claude-proxy :80
  (any new service: add Traefik labels to its compose service)

DNS: Wildcard *.vps-h1.infra.zintegrowana.online → 72.60.32.61 (Cloudflare, zone 57cb3d8f24c7cc319fb703394edc7b87).

Compose file on server: /root/docker-compose.yml
Compose file in repo: hostinger/docker-compose.yml

No dedicated Traefik dashboard URL is exposed publicly. Dashboard is disabled or bound to localhost only.


Config Management

Config elementLocationIn repo?Notes
Static configTraefik CLI flags in docker-compose.yml labelsYesentrypoints, ACME resolver, log level
Dynamic routingPer-service Docker labels in docker-compose.ymlYesrouter + service definitions
TLS certstraefik_acme Docker volume (acme.json)NoAuto-managed by Let’s Encrypt
.env/root/.env on vps-h1NoHolds secrets referenced in compose

Adding a new routed service

# In hostinger/docker-compose.yml — add labels to the new service:
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.myservice.rule=Host(`myservice.vps-h1.infra.zintegrowana.online`)"
  - "traefik.http.routers.myservice.entrypoints=websecure"
  - "traefik.http.routers.myservice.tls.certresolver=letsencrypt"
  - "traefik.http.services.myservice.loadbalancer.server.port=8080"
# Deploy
git pull
cd /root
docker compose up -d myservice
# Traefik detects new labels dynamically — no Traefik restart needed

Modifying Traefik static config

Static config changes (entrypoints, ACME settings) require a Traefik restart:

docker compose -f /root/docker-compose.yml restart traefik

Deployment

Fresh install

# On vps-h1 as root
cd /root
# Ensure .env is populated
docker compose up -d traefik

Restart Traefik

docker compose -f /root/docker-compose.yml restart traefik

Check routing

# Verify Traefik is running
docker inspect root-traefik-1 --format '{{.State.Status}}'
 
# Check TLS cert for a domain
curl -I https://n8n.vps-h1.infra.zintegrowana.online
 
# Local HTTP check (should redirect to HTTPS)
curl -I http://72.60.32.61

Backup

DataMethodScheduleDestination
Routing config (compose labels)Git repoOn every pushGitHub radieu/p24-infra
TLS certs (traefik_acme volume)Not backed upAuto-renewed by Let’s Encrypt
.env secretsNot backed up in git — use .env.local on local workstationLocal workstation + GH Secrets

TLS certs: If traefik_acme volume is lost, Traefik requests new certificates from Let’s Encrypt on first HTTPS request. Brief per-domain delay (~10s) during initial cert provisioning. Not a data-loss risk. Let’s Encrypt rate limit: 5 certificates per domain per week — avoid frequent volume destruction.

Backup = config fully in git. Restore is git pull + compose up.


Restore

Scenario 1: Traefik container crash

docker compose -f /root/docker-compose.yml up -d traefik
# TLS certs in traefik_acme volume survive container restarts

Scenario 2: Full vps-h1 rebuild

# 1. Provision new Hostinger VPS (Ubuntu 24.04)
# 2. Install Docker
# 3. Clone or copy compose file
git clone https://github.com/radieu/p24-infra /opt/p24-infra
cp /opt/p24-infra/hostinger/docker-compose.yml /root/docker-compose.yml
 
# 4. Restore .env from local workstation
scp -i C:\Users\konar\.ssh\id_ed25519 .env.local root@72.60.32.61:/root/.env
 
# 5. Start full stack (Traefik first — it must be up before routed services)
docker compose -f /root/docker-compose.yml up -d traefik
docker compose -f /root/docker-compose.yml up -d
 
# 6. TLS certs auto-provisioned on first HTTPS request per domain

Estimated RTO: ~10 minutes (compose up + cert provisioning per domain).


Healthcheck / Monitoring

CheckMethodAlert
Container runningcAdvisor container metrics scraped by Prometheus (job cadvisor, 72.60.32.61:8080)ContainerCrashLooping if restarting
HTTP 80 respondingcurl http://72.60.32.61 → expect 301/302 redirectManual check
HTTPS endpoint reachabilityBlackbox exporter probes per-service URLsEndpointDown alert per routed service
TLS cert expiryBlackbox exporter ssl_earliest_cert_expiry metricNo dedicated alert rule yet — gap

No dedicated Traefik metrics endpoint is configured. cAdvisor provides container-level CPU/mem/restart metrics only.

Manual health check:

# Container up?
ssh root@72.60.32.61 "docker inspect root-traefik-1 --format '{{.State.Status}} {{.State.Health.Status}}'"
 
# Verify a routed service end-to-end
curl -o /dev/null -s -w "%{http_code}" https://n8n.vps-h1.infra.zintegrowana.online/healthz

Password Rotation

Traefik has no own admin password. The dashboard is not publicly exposed.

CredentialManaged byRotation
TLS certificatesLet’s Encrypt ACME (auto-renewed)90-day cycle, fully automatic
Traefik API tokensNone configuredN/A
Routed service credentialsPer-service — see each service’s ops workbookPer-service schedule

No password rotation action required for Traefik itself.


Troubleshooting

SymptomLikely causeFix
404 on a routed domainLabels missing or wrong Host() ruleCheck compose labels; docker compose up -d <service>
TLS cert not provisioningHTTP-01 challenge blocked (port 80 closed)Ensure port 80 is open in Hostinger firewall
acme.json permission errorTraefik requires chmod 600 acme.jsondocker exec root-traefik-1 chmod 600 /etc/traefik/acme.json
502 Bad GatewayUpstream container not runningdocker compose -f /root/docker-compose.yml up -d <service>
Traefik won’t startPort 80/443 already bound`ss -tlnp
Let’s Encrypt rate limit hitToo many cert requests for a domainWait up to 1 week; use staging ACME URL for testing