How to Install and Configure Traefik Reverse Proxy on RHEL 7

Traefik is a modern, cloud-native reverse proxy and load balancer that differentiates itself from Nginx and HAProxy through its dynamic configuration model — routing rules can be updated at runtime without restarting the proxy. Originally designed for microservices and Docker environments, Traefik works equally well on bare-metal and VM deployments using file-based dynamic configuration. On RHEL 7, Traefik is distributed as a single statically-linked binary, making installation straightforward without any package repository dependencies. This guide covers downloading and installing Traefik, configuring it as a systemd service, setting up HTTP and HTTPS entrypoints with automatic Let’s Encrypt certificates, defining routers and services via file provider configuration, enabling the dashboard, and applying common middleware such as HTTP-to-HTTPS redirects, basic authentication, and security headers.

Prerequisites

  • RHEL 7 server with root access
  • A public domain name pointing to the server’s IP (required for Let’s Encrypt TLS certificates)
  • Ports 80 and 443 open in the firewall and accessible from the internet
  • One or more backend services already running on localhost ports (e.g., a web application on port 8080)
  • The curl and tar utilities installed (available by default on RHEL 7)

Step 1: Downloading the Traefik Binary

Traefik releases are published as pre-built binaries on GitHub. Check the latest stable v2.x release at https://github.com/traefik/traefik/releases and download the Linux AMD64 build:

# Set the version to install (check GitHub releases for the latest)
TRAEFIK_VERSION="v2.11.0"

cd /tmp
curl -LO "https://github.com/traefik/traefik/releases/download/${TRAEFIK_VERSION}/traefik_${TRAEFIK_VERSION}_linux_amd64.tar.gz"

# Verify the checksum (recommended)
curl -LO "https://github.com/traefik/traefik/releases/download/${TRAEFIK_VERSION}/traefik_${TRAEFIK_VERSION}_checksums.txt"
sha256sum -c traefik_${TRAEFIK_VERSION}_checksums.txt --ignore-missing

Extract and install the binary:

tar xzf traefik_${TRAEFIK_VERSION}_linux_amd64.tar.gz
install -m 755 traefik /usr/local/bin/traefik

# Verify
traefik version

Step 2: Creating the Directory Structure and User

Create a dedicated unprivileged system user and the required directories:

# Create system user with no login shell
useradd -r -s /sbin/nologin -d /etc/traefik traefik

# Create config directories
mkdir -p /etc/traefik/conf.d
mkdir -p /var/log/traefik
mkdir -p /etc/traefik/acme

# Set ownership
chown -R traefik:traefik /etc/traefik
chown -R traefik:traefik /var/log/traefik

# ACME storage must be private — Let's Encrypt requires 0600
touch /etc/traefik/acme/acme.json
chmod 600 /etc/traefik/acme/acme.json
chown traefik:traefik /etc/traefik/acme/acme.json

Grant the binary capability to bind to privileged ports (80, 443) without running as root:

yum install -y libcap
setcap 'cap_net_bind_service=+ep' /usr/local/bin/traefik

Step 3: Creating the Static Configuration (traefik.yml)

Traefik uses a two-tier configuration model. The static configuration (traefik.yml) defines entrypoints, providers, logging, and certificate resolvers. The dynamic configuration (files in /etc/traefik/conf.d/) defines routers, services, and middleware and can be reloaded without restarting Traefik.

vi /etc/traefik/traefik.yml
# Traefik v2 Static Configuration
# /etc/traefik/traefik.yml

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

accessLog:
  filePath: /var/log/traefik/access.log
  bufferingSize: 100

api:
  dashboard: true
  insecure: false   # dashboard served via a secure router defined in dynamic config

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true

  websecure:
    address: ":443"
    http:
      tls:
        certResolver: letsencrypt

certificatesResolvers:
  letsencrypt:
    acme:
      email: [email protected]
      storage: /etc/traefik/acme/acme.json
      httpChallenge:
        entryPoint: web

providers:
  file:
    directory: /etc/traefik/conf.d
    watch: true      # reload dynamic config automatically when files change

The watch: true directive causes Traefik to monitor /etc/traefik/conf.d/ for changes and apply new routing rules without a restart — this is Traefik’s key operational advantage.

Step 4: Creating the systemd Service Unit

vi /etc/systemd/system/traefik.service
[Unit]
Description=Traefik Reverse Proxy
Documentation=https://doc.traefik.io/traefik/
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
User=traefik
Group=traefik
ExecStart=/usr/local/bin/traefik --configFile=/etc/traefik/traefik.yml
Restart=on-failure
RestartSec=5s

