Traefik Deploy Role¶
Ansible role to deploy Traefik reverse proxy with Let’s Encrypt automatic certificate management.
Description¶
This role installs and configures the base Traefik infrastructure on a target host. It handles:
Downloading and installing the Traefik binary
Creating the directory structure (
/etc/traefik,/etc/traefik/dynamic,/etc/traefik/acme,/var/log/traefik)Deploying static configuration with HTTP→HTTPS redirect
Setting up Let’s Encrypt automatic certificate management
Configuring the systemd service with security hardening
Setting up log rotation
Optionally configuring firewall rules
Note: This role only handles the base Traefik infrastructure. Individual service configurations should be managed by their respective roles using Traefik’s dynamic configuration in /etc/traefik/dynamic/.
Requirements¶
Target system: Linux (Debian/Ubuntu recommended)
Root/sudo access
Ports 80 and 443 available and accessible from the internet (for Let’s Encrypt HTTP challenge)
Valid email address for Let’s Encrypt registration
Role Variables¶
Required Variables¶
# Let's Encrypt email (REQUIRED - must be set in playbook)
traefik_letsencrypt_email: "admin@example.com"
Optional Variables¶
Version and Platform¶
# Traefik version to install
traefik_version: "3.3.5"
# Platform configuration (auto-detected from ansible facts)
# Only override if auto-detection fails or for cross-platform deployment
traefik_os: "linux" # auto-detected from ansible_system
traefik_arch: "amd64" # auto-detected from ansible_architecture
# x86_64 → amd64, aarch64 → arm64, armv7l → arm
# Checksum validation (RECOMMENDED for production)
# Get from https://github.com/traefik/traefik/releases
traefik_checksum: "" # Empty = skip validation
# Example: "sha256:abc123..."
# Force update even if version matches
traefik_force_update: false
Directory Configuration¶
traefik_config_dir: /etc/traefik
traefik_dynamic_dir: "{{ traefik_config_dir }}/dynamic"
traefik_acme_dir: "{{ traefik_config_dir }}/acme"
traefik_log_dir: /var/log/traefik
traefik_binary_path: /usr/local/bin/traefik
Logging¶
traefik_log_level: "INFO" # DEBUG, INFO, WARN, ERROR
traefik_log_format: "json" # json or common
traefik_logrotate_days: 7
Dashboard & API¶
traefik_dashboard_enabled: true
traefik_dashboard_port: 8090 # Moved from 8080 to avoid UniFi conflict
# Dashboard firewall access (default: internal only)
traefik_dashboard_firewall_open: false
Dashboard Access Options:
SSH Tunnel (Recommended):
ssh -L 8090:localhost:8090 your-serverFirewall Open (Security Risk): Set
traefik_dashboard_firewall_open: trueVia Traefik HTTPS: Create dynamic config to expose with authentication
Entrypoints¶
traefik_http_port: 80
traefik_https_port: 443
traefik_http_redirect_to_https: true
Features¶
traefik_metrics_enabled: true # Prometheus metrics
traefik_configure_firewall: true
Dependencies¶
None.
Example Playbook¶
Basic Usage¶
---
- name: Deploy Traefik
hosts: webservers
become: true
roles:
- role: local.ops_library.traefik_deploy
vars:
traefik_letsencrypt_email: "admin@example.com"
Production Deployment with Checksum¶
---
- name: Deploy Traefik with Checksum Validation
hosts: webservers
become: true
roles:
- role: local.ops_library.traefik_deploy
vars:
traefik_version: "3.3.5"
traefik_letsencrypt_email: "admin@example.com"
traefik_checksum: "sha256:1234567890abcdef..."
ARM64 Architecture¶
Architecture is auto-detected, but you can override if needed:
---
- name: Deploy Traefik on ARM64
hosts: arm_servers
become: true
roles:
- role: local.ops_library.traefik_deploy
vars:
traefik_letsencrypt_email: "admin@example.com"
# traefik_arch auto-detected from ansible_architecture
# Override only if needed: traefik_arch: "arm64"
Upgrade to New Version¶
Simply change the traefik_version variable:
---
- name: Upgrade Traefik
hosts: webservers
become: true
roles:
- role: local.ops_library.traefik_deploy
vars:
traefik_version: "3.4.0" # Role will detect version mismatch and upgrade
traefik_letsencrypt_email: "admin@example.com"
traefik_checksum: "sha256:newversion..."
Service Configuration¶
After deploying Traefik, create dynamic configurations in /etc/traefik/dynamic/ for your services.
Example: Simple HTTPS Service¶
Create /etc/traefik/dynamic/myapp.yml:
http:
routers:
myapp:
rule: "Host(`myapp.example.com`)"
entryPoints: [web-secure]
service: myapp
tls:
certResolver: letsencrypt
services:
myapp:
loadBalancer:
servers:
- url: "http://localhost:8000"
Traefik automatically watches this directory and reloads configurations.
Use certbot-managed certificates (file provider)¶
- role: local.ops_library.traefik_deploy
vars:
traefik_letsencrypt_email: "admin@example.com"
traefik_file_certificates:
- cert_file: "/etc/letsencrypt/live/home.xn--wersdrfer-47a.de/fullchain.pem"
key_file: "/etc/letsencrypt/live/home.xn--wersdrfer-47a.de/privkey.pem"
Place this under /etc/traefik/dynamic/certificates.yml; Traefik reloads it automatically when the cert is renewed.
Dual Router Authentication Pattern¶
For implementing the dual router pattern (internal vs external authentication), see the example in homelab service configuration.
Architecture Support¶
This role automatically detects the target platform from Ansible facts:
ansible_system→traefik_os(Linux → linux, Darwin → darwin)ansible_architecture→traefik_arch(x86_64 → amd64, aarch64 → arm64)
Supported platforms:
OS |
Architecture |
Auto-detect |
Tested |
|---|---|---|---|
Linux |
amd64 |
✅ |
✅ |
Linux |
arm64 |
✅ |
⚠️ |
Linux |
arm |
✅ |
❌ |
Darwin |
amd64 |
✅ |
❌ |
Darwin |
arm64 |
✅ |
❌ |
Override traefik_os and traefik_arch only if auto-detection fails.
Security Considerations¶
Checksum Validation¶
Always use checksum validation in production:
Visit https://github.com/traefik/traefik/releases/tag/v3.3.5
Download
traefik_v3.3.5_checksums.txtFind the SHA256 hash for your platform
Set in playbook:
traefik_checksum: "sha256:abc123..."
Dashboard Security¶
The dashboard is NOT exposed through the firewall by default (internal localhost access only).
Secure access methods:
SSH Tunnel (Recommended):
ssh -L 8090:localhost:8090 user@server # Access at http://localhost:8090
Traefik Dynamic Config with Auth: Create
/etc/traefik/dynamic/dashboard.yml:http: routers: dashboard: rule: "Host(`traefik.example.com`)" entryPoints: [web-secure] service: api@internal middlewares: [dashboard-auth] tls: certResolver: letsencrypt middlewares: dashboard-auth: basicAuth: users: - "admin:$apr1$..." # htpasswd hash
Open Firewall (Not Recommended):
traefik_dashboard_firewall_open: true # ⚠️ Security risk!
Systemd Hardening¶
The role applies systemd security hardening:
NoNewPrivileges=truePrivateTmp=trueProtectSystem=strictProtectHome=trueLimited write access to
/etc/traefikand/var/log/traefik
Monitoring¶
Prometheus Metrics¶
Metrics are exposed on the dashboard port:
curl http://localhost:8090/metrics
Configure Prometheus to scrape:
scrape_configs:
- job_name: 'traefik'
static_configs:
- targets: ['localhost:8090']
Logs¶
# Traefik logs
journalctl -u traefik -f
# Access logs
tail -f /var/log/traefik/access.log
# Error logs
tail -f /var/log/traefik/traefik.log
Troubleshooting¶
Let’s Encrypt Certificate Issues¶
Port 80 not accessible:
Ensure firewall allows port 80 (HTTP challenge)
Check router port forwarding
Rate limiting:
Let’s Encrypt has rate limits (5 certificates per week per domain)
Use staging environment for testing: https://letsencrypt.org/docs/staging-environment/
Check ACME logs:
journalctl -u traefik | grep -i acme
Version Upgrade Not Working¶
If version upgrade is skipped:
# Force upgrade
ansible-playbook playbook.yml -e traefik_force_update=true
Dashboard Not Accessible¶
Check service is running:
systemctl status traefik
Verify port is listening:
netstat -tlnp | grep 8090
Access via SSH tunnel:
ssh -L 8090:localhost:8090 user@server # Then visit http://localhost:8090
License¶
MIT
Changelog¶
v0.1.0 (2025-10-07)¶
Initial implementation
Traefik v3.3.5 support
Let’s Encrypt HTTP challenge
Systemd service with security hardening
Automatic version detection and upgrade
Multi-architecture support (amd64, arm64)
Checksum validation
Dashboard firewall controls
Log rotation configuration