Nuxtstop

For all things nuxt.js

A complete Traefik configuration 🚥

A complete Traefik configuration 🚥
13 2

If you're lucky, someone else in your organization may have already configured Traefik, an HTTP reverse proxy and load balancer for microservices. Otherwise, you can follow their tutorial to quickly launch the application with docker-compose.

But, if you are ready to improve your installation, you can read the official documentation. Or, if you are like me, you may want to check other people's setups. 😉

I have decided to share with you my personal configuration of Traefik below. It can inspire you to explore concepts that you are not yet familiar with. I won't particularly describe each instruction, so if in doubt, check their documentation! 🤷

This configuration below is made for Docker Swarm and all files are written in YAML. If your configuration is in TOML format, you should be able to switch easily between them.

Static configuration (traefik.yml)

# Traefik static configuration file (/etc/traefik/traefik.yml)
# See https://doc.traefik.io/traefik/getting-started/configuration-overview/#the-static-configuration
# and https://doc.traefik.io/traefik/reference/static-configuration/cli/

api:
  dashboard: true # Enable the dashboard

# Certificate Resolvers are responsible for retrieving certificates from an ACME server
# See https://doc.traefik.io/traefik/https/acme/#certificate-resolvers
certificatesResolvers:
  letsEncrypt:
    acme:
      email: "letsEncrypt@benjaminrancourt.ca" # Email address used for registration
      storage: "/etc/traefik/acme/acme.json" # File or key used for certificates storage
      tlsChallenge: {}

entryPoints:
  http:
    address: ":80" # Create the HTTP entrypoint on port 80
    http:
      redirections: # HTTPS redirection (80 to 443)
        entryPoint:
          to: "https" # The target element
          scheme: "https" # The redirection target scheme
  https:
    address: ":443" # Create the HTTPS entrypoint on port 443

global:
  checknewversion: true # Periodically check if a new version has been released.
  sendanonymoususage: true # Periodically send anonymous usage statistics.

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock" # Listen to the UNIX Docker socket
    exposedByDefault: false # Only expose container that are explicitly enabled (using label traefik.enabled)
    network: "traefik-net" # Default network to use for connections to all containers.
    swarmmode: true # Activates the Swarm Mode (instead of standalone Docker).
    swarmModeRefreshSeconds: 15 # Defines the polling interval (in seconds) in Swarm Mode.
    watch: true # Watch Docker Swarm events
  file:
    filename: "/etc/traefik/config.yml" # Link to the dynamic configuration
    watch: true # Watch for modifications
  providersThrottleDuration: 10 # Configuration reload frequency

Enter fullscreen mode Exit fullscreen mode
The static configuration file, in the traefik.yml file.

Dynamic configuration (config.yml)

Psst, if you want to replace a value from any of the middleware below, check out my post titled How to override an HTTP header in Traefik!

# Traefik dynamic configuration file
# See https://doc.traefik.io/traefik/getting-started/configuration-overview/#the-dynamic-configuration

http:
  middlewares:
    # A basic authentification middleware, to protect the Traefik dashboard to anyone except myself
    # Use with traefik.http.routers.myRouter.middlewares: "traefikAuth@file"
    traefikAuth:
      basicAuth:
        users:
          - "admin:PASSWORD_HASHED"

    # Recommended default middleware for most of the services
    # Use with traefik.http.routers.myRouter.middlewares: "default@file"
    # Equivalent of traefik.http.routers.myRouter.middlewares: "default-security-headers@file,error-pages@file,gzip@file"
    default:
      chain:
        middlewares:
          - default-security-headers
          - error-pages
          - gzip

    # Add automatically some security headers
    # Use with traefik.http.routers.myRouter.middlewares: "default-security-headers@file"
    default-security-headers:
      headers:
        browserXssFilter: true # X-XSS-Protection=1; mode=block
        contentTypeNosniff: true # X-Content-Type-Options=nosniff
        forceSTSHeader: true # Add the Strict-Transport-Security header even when the connection is HTTP
        frameDeny: true # X-Frame-Options=deny
        referrerPolicy: "strict-origin-when-cross-origin"
        sslRedirect: true # Allow only https requests
        stsIncludeSubdomains: true # Add includeSubdomains to the Strict-Transport-Security header
        stsPreload: true # Add preload flag appended to the Strict-Transport-Security header
        stsSeconds: 63072000 # Set the max-age of the Strict-Transport-Security header (63072000 = 2 years)

    # Serve the error pages when the status is included inside the following ranges
    # Use with traefik.http.routers.myRouter.middlewares: "error-pages@file"
    error-pages:
      errors:
        query: "erreur{status}/"
        service: traefik-error-pages
        status:
          - "403-404"
          - "500"
          - "503"

    # Enables the GZIP compression (https://docs.traefik.io/middlewares/compress/)
    # if the response body is larger than 1400 bytes
    # if the Accept-Encoding request header contains gzip
    # if the response is not already compressed (Content-Encoding is not set)
    # Use with traefik.http.routers.myRouter.middlewares: "gzip@file"
    gzip:
      compress: {}

  services:
    # Error pages
    traefik-error-pages:
      loadBalancer:
        servers:
          - url: "https://www.usherbrooke.ca/error-pages/"

# See https://doc.traefik.io/traefik/https/tls/
tls:
  options:
    # To use with the label "traefik.http.routers.myrouter.tls.options=modern@file"
    modern:
      minVersion: "VersionTLS13" # Minimum TLS Version
      sniStrict: true # Strict SNI Checking

    # To use with the label "traefik.http.routers.myrouter.tls.options=intermediate@file"
    intermediate:
      cipherSuites:
        - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
        - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
        - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
        - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
        - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305"
        - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
      minVersion: "VersionTLS12" # Minimum TLS Version
      sniStrict: true # Strict SNI Checking

    # To use with the label "traefik.http.routers.myrouter.tls.options=old@file"
    old:
      cipherSuites:
        - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
        - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
        - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
        - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
        - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305"
        - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
        - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
        - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
        - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"
        - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
        - "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"
        - "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"
        - "TLS_RSA_WITH_AES_128_GCM_SHA256"
        - "TLS_RSA_WITH_AES_256_GCM_SHA384"
        - "TLS_RSA_WITH_AES_128_CBC_SHA256"
        - "TLS_RSA_WITH_AES_128_CBC_SHA"
        - "TLS_RSA_WITH_AES_256_CBC_SHA"
        - "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
      minVersion: "TLSv1" # Minimum TLS Version
      sniStrict: true # Strict SNI Checking

# Generated 2021-08-12, Mozilla Guideline v5.6, Traefik 2.4.8
# https://ssl-config.mozilla.org/#server=traefik&version=2.4.8&config=old&guideline=5.6
# https://ssl-config.mozilla.org/#server=traefik&version=2.4.8&config=intermediate&guideline=5.6
Enter fullscreen mode Exit fullscreen mode
The dynamic configuration file, in the config.yml file.

docker-compose.yml

version: "3.8"

services:
  traefik:
    deploy:
      labels:
        traefik.docker.network: "traefik-net"
        traefik.enable: "true"
        traefik.http.routers.traefik.entrypoints: "https"
        traefik.http.routers.traefik.middlewares: "traefikAuth@file,default@file"
        traefik.http.routers.traefik.rule: "Host(`${TRAEFIK_SUBDOMAIN}.${TRAEFIK_DOMAIN}`)"
        traefik.http.routers.traefik.service: "api@internal"
        traefik.http.routers.traefik.tls.certresolver: "letsEncrypt"
        traefik.http.routers.traefik.tls.options: "modern@file"
        traefik.http.routers.traefik.tls: "true"
        traefik.http.services.traefik.loadbalancer.server.port: 8080
        traefik.http.services.traefik.loadbalancer.sticky.cookie.httpOnly: "true"
        traefik.http.services.traefik.loadbalancer.sticky.cookie.secure: "true"
      mode: global
      # Schedule Traefik on the Swarm manager nodes, as the Swarm API is only exposed on the manager nodes
      # See https://docs.traefik.io/providers/docker/#docker-api-access_1
      placement:
        constraints:
          - node.role == manager
    # Published on https://hub.docker.com/_/traefik?tab=tags
    image: traefik:2.4.8 # See https://github.com/containous/traefik/releases
    networks:
      - traefik-net
    ports:
      # To be able to listen on port 80 (http)
      - mode: host
        published: 80
        target: 80
      # To be able to listen on port 443 (https)
      - mode: host
        published: 443
        target: 443
    volumes:
      - /etc/localtime:/etc/localtime:ro # Set the container timezone by sharing the read-only localtime
      - /home/ranb2002/traefik/config.yml:/etc/traefik/config.yml:ro # Set the dynamic configuration for the file provider
      - /home/ranb2002/traefik/traefik.yml:/etc/traefik/traefik.yml:ro # Set the static configuration
      - /var/opt/traefik:/etc/traefik/acme # Set the location where my ACME certificates are saved to
      - /var/run/docker.sock:/var/run/docker.sock:ro # Give access to the UNIX Docker socket

networks:
  traefik-net:
    driver: overlay
    external: true

Enter fullscreen mode Exit fullscreen mode
The docker-compose.yml file for Traefik.

If you want an example of another application using the Traefik labels, check out the Code section of my Testing certificates generated by Traefik and Let's Encrypt post.

If you have any tips for improving this setup, let me know! 😎