0f76abd1faa67d6840447fd6726f026049cabc87
Refs #1 ## Security * Remove the CrowdSec LAPI key from config.yml. Traefik does not interpolate env vars in its YAML config, so the key had to be literal there - which is why the file kept drifting out of version control. It is now defined as a docker-compose label, where compose substitutes ${CROWDSEC_LAPI_KEY} from .env. config.yml is therefore secret-free and stays in git. NOTE: this renames the middleware crowdsec-bouncer@file -> @docker. Site stacks referencing @file must be updated. The old key remains in this repo's history and must still be rotated and scrubbed - removing it here does not un-expose it. * Move the dashboard basic-auth hash out of docker-compose.yml into .env. In .env every '$' must be doubled to '$$', or compose silently collapses the hash to an empty string and the dashboard rejects every password. * Stop publishing port 8080. The API is not insecure-mode, so nothing served there; publishing it only widened exposure. ## Geoblock (the availability fix) * allowUnknownCountries: false -> true. Previously a geojs.io outage made every lookup "unknown" and therefore blocked, taking sites down for US visitors too - a third-party service in the critical path with no degraded mode. Now an outage degrades to "geoblocking ineffective". CrowdSec still blocks actual attackers. * cacheSize: 25 -> 5000. At 25, nearly every visitor triggered a fresh API call, adding up to 750ms and risking rate limits. ## Dev host support * Add traefik.dev.yml, selected by TRAEFIK_STATIC_CONFIG in .env (defaults to traefik.yml, so prod behaviour is unchanged). It differs from traefik.yml ONLY in the ACME challenge type: public port 80 forwards to prod for its renewals, so an HTTP-01 challenge for a dev hostname hits prod's Traefik, matches no router, and 404s. Dev uses DNS-01 via Route 53 instead, which needs no inbound connectivity. * Add .env.example documenting every variable. ## Captured from prod's working tree Prod had uncommitted drift; these were running but never committed: plugin bumps (bouncer v1.3.3->v1.3.5, geoblock v0.2.7->v0.2.8), the entryPoints HTTP->HTTPS redirect with priority 1, and httpClientTimeout: 0. The priority: 1 on that redirect is load-bearing - it keeps the redirect below normal routers so basil's Host(`localhost`) HTTP route still serves. Do not raise it. ## Verified on dev (prkl10), Traefik 3.7.10 7 routers / 8 middlewares, 0 warnings, 0 errors. Certificates issued via DNS-01. pihole and technitium routers preserved. Sites serving 200.
Traefik Reverse Proxy Configuration
This directory contains the Traefik reverse proxy configuration for managing SSL certificates and routing traffic to services.
Services Managed
- Mealie (recipes.pkartchner.com) - Recipe manager
- Gogs (git.pkartchner.com) - Git repository server
- Traefik Dashboard (traefik.pkartchner.com) - Traefik management UI
Features
- ✅ Automatic HTTPS with Let's Encrypt SSL certificates
- ✅ Automatic HTTP to HTTPS redirect
- ✅ Docker service discovery
- ✅ Security headers middleware
- ✅ Traefik dashboard with basic auth
Files
docker-compose.yml- Traefik container configurationtraefik.yml- Main Traefik configurationconfig.yml- Dynamic configuration for external servicesacme.json- Let's Encrypt certificate storage (auto-generated)
Setup
1. DNS Configuration
Ensure these DNS records point to your server's public IP:
A recipes.pkartchner.com → YOUR_PUBLIC_IP
A git.pkartchner.com → YOUR_PUBLIC_IP
A traefik.pkartchner.com → YOUR_PUBLIC_IP
2. Start Traefik
cd /srv/docker-compose/traefik
docker compose up -d
3. Check Logs
docker logs traefik -f
Dashboard Access
Access the Traefik dashboard at: https://traefik.pkartchner.com
Default credentials:
- Username:
admin - Password:
change-this-password
Change the password:
# Generate new password hash
echo $(htpasswd -nb admin yournewpassword) | sed -e s/\\$/\\$\\$/g
# Update the label in docker-compose.yml:
# traefik.http.middlewares.traefik-auth.basicauth.users=admin:$HASH
SSL Certificates
Traefik automatically obtains and renews SSL certificates from Let's Encrypt.
- Certificates are stored in
acme.json - Auto-renewal happens 30 days before expiration
- Email notifications sent to: pkartch@gmail.com
Staging vs Production
The configuration uses Let's Encrypt production by default.
To use staging (for testing, to avoid rate limits):
Uncomment this line in traefik.yml:
caServer: https://acme-staging-v02.api.letsencrypt.org/directory
Port Configuration
- 80 - HTTP (redirects to HTTPS)
- 443 - HTTPS (main entry point)
- 8080 - Traefik dashboard
Adding New Services
Docker Services
Add labels to your service's docker-compose.yml:
services:
myservice:
labels:
- "traefik.enable=true"
- "traefik.http.routers.myservice.rule=Host(`myservice.pkartchner.com`)"
- "traefik.http.routers.myservice.entrypoints=https"
- "traefik.http.routers.myservice.tls.certresolver=letsencrypt"
- "traefik.http.services.myservice.loadbalancer.server.port=PORT"
networks:
- traefik
External Services
Add to config.yml:
http:
routers:
myservice:
rule: "Host(`myservice.pkartchner.com`)"
entryPoints:
- https
service: myservice
tls:
certResolver: letsencrypt
services:
myservice:
loadBalancer:
servers:
- url: "http://INTERNAL_IP:PORT"
Troubleshooting
Check Traefik logs
docker logs traefik --tail 100
Verify network
docker network ls | grep traefik
Test certificate
openssl s_client -connect recipes.pkartchner.com:443 -servername recipes.pkartchner.com
Reload configuration
docker compose restart traefik
Security Notes
- Change the default dashboard password immediately
- Keep
acme.jsonpermissions at 600 - Regularly update Traefik image
- Monitor access logs
- Consider disabling the dashboard in production
Maintenance
Update Traefik
docker compose pull
docker compose up -d
Backup certificates
cp acme.json acme.json.backup
View certificate info
Check the Traefik dashboard under "HTTP" → "Routers"
Description
Languages
Markdown
100%