# Security hardening
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ReadWritePaths=/etc/traefik/acme /var/log/traefik

# Resource limits
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable traefik --now
systemctl status traefik

Check the log for startup errors:

journalctl -u traefik -n 50 --no-pager

Step 5: Configuring Routers and Services in Dynamic Config

Create the first dynamic configuration file to route traffic to a backend application running on port 8080:

vi /etc/traefik/conf.d/myapp.yml
http:
  routers:
    myapp:
      rule: "Host(`app.example.com`)"
      entryPoints:
        - websecure
      service: myapp-backend
      tls:
        certResolver: letsencrypt
      middlewares:
        - security-headers

  services:
    myapp-backend:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:8080"
        healthCheck:
          path: /health
          interval: 10s
          timeout: 5s
          scheme: http

Traefik will detect this file immediately (due to watch: true) and begin routing requests for app.example.com to the backend. TLS certificates will be issued automatically via Let’s Encrypt’s HTTP-01 challenge.

Step 6: Configuring Middleware

Middleware in Traefik transforms requests or responses before they reach a service. Create a shared middleware file:

vi /etc/traefik/conf.d/middleware.yml
http:
  middlewares:
    # Redirect HTTP to HTTPS (also defined at entrypoint level for global redirect)
    redirect-to-https:
      redirectScheme:
        scheme: https
        permanent: true

    # Basic authentication for protected endpoints
    # Generate password hash: htpasswd -nb admin 'MyPassword'
    basicauth-admin:
      basicAuth:
        users:
          - "admin:$2y$10$abcdefghijklmnopqrstuvXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        realm: "Traefik Dashboard"
        removeHeader: true

    # Security response headers
    security-headers:
      headers:
        stsSeconds: 31536000
        stsIncludeSubdomains: true
        stsPreload: true
        forceSTSHeader: true
        contentTypeNosniff: true
        browserXssFilter: true
        referrerPolicy: "strict-origin-when-cross-origin"
        frameDeny: true
        customResponseHeaders:
          X-Powered-By: ""
          Server: ""

    # Rate limiting (100 requests/second average, burst 200)
    rate-limit:
      rateLimit:
        average: 100
        burst: 200

Generate a bcrypt password hash for basic auth (install httpd-tools for htpasswd):

yum install -y httpd-tools
htpasswd -nb admin 'MySecurePassword'
# Output: admin:$apr1$xxxx$yyyyyyyyyyyyyyyyyyyyyyyyyyy

Step 7: Exposing the Traefik Dashboard Securely

The dashboard is a built-in web UI showing active routers, services, and middleware. Expose it on a dedicated subdomain with basic auth:

vi /etc/traefik/conf.d/dashboard.yml
http:
  routers:
    dashboard:
      rule: "Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
      entryPoints:
        - websecure
      service: api@internal
      tls:
        certResolver: letsencrypt
      middlewares:
        - basicauth-admin
        - security-headers

Browse to https://traefik.example.com/dashboard/ (note the trailing slash) and log in with the credentials defined in your basicauth middleware. The dashboard shows real-time routing topology, health check status, and certificate details.

Step 8: Opening Firewall Ports

firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
firewall-cmd --list-services

Step 9: Testing the Configuration

Verify the HTTP-to-HTTPS redirect works:

curl -v http://app.example.com/ 2>&1 | grep -E 'Location|HTTP/'
# Expect: HTTP/1.1 301 Moved Permanently
# Expect: Location: https://app.example.com/

Test HTTPS and check certificate:

curl -v https://app.example.com/ 2>&1 | grep -E 'subject|issuer|HTTP/'

# Check response headers include security headers
curl -I https://app.example.com/ | grep -E 'Strict-Transport|X-Frame|X-Content'

Verify the Traefik API is responding:

curl -sk -u admin:MySecurePassword https://traefik.example.com/api/rawdata | python -m json.tool | head -50

Watch the access log in real time:

tail -f /var/log/traefik/access.log

Conclusion

Traefik on RHEL 7 combines the simplicity of a single binary deployment with powerful dynamic routing capabilities that would otherwise require complex Nginx reload scripts or HAProxy hot-reload mechanisms. By structuring configuration into a static traefik.yml for infrastructure-level settings and watched drop-in files under /etc/traefik/conf.d/ for application routing, you can add, modify, or remove routes for new services without any service interruption. Automatic Let’s Encrypt certificate issuance and renewal, combined with the security headers middleware and basic auth protection on the dashboard, gives you a production-ready reverse proxy setup that scales from a single application on one server to dozens of services as your infrastructure grows.