Traefik

Syncthing docker-compose setup using Traefik as reverse proxy with HTTP basic auth

This setup uses a docker-compose based syncthing setup and Traefik as reverse proxy. HTTP basic auth is used to prevent unauthorized access to the syncthing web UI. Alternatively, you can use the built-in password protection.

See Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges for my HTTPS setup for Traefik.

version: "3"
services:
  syncthing:
    image: syncthing/syncthing
    hostname: Syncthing-Myserver
    environment:
      - PUID=1000
      - PGID=1000
    volumes:
      - ./syncthing_data:/var/syncthing
    ports: # NOTE: 8384 not forwarded, this is handled by traefik
      - "22000:22000"
      - "21027:21027/udp"
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.syncthing.rule=Host(`syncthing.myserver.net`)"
      - "traefik.http.routers.syncthing.entrypoints=websecure"
      - "traefik.http.routers.syncthing.tls.certresolver=cloudflare"
      - "traefik.http.routers.syncthing.tls.domains[0].main=myserver.net"
      - "traefik.http.routers.syncthing.tls.domains[0].sans=*.myserver.net"
      - "traefik.http.services.syncthing.loadbalancer.server.port=8384"
      - "traefik.http.routers.syncthing.middlewares=syncthing-auth"
      # Auth (this is shared with the server). NOTE: generate with "htpasswd -n admin" and REPLACE EVERY "$" by "$$" IN THE OUTPUT!
      - "traefik.http.middlewares.syncthing-auth.basicauth.users=admin:$$apr1$$ehr8oqEZ$$tHoOVLG19oHdUe81IeePo1
"

 

Posted by Uli Köhler in Docker, Traefik

InvenTree Traefik reverse proxy container labels

This post is based on How to install InvenTree using docker in just 5 minutes and uses the auto-generated docker-compose.yml from there. However it should be useable for almost any setup.

The setup is pretty standard since the inventree proxy container runs the webserver on port 80. Therefore, you don’t even have to explicitly specify a load balancer port

In your docker-compose.yml, add the following labels to the inventree-proxy container:

Wildcard certificate setup:

For more details on the base Traefik setup, see Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges

labels:
    - "traefik.enable=true"
    - "traefik.http.routers.inventree-mydomain.rule=Host(`inventree.mydomain.com`)"
    - "traefik.http.routers.inventree-mydomain.entrypoints=websecure"
    - "traefik.http.routers.inventree-mydomain.tls.certresolver=cloudflare"
    - "traefik.http.routers.inventree-mydomain.tls.domains[0].main=mydomain.com"
    - "traefik.http.routers.inventree-mydomain.tls.domains[0].sans=*.mydomain.com"

 

Posted by Uli Köhler in InvenTree, Traefik

Traefik container labels for the Unifi controller via docker-compose

For the basic configuration & setup of the Unifi controller via docker-compose, see Simple Unifi controller setup using docker-compose ! This post just covers the Traefik label part.

This setup is based on our previous post on the Unifi docker-compose setup. Furthermore, our traefik configuration is discussed in more detail in our post on Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges.

For this example, we’ll use a wildcart Let’s Encrypt certificate for the domain *.mydomain.com via the Traefik certificate provider named cloudflare, with the Unifi controller running on unifi.mydomain.com

Here’s the container label config:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.unifi.rule=Host(`unifi.mydomain.com`)"
  - "traefik.http.routers.unifi.entrypoints=websecure"
  - "traefik.http.routers.unifi.tls.certresolver=cloudflare"
  - "traefik.http.routers.unifi.tls.domains[0].main=mydomain.com"
  - "traefik.http.routers.unifi.tls.domains[0].sans=*.mydomain.com"
  - "traefik.http.services.unifi.loadbalancer.server.port=8443"
  - "traefik.http.services.unifi.loadbalancer.server.scheme=https"

Note particularly these lines which make Traefik access the Unifi controller via HTTPS:

- "traefik.http.services.unifi.loadbalancer.server.port=8443"
- "traefik.http.services.unifi.loadbalancer.server.scheme=https"

Complete example

version: '2.3'
services:
  mongo_unifi:
    image: mongo:3.6
    network_mode: host
    restart: always
    volumes:
      - ./mongo_db:/data/db
      - ./mongo/dbcfg:/data/configdb
    command: mongod --port 29718
  controller:
    image: "jacobalberty/unifi:latest"
    depends_on:
      - mongo_unifi
    init: true
    network_mode: host
    restart: always
    volumes:
      - ./unifi_dir:/unifi
      - ./unifi_data:/unifi/data
      - ./unifi_log:/unifi/log
      - ./unifi_cert:/unifi/cert
      - ./unifi_init:/unifi/init.d
      - ./unifi_run:/var/run/unifi
      - ./unifi_backup:/unifi/data/backup
#    sysctls:
#      net.ipv4.ip_unprivileged_port_start: 0
    environment:
      - DB_URI=mongodb://localhost:29718/unifi
      - STATDB_URI=mongodb://localhost:29718/unifi_stat
      - DB_NAME=unifi
      - UNIFI_HTTP_PORT=8090
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.unifi.rule=Host(`unifi.mydomain.com`)"
      - "traefik.http.routers.unifi.entrypoints=websecure"
      - "traefik.http.routers.unifi.tls.certresolver=cloudflare"
      - "traefik.http.routers.unifi.tls.domains[0].main=mydomain.com"
      - "traefik.http.routers.unifi.tls.domains[0].sans=*.mydomain.com"
      - "traefik.http.services.unifi.loadbalancer.server.port=8443"
      - "traefik.http.services.unifi.loadbalancer.server.scheme=https"
# Ports commentet out since network mode is set to "host"
#    ports:
#      - "3478:3478/udp" # STUN
#      - "6789:6789/tcp" # Speed test
#      - "8080:8080/tcp" # Device/ controller comm.
#      - "8443:8443/tcp" # Controller GUI/API as seen in a web browser
#      - "8880:8880/tcp" # HTTP portal redirection
#      - "8843:8843/tcp" # HTTPS portal redirection
#      - "10001:10001/udp" # AP discovery
  logs:
    image: bash
    depends_on:
      - controller
    command: bash -c 'tail -F /unifi/log/*.log'
    restart: always
    volumes:
      - ./unifi_log:/unifi/log
Posted by Uli Köhler in Networking, Traefik

MikroTik webinterface reverse proxy using Traefik

The following Traefik .toml file which reverse proxies a MikroTik router’s WebFig webinterface is based on our Traefik setup from Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges. It assumes that the MikroTik router is reachable at 10.1.2.3 via HTTP.

No Authentication beyond the MikroTik router’s WebFig internal authentication is performed. However – at least when using our Traefik config from our previous post it enforces HTTPS i.e. encrypted access.

Save the following file under config/mikrotik01.toml. Traefik will automatically reload, no restart will be required.

[http.routers.mikrotik01]
rule = "Host(`mikrotik01.mydomain.com`)"
service = "mikrotik01"

[http.routers.mikrotik01.tls]
certresolver = "cloudflare"

[[http.routers.mikrotik01.tls.domains]]
main = "mydomain.com"
sans = ["*.mydomain.com"]

[http.services]
[http.services.mikrotik01.loadBalancer]
[[http.services.mikrotik01.loadBalancer.servers]]
url = "http://10.1.2.3.4/"

 

Posted by Uli Köhler in MikroTik, Networking, Traefik

A working Traefik & docker-compose minio setup with console

Note: I have not updated this config to use the xl or xl-single storage backends, hence the version is locked at RELEASE.2022-10-24T18-35-07Z

The following config works by using two domains: minio.mydomain.com and console.minio.mydomain.com.

For the basic Traefik setup this is based on, see Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges. Regarding this setup, the important part is to enabled the docker autodiscovery and defining the certificate resolve (we’re using the ALPN resolver).

Be sure to choose a random MINIO_ROOT_PASSWORD!

version: '3.5'
services:
   minio:
       image: quay.io/minio/minio:RELEASE.2022-10-24T18-35-07Z
       command: server --console-address ":9001" /data
       volumes:
          - ./data:/data
          - ./config:/root/.minio
       environment:
          - MINIO_ROOT_USER=minioadmin
          - MINIO_ROOT_PASSWORD=uikui5choRith0ZieV2zohN5aish5r
          - MINIO_DOMAIN=minio.mydomain.com
          - MINIO_SERVER_URL=https://minio.mydomain.com
          - MINIO_BROWSER_REDIRECT_URL=https://console.minio.mydomain.com
       labels:
          - "traefik.enable=true"
          # Console
          - "traefik.http.routers.minio-console.rule=Host(`console.minio.mydomain.com`)"
          - "traefik.http.routers.minio-console.entrypoints=websecure"
          - "traefik.http.routers.minio-console.tls.certresolver=alpn"
          - "traefik.http.routers.minio-console.service=minio-console"
          - "traefik.http.services.minio-console.loadbalancer.server.port=9001"
          # APi
          - "traefik.http.routers.minio.rule=Host(`minio.mydomain.com`)"
          - "traefik.http.routers.minio.entrypoints=websecure"
          - "traefik.http.routers.minio.tls.certresolver=alpn"
          - "traefik.http.routers.minio.service=minio"
          - "traefik.http.services.minio.loadbalancer.server.port=9000"

 

Posted by Uli Köhler in Container, Docker, S3, Traefik

How to fix Traefik Could not define the service name for the router: too many services

Problem:

Traefik does not load some of your services and you see an error message like the following one:

traefik_1  | time="2022-03-27T15:22:05Z" level=error msg="Could not define the service name for the router: too many services" routerName=myapp providerName=docker

with a docker label config with multiple routers like this:

labels:
    - "traefik.enable=true"
    - "traefik.http.routers.myapp-console.rule=Host(`console.myapp.mydomain.com`)"
    - "traefik.http.routers.myapp-console.entrypoints=websecure"
    - "traefik.http.routers.myapp-console.tls.certresolver=alpn"
    - "traefik.http.services.myapp-console.loadbalancer.server.port=9001"
    #
    - "traefik.http.routers.myapp.rule=Host(`myapp.mydomain.com`)"
    - "traefik.http.routers.myapp.entrypoints=websecure"
    - "traefik.http.routers.myapp.tls.certresolver=cloudflare-techoverflow"
    - "traefik.http.routers.myapp.tls.domains[0].main=mydomain.com"
    - "traefik.http.routers.myapp.tls.domains[0].sans=*.mydomain.com"
    - "traefik.http.services.myapp.loadbalancer.server.port=9000"

Solution:

The basic issue here is that you have multiple routers defined for a single docker container and Traefik does not know which http.services belongs to which http.routers!

In order to fix this, explicitly tell traefik for each router what service it should use like this:

- "traefik.http.routers.myapp-console.service=myapp-console"

Full example:

labels:
    - "traefik.enable=true"
    - "traefik.http.routers.myapp-console.rule=Host(`console.myapp.mydomain.com`)"
    - "traefik.http.routers.myapp-console.entrypoints=websecure"
    - "traefik.http.routers.myapp-console.tls.certresolver=alpn"
    - "traefik.http.routers.myapp-console.service=myapp-console"
    - "traefik.http.services.myapp-console.loadbalancer.server.port=9001"
    #
    - "traefik.http.routers.myapp.rule=Host(`myapp.mydomain.com`)"
    - "traefik.http.routers.myapp.entrypoints=websecure"
    - "traefik.http.routers.myapp.tls.certresolver=cloudflare-techoverflow"
    - "traefik.http.routers.myapp.tls.domains[0].main=mydomain.com"
    - "traefik.http.routers.myapp.tls.domains[0].sans=*.mydomain.com"
    - "traefik.http.routers.myapp.service=myapp"
    - "traefik.http.services.myapp.loadbalancer.server.port=9000"

 

Posted by Uli Köhler in Container, Docker, Networking, Traefik

Traefik TOML config for frontend and /api backend

The following Traefik .toml config files work by redirecting /api requests to the backend server running on localhost:61913 while redirecting any request besides /api to the frontend running on localhost:17029. You can simply define the frontend rule as

rule = "Host(`myapp.mydomain.com`)"

and the backend rule as

rule = "Host(`myapp.mydomain.com`) && PathPrefix(`/api`)"

since the longest matching route will win.

See our poist Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges for our basic Traefik config, which also defines the alpn certificate resolver. With this config, place both the myapp-frontend.toml and myapp-backend.toml in the config directory.

Frontend config

# Host
[http.routers.myapp-frontend]
rule = "Host(`myapp.mydomain.com`)"
service = "myapp-frontend"

# Backend
[http.services]
[http.services.myapp-frontend.loadBalancer]
[[http.services.myapp-frontend.loadBalancer.servers]]
url = "http://127.0.0.1:17029/"

# Certificates
[http.routers.myapp-frontend.tls]
certresolver = "alpn"

Backend Traefik config

# Host
[http.routers.myapp-backend]
rule = "Host(`myapp.mydomain.com`) && PathPrefix(`/api`)"
service = "myapp-backend"

# Backend
[http.services]
[http.services.myapp-backend.loadBalancer]
[[http.services.myapp-backend.loadBalancer.servers]]
url = "http://127.0.0.1:61913/"

# Certificates
[http.routers.myapp-backend.tls]
certresolver = "alpn"

 

Posted by Uli Köhler in Networking, Traefik

Traefik docker container labels for custom port & ALPN certificate

See our previous post Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges for the general config we’re using to deploy Traefik. This includes the configuration of the alpn certificate resolver.

If you want to automatically connect Traefik to your docker container on a specific port running on the docker container (17029 in this example), use labels like

    labels:
        - "traefik.enable=true"
        - "traefik.http.routers.my-webservice.rule=Host(`subdomain.mydomain.com`)"
        - "traefik.http.routers.my-webservice.entrypoints=websecure"
        - "traefik.http.routers.my-webservice.tls.certresolver=alpn"
        - "traefik.http.services.my-webservice.loadbalancer.server.port=17029"

 

Posted by Uli Köhler in Traefik

Traefik API config example using Wildcard certificates and HTTP username/password (basic auth)

Based on our previous post Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges this is the TOML config I use to allow access to the Traefik dashboard using HTTPS and my Let’s encrypt wildcard certificate. In this example, it will be reachable under traefik.mydomain.com. Place the config in /opt/traefik/conf/api.toml assuming you have setup Traefik based on our example.

[http.routers.traefik-api]
rule = "Host(`traefik.mydomain.com`)"
service = "api@internal"
middlewares = ["auth"]
[http.routers.traefik-api.tls]
certresolver = "cloudflare"
[[http.routers.traefik-api.tls.domains]]
main = "mydomain.com"
sans = ["*.mydomain.com"]

[http.middlewares.auth.basicAuth]
users = [
  "admin:$apr1$ocvmQb0w$Bwlbz3V2VVRZlcu46X0zK0",
]

Create a new password string using htpasswd:

htpasswd -n admin

When prompted, enter the password and then copy the password such as admin:$apr1$ocvmQb0w$Bwlbz3V2VVRZlcu46X0zK0 to the [http.middlewares.auth.basicAuth] section:

[http.middlewares.auth.basicAuth]
users = [
  "COPY IT HERE"
]

It should look like our full example above.

Posted by Uli Köhler in Traefik

Traefik docker container labels for wildcard certificate using Cloudflare

See our previous post Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges for the general config we’re using to deploy Traefik.

If you want to automatically connect Traefik to your docker container, use labels like

   labels:
     - "traefik.enable=true"
     - "traefik.http.routers.homeassistant.rule=Host(`homeassistant.mydomain.com`)"
     - "traefik.http.routers.homeassistant.entrypoints=websecure"
     - "traefik.http.routers.homeassistant.tls.certresolver=cloudflare"
     - "traefik.http.routers.homeassistant.tls.domains[0].main=mydomain.com"
     - "traefik.http.routers.homeassistant.tls.domains[0].sans=*.mydomain.com"
     - "traefik.http.services.homeassistant.loadbalancer.server.port=80"

 

Posted by Uli Köhler in Traefik

Traefik wildcard Lets Encrypt certificate reverse proxy example

The following example builds on our config from Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges

This config (placed in /etc/traefik/conf/myservice.toml – which is mapped to ./conf/myservice.toml i.e. /opt/traefik/conf/myservice.toml in our docker-compose example) generates a wildcard certificate for *.mydomain.com (also including just mydomain.com) using the cloudflare certificate provider and uses said wildcard certificate for myservice.mydomain.com and any other *.mydomain.com backends you have configured.

This config will reverse proxy all traffic on myservice.mydomain.com to 192.168.178.233:8080

# Host
[http.routers.myservice]
rule = "Host(`myservice.mydomain.com`)"
service = "myservice"

# Backend
[http.services]
[http.services.myservice.loadBalancer]
[[http.services.myservice.loadBalancer.servers]]
url = "http://192.168.178.233:8080/"

# Certificates
[http.routers.myservice.tls]
certresolver = "cloudflare"
[[http.routers.myservice.tls.domains]]
main = "mydomain.com"
sans = ["*.mydomain.com"]

Note that cloudflare in certresolver = "cloudflare" refers to the provider configured using

--certificatesresolvers.cloudflare....

but you can choose any other name with the cloudflare method such as --certificatesresolvers.myprovider.acme.dnschallenge.provider=cloudflare in which case the provider will be referred to as myprovider !

Posted by Uli Köhler in Networking, Traefik

Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges

This is my setup using docker-compose to start Traefik, supporting all major encryption providers. I recommend to create the /opt/traefikdirectory and save the following file as /opt/traefik/docker-compose.yml. This config has the fileand docker providers enabled by default.

version: "3.4"
services:
  traefik:
    image: "traefik:v2.8"
    network_mode: "host" 
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.file.directory=/etc/traefik/conf"
      - "--providers.file.watch=true"
      - "--entrypoints.web.address=:80"
      - "--entryPoints.web.http.redirections.entryPoint.to=websecure"
      - "--entryPoints.web.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.websecure.address=:443"
      - "--log.level=info"
      - "--serversTransport.insecureSkipVerify=true"
#
      - "--certificatesresolvers.cloudflare.acme.dnschallenge=true"
      - "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"
      - "--certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
      - "--certificatesresolvers.cloudflare.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.cloudflare.acme.email=letsencrypt@mydomain.com"
      - "--certificatesresolvers.cloudflare.acme.KeyType=EC256"
      - "--certificatesresolvers.cloudflare.acme.storage=/letsencrypt/acme.json"
#
      - "--certificatesresolvers.cloudflare-staging.acme.dnschallenge=true"
      - "--certificatesresolvers.cloudflare-staging.acme.dnschallenge.provider=cloudflare"
      - "--certificatesresolvers.cloudflare-staging.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
      - "--certificatesresolvers.cloudflare-staging.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.cloudflare-staging.acme.email=letsencrypt@mydomain.com"
      - "--certificatesresolvers.cloudflare-staging.acme.KeyType=EC256"
      - "--certificatesresolvers.cloudflare-staging.acme.storage=/letsencrypt/acme.json"
#
      - "--certificatesresolvers.alpn.acme.tlsChallenge=true"
      - "--certificatesresolvers.alpn.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
      - "[email protected]"
      - "--certificatesresolvers.alpn.acme.KeyType=EC256"
      - "--certificatesresolvers.alpn.acme.storage=/letsencrypt/acme.json"
#
      - "--certificatesresolvers.alpn-staging.acme.tlsChallenge=true"
      - "--certificatesresolvers.alpn-staging.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.alpn-staging.acme.email=letsencrypt@mydomain.com"
      - "--certificatesresolvers.alpn-staging.acme.KeyType=EC256"
      - "--certificatesresolvers.alpn-staging.acme.storage=/letsencrypt/acme.json"
    environment:
      - [email protected]
      - CLOUDFLARE_API_KEY=XYZABC123
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./conf:/etc/traefik/conf:ro"

Replace [email protected] by the Email address to register certificates to. Also ensure to change

- [email protected]
- CLOUDFLARE_API_KEY=XYZABC123

Optionally, create a Pilot token and set it (don’t forget to un-comment the line) using

# - "--pilot.token=PILOT_TOKEN_HERE"

Now let’s make the service autostart on boot (and start it right now) using the method detailed in docker-compose systemd .service generator: Run the following in /opt/traefik

curl -fsSL https://techoverflow.net/scripts/create-docker-compose-service.sh | sudo bash /dev/stdin

We will detail how to get access to the Traefik API in followup posts.

 

 

Posted by Uli Köhler in Networking, Traefik

How to export certificates from Traefik certificate store

Traefik stores certificates as base64 encoded X.509 certificates and keys inside the certificate store.

This is a python script to export certificate from Traefik certificate store .json file:

import json
import base64

# Read Traefik ACME JSON
with open("acme.json") as acme_file:
    acme = json.load(acme_file)

# Select certificates from a specific resolver
resolver_name = "my-resolver"
certificates = acme[resolver_name]["Certificates"]

# Find the specific certificate we are looking for
certificate = [certificate for certificate in certificates if "myddomain.com" in certificate["domain"].get("sans", [])][0]

# Extract X.509 certificate data
certificate_data = base64.b64decode(certificate["certificate"])
key_data = base64.b64decode(certificate["key"])

# Export certificate and key to file
with open("certificate.pem", "wb") as certfile:
    certfile.write(certificate_data)

with open("key.pem", "wb") as keyfile:
    keyfile.write(key_data)

Note that depending on what is the primary name for your certificate, you might need to use

if "myddomain.com" == certificate["domain"]["main"]

instead of

if "myddomain.com" in certificate["domain"].get("sans", [])

 

Posted by Uli Köhler in Python, Traefik

How to fix Traefik “Gateway Timeout” for Docker services

Problem

If you have setup your Traefik instance with Docker providers, you will often encounter an issue where every service running on Docker or docker-compose will return

Gateway Timeout

(HTTP response 504) after a couple of seconds.

Why does the gateway timeout occur?

This issue is caused by the Traefik instance not being on the same Docker network(s) as the containers running the services. Therefore, the IP address of the traefik container is firewalled from being able to access the IP addresses of the docker containers.

There are two ways to fix this issue.

Preferred solution: Use host networking

The host is able to access all docker container IP addresses. Therefore, we can operate the traefik contaienr with network_mode: "host" so it doesn’t receive a separate IP address in a separate network but uses the hosts’s IP address and ports directly.

In order enable host networking in a docker-compose-based setup, use

network_mode: "host" 

For example:

version: "3.3"
services:
  traefik:
    image: "traefik:v2.4.8"
    network_mode: "host"
# [...]

The approach of using host network also has the added advantage of increasing traefik throughput, since you don’t need any docker port forwarding but the host ports (like port 80 for HTTP and port 443 for HTTPS) are connected directly to traefik.

Alternate solution: Add traefik to every docker network

You can also add the traefik instance to each and every docker network where a service container is located. This will work, but you need to remember to add the traefik instance to every docker container. Since this is not only often a lot of work (especially if you have many services with separate networks running in your setup)

Posted by Uli Köhler in Traefik

Traefik docker-compose configuration with secure dashboard and Let’s Encrypt

This configuration only provides only the minimum to get the Traefik Dashboard running with Let’s Encrypt-driven SSL encryption and user authentication. It also redirects all HTTP requests to HTTPS in order to avoid insecure access to the Dashboard and other services.

Let’s encrypt is used with the HTTP-01 challenge. This means that Traefik MUST be reachable by Port 80 from the Internet.

In order to install docker & docker-compose, see How to install docker and docker-compose on Ubuntu in 30 seconds.

First prepare the directory (/var/lib/traefik):

sudo mkdir /var/lib/traefik
sudo chown -R $USER: /var/lib/traefik
cd /var/lib/traefik
mkdir acme conf

Now create docker-compose.yml:

version: "3.3"

services:
  traefik:
    image: "traefik:v2.3"
    container_name: "traefik"
    command:
      - "--api=true"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./acme:/etc/traefik/acme"
      - "./traefik.toml:/etc/traefik/traefik.toml"
      - "./conf:/etc/traefik/conf"

Now create the main traefik.toml configuration file:

defaultEntryPoints = ["http", "https"]

[api]
dashboard = true

# You can create config files in /var/lib/traefik/traefik.conf and Traefik will automatically reload them
[providers]
[providers.file]
directory = "/etc/traefik/conf/"
watch = true

# Change this to INFO if you don't want as much debug output
[log]
level = "DEBUG"

[entryPoints.web]
address = ":80"
[entryPoints.web.http]
[entryPoints.web.http.redirections]
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
[entryPoints.websecure]
address = ":443"

[certificatesResolvers.letsencrypttls.acme]
# TODO Add your email here
email = "[email protected]"
storage = "/etc/traefik/acme/acme.json"
[certificatesResolvers.letsencrypttls.acme.httpChallenge]
entryPoint = "web"

Now we need to create the API config file in conf/api.toml:

[http.routers.traefik-api]
# TODO: Set your domain here !!!
rule = "Host(`traefik.example.com`)"
service = "api@internal"
middlewares = ["auth"]
[http.routers.traefik-api.tls]
certresolver = "letsencrypttls"
[http.middlewares.auth.basicAuth]
# TODO Add your admin user & password here, generate e.g. using https://wtools.io/generate-htpasswd-online
users = [
  "admin:$1$ySFBr~_y$GsKgEasDQkpCX8sO8vNia0",
]

Don’t forget to change your email address and the domain name in the config files (marked by TODO). Ensure you have setup all DNS records correctly so that your domains points to the server running Traefik!

Now it’s time to startup Traefik for the first time:

docker-compose up

Traefik will take a few seconds to automatically generate the Let’s Encrypt certificate for your domain. Once you see a message like

traefik    | time="2020-09-20T23:48:30Z" level=debug msg="Certificates obtained for domains [traefik.mydomain.com]" providerName=letsencrypttls.acme routerName=traefik-api@file rule="Host(`traefik.mydomain.com`)"

the certificate is available and loaded automatically.

Now you can go to https://traefik.mydomain.com/ , login with the username and password you have generated and check out the dashboard.

 

If desired, you can also setup a systemd service to automatically start Traefik on boot (generated using docker-compose systemd .service generator). In order to do this, first stop the running docker-compose instance using Ctrl-C if you still have the terminal open and docker-compose down.

Now add this as /etc/systemd/system/traefik.service:

[Unit]
Description=traefik
Requires=docker.service
After=docker.service

[Service]
Restart=always
User=root
Group=docker
WorkingDirectory=/var/lib/traefik
# Shutdown container (if running) when unit is stopped
ExecStartPre=/usr/local/bin/docker-compose -f docker-compose.yml down -v
# Start container when unit is started
ExecStart=/usr/local/bin/docker-compose -f docker-compose.yml up
# Stop container when unit is stopped
ExecStop=/usr/local/bin/docker-compose -f docker-compose.yml down -v

[Install]
WantedBy=multi-user.target

and run

sudo systemctl enable traefik.service
sudo systemctl start traefik.service

 

Posted by Uli Köhler in Traefik

How to fix Traefik Dashboard/API 404 page not found “api is not enabled”

Problem:

You are trying to configure the Traefik API/Dashboard in a secure way, but every time you try to access the API, you’re only getting a 404 error (unless you set api.insecure=true)

In the logs, you see an error message like this: (if log.level = "DEBUG"):

traefik    | time="2020-09-20T22:53:51Z" level=error msg="api is not enabled" routerName=my-api@file entryPointName=websecure

Solution:

You have to pass --api=true to Traefik, e.g. using docker-compose:

command:
  - "--api=true"

and also set

[api]
dashboard = true

in your traefik.toml.

After that, restart Traefik and you should be able to access your dashboard at /dashboard.

Credits to multiple GitHub users for the original solution.

Posted by Uli Köhler in Traefik

How to fix Traefik “command traefik error: field not found, node: dnsProvider”

Problem:

You are trying to configure your Traefik server but you see an error message like

traefik    | 2020/09/20 22:07:11 command traefik error: field not found, node: dnsProvider

Solution:

dnsProvider is a configuration option from Traefik 1.x. You need to use provider for Traefik 2.x. Example:

[certificatesResolvers.lecloudflare.acme.dnsChallenge]
provider = "cloudflare"

Full example:

[certificatesResolvers.lecloudflare.acme]
email = "[email protected]"
storage = "/etc/traefik/acme/acme.json"

[certificatesResolvers.lecloudflare.acme.dnsChallenge]
provider = "cloudflare"



 

 

Posted by Uli Köhler in Traefik