Configure Traefik with Consul service discovery for dynamic load balancing

Intermediate 25 min Apr 18, 2026 148 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up Traefik 3.1 reverse proxy with Consul service discovery to automatically route traffic to services without manual configuration. Learn dynamic routing, SSL automation, health checks, and monitoring setup for production environments.

Prerequisites

  • Root or sudo access
  • Basic understanding of reverse proxies
  • Domain name for SSL certificates

What this solves

Traefik with Consul service discovery automatically routes traffic to your services without manual configuration updates. When you deploy or scale services, Consul registers them and Traefik immediately starts load balancing traffic based on health checks and routing rules.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you get the latest versions.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install required packages

Install curl and unzip to download Consul and Traefik binaries.

sudo apt install -y curl unzip wget
sudo dnf install -y curl unzip wget

Download and install Consul

Download the latest Consul binary and install it in the system PATH.

curl -fsSL https://releases.hashicorp.com/consul/1.17.0/consul_1.17.0_linux_amd64.zip -o consul.zip
unzip consul.zip
sudo mv consul /usr/local/bin/
sudo chmod +x /usr/local/bin/consul
consul --version

Create Consul user and directories

Create a dedicated user for Consul and set up the necessary directories with proper permissions.

sudo useradd --system --home /etc/consul.d --shell /bin/false consul
sudo mkdir -p /opt/consul /etc/consul.d
sudo chown -R consul:consul /opt/consul /etc/consul.d
sudo chmod 755 /opt/consul /etc/consul.d

Configure Consul server

Create the main Consul configuration file with clustering and service discovery settings.

{
  "datacenter": "dc1",
  "data_dir": "/opt/consul",
  "log_level": "INFO",
  "server": true,
  "bootstrap_expect": 1,
  "bind_addr": "0.0.0.0",
  "client_addr": "0.0.0.0",
  "retry_join": ["127.0.0.1"],
  "ui_config": {
    "enabled": true
  },
  "connect": {
    "enabled": true
  },
  "ports": {
    "grpc": 8502
  },
  "acl": {
    "enabled": false,
    "default_policy": "allow"
  }
}

Create Consul systemd service

Set up Consul as a systemd service for automatic startup and management.

[Unit]
Description=Consul
Documentation=https://www.consul.io/
Requires=network-online.target
After=network-online.target
ConditionFileNotEmpty=/etc/consul.d/consul.json

[Service]
Type=notify
User=consul
Group=consul
ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d/
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Start and enable Consul

Start Consul and configure it to start automatically on boot.

sudo systemctl daemon-reload
sudo systemctl enable --now consul
sudo systemctl status consul

Download and install Traefik

Download Traefik 3.1 binary and install it in the system PATH.

curl -fsSL https://github.com/traefik/traefik/releases/download/v3.1.0/traefik_v3.1.0_linux_amd64.tar.gz -o traefik.tar.gz
tar -xzf traefik.tar.gz
sudo mv traefik /usr/local/bin/
sudo chmod +x /usr/local/bin/traefik
traefik version

Create Traefik user and directories

Create a dedicated user for Traefik and set up configuration directories.

sudo useradd --system --home /var/lib/traefik --shell /bin/false traefik
sudo mkdir -p /etc/traefik /var/lib/traefik /var/log/traefik
sudo chown -R traefik:traefik /etc/traefik /var/lib/traefik /var/log/traefik
sudo chmod 755 /etc/traefik /var/lib/traefik
sudo chmod 750 /var/log/traefik

Configure Traefik with Consul integration

Create the main Traefik configuration file with Consul service discovery and Let's Encrypt SSL automation.

global:
  checkNewVersion: false
  sendAnonymousUsage: false

serversTransport:
  insecureSkipVerify: true

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entrypoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

providers:
  consul:
    endpoints:
      - "127.0.0.1:8500"
    watch: true
    exposedByDefault: false
    defaultRule: "Host({{ .Name }}.example.com)"
  consulCatalog:
    prefix: traefik
    exposedByDefault: false
    endpoints:
      - "127.0.0.1:8500"
    watch: true

certificatesResolvers:
  letsencrypt:
    acme:
      email: admin@example.com
      storage: "/var/lib/traefik/acme.json"
      httpChallenge:
        entryPoint: web

api:
  dashboard: true
  debug: true

log:
  level: INFO
  filePath: "/var/log/traefik/traefik.log"

accessLog:
  filePath: "/var/log/traefik/access.log"

metrics:
  prometheus:
    addEntryPointsLabels: true
    addServicesLabels: true

Set secure permissions for ACME storage

Create and secure the ACME certificate storage file with proper permissions.

sudo touch /var/lib/traefik/acme.json
sudo chown traefik:traefik /var/lib/traefik/acme.json
sudo chmod 600 /var/lib/traefik/acme.json

Create Traefik systemd service

Set up Traefik as a systemd service with proper security constraints.

[Unit]
Description=Traefik
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/traefik --configfile=/etc/traefik/traefik.yml
Restart=on-failure
RestartSec=5
User=traefik
Group=traefik
StandardOutput=journal
StandardError=journal
SyslogIdentifier=traefik
KillMode=mixed
KillSignal=SIGTERM

Security settings

NoNewPrivileges=yes PrivateTmp=yes PrivateDevices=yes ProtectHome=yes ProtectSystem=strict ReadWritePaths=/var/lib/traefik /var/log/traefik CapabilityBoundingSet=CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_BIND_SERVICE [Install] WantedBy=multi-user.target

Configure firewall rules

Open the necessary ports for Traefik HTTP/HTTPS and Consul communication.

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 8500/tcp
sudo ufw allow 8300/tcp
sudo ufw reload
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --permanent --add-port=8500/tcp
sudo firewall-cmd --permanent --add-port=8300/tcp
sudo firewall-cmd --reload

Start and enable Traefik

Start Traefik and configure it to start automatically on boot.

sudo systemctl daemon-reload
sudo systemctl enable --now traefik
sudo systemctl status traefik

Register a sample service in Consul

Create a sample web service registration to test the Traefik-Consul integration.

{
  "ID": "web-app-1",
  "Name": "web-app",
  "Tags": [
    "traefik.enable=true",
    "traefik.http.routers.web-app.rule=Host(web-app.example.com)",
    "traefik.http.routers.web-app.tls=true",
    "traefik.http.routers.web-app.tls.certresolver=letsencrypt",
    "traefik.http.services.web-app.loadbalancer.server.port=8080"
  ],
  "Address": "127.0.0.1",
  "Port": 8080,
  "Check": {
    "HTTP": "http://127.0.0.1:8080/health",
    "Interval": "10s",
    "Timeout": "5s"
  }
}

Register the service with Consul

Use the Consul API to register the sample service for testing.

curl -X PUT -d @/tmp/sample-service.json http://localhost:8500/v1/agent/service/register

Configure Traefik dashboard access

Create a separate configuration file for secure dashboard access.

http:
  routers:
    dashboard:
      rule: "Host(traefik.example.com)"
      tls:
        certResolver: letsencrypt
      service: "api@internal"
      middlewares:
        - "dashboard-auth"
  middlewares:
    dashboard-auth:
      basicAuth:
        users:
          - "admin:$2y$10$8K6zGz7gO.4xFz7L8O4YBOxP7SqEcNz2V8wA5c9vQ7XYz1b2c3d4e"

Configure health checks and monitoring

Create health check endpoint

Set up a simple health check service to demonstrate Consul health monitoring.

#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
import json

class HealthHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/health':
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            response = {'status': 'healthy', 'service': 'web-app'}
            self.wfile.write(json.dumps(response).encode())
        else:
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write(b'

Sample Web Application

') if __name__ == '__main__': server = HTTPServer(('localhost', 8080), HealthHandler) print('Starting health check server on port 8080') server.serve_forever()

Run the sample service

Start the sample web service to test health checks and load balancing.

sudo chmod +x /tmp/health-server.py
python3 /tmp/health-server.py &

Configure log rotation

Set up log rotation for Traefik to prevent disk space issues.

/var/log/traefik/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 traefik traefik
    postrotate
        systemctl reload traefik
    endscript
}

Configure SSL automation and security

Test SSL certificate generation

Verify that Let's Encrypt certificates are being generated automatically.

sudo journalctl -u traefik -f

Configure security headers middleware

Add security headers to all services through Traefik middleware.

http:
  middlewares:
    security-headers:
      headers:
        frameDeny: true
        sslRedirect: true
        browserXssFilter: true
        contentTypeNosniff: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 31536000
        customRequestHeaders:
          X-Forwarded-Proto: "https"
        customResponseHeaders:
          X-Robots-Tag: "noindex,nofollow,nosnippet,noarchive"
    rate-limit:
      rateLimit:
        burst: 100
        average: 50

Update Traefik configuration to include security

Modify the main Traefik configuration to load additional configuration files.

sudo sed -i '/providers:/a\  file:\n    directory: /etc/traefik\n    watch: true' /etc/traefik/traefik.yml
sudo systemctl restart traefik

Verify your setup

Check that all services are running and communicating properly.

# Check Consul status
consul members
curl -s http://localhost:8500/v1/status/leader

Check registered services

curl -s http://localhost:8500/v1/catalog/services | python3 -m json.tool

Check Traefik status

sudo systemctl status traefik curl -s http://localhost:8080/api/rawdata | python3 -m json.tool

Test service discovery

curl -s http://localhost:8500/v1/health/service/web-app

Check health of sample service

curl -s http://localhost:8080/health

Access the Consul UI at http://your-server-ip:8500 and Traefik dashboard at http://your-server-ip:8080 to verify the setup.

Common issues

SymptomCauseFix
Consul won't startPort 8500 already in usesudo ss -tulpn | grep :8500 to find conflicting process
Traefik can't connect to ConsulConsul not accessibleCheck curl http://localhost:8500/v1/status/leader
SSL certificates not generatingLet's Encrypt rate limits or DNS issuesCheck sudo journalctl -u traefik -f for ACME errors
Service not appearing in TraefikMissing traefik.enable=true tagAdd traefik.enable=true to service tags in Consul
502 Bad GatewayBackend service not respondingCheck service health in Consul UI and verify port configuration
Permission denied on ACME fileIncorrect file ownershipsudo chown traefik:traefik /var/lib/traefik/acme.json && sudo chmod 600
Never use chmod 777. It gives every user on the system full access to your files. Instead, fix ownership with chown and use minimal permissions like 644 for files and 755 for directories.

Next steps

Running this in production?

Want this handled for you? Setting up Traefik and Consul once is straightforward. Keeping them patched, monitored, backed up and tuned across environments is the harder part. See how we run infrastructure like this for European SaaS and e-commerce teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed devops services for businesses that depend on uptime. From initial setup to ongoing operations.