Featured image of post Accessing Personal Websites from the Public Network (2) - Traefik Reverse Proxy Configuration

Accessing Personal Websites from the Public Network (2) - Traefik Reverse Proxy Configuration

Use Traefik to configure a reverse proxy for accessing your server or website from the public network

Motivation

I previously used Nginx as a reverse proxy to access websites on my private server. At that time, Nginx was installed directly on the computer without containerization, which meant that when I wanted to migrate these services to other computers later, I had to reconfigure Nginx and reconfigure SSL certificates, etc.

So I decided to containerize the reverse proxy service as well, to facilitate future management and migration. I saw many examples of using Traefik in Docker online, so I decided to migrate from Nginx to Traefik.

Prerequisites

Traefik Overview

Traefik is a modern reverse proxy and load balancer that can automatically discover and configure backend services. Traefik supports various backend services such as Docker, Kubernetes, Consul, etc., and can automatically obtain SSL certificates. Traefik’s configuration is very flexible and can be done through labels, files, or APIs.

Installing and Configuring Traefik

Overall Architecture

Traefik can be configured using labels, APIs, or files. Since I previously used file-based configuration with Nginx, where each service had its own configuration file, I found this approach very clear and manageable. Therefore, I will also use file-based configuration with Traefik.

The Traefik container itself is independent and managed using a docker-compose.yml file like other Docker containers. We will create a new network in Docker called traefik-net, and all containers, including Traefik, will use this network. Within this network, we will use Traefik for reverse proxying.

In this article, we will take the deployment of a Whoami service as an example to introduce the use of Traefik. Whoami is a simple HTTP server that returns the request’s IP address, request headers, and other information, making it ideal for testing reverse proxies.

Project Directory Structure

traefik Project

Based on the above architecture design, we create a new traefik directory under the directory where all Docker projects are stored, to hold the relevant files for the Traefik project. The directory structure is as follows:

1
2
3
4
5
6
7
8
9
traefik/
  ├── docker-compose.yml
  ├── .env
  ├── traefik.yml
  ├── acme.json
  └── dynamic/
      ├── app1.yml
      ├── app2.yml
      └── app3.yml

where:

  • docker-compose.yml: The Docker Compose configuration file for Traefik.
  • .env: The environment variable file used to store environment variables for the Traefik project.
  • traefik.yml: The main configuration file for Traefik.
  • acme.json: The file used to store SSL certificates.
  • dynamic: The directory for storing dynamic configuration files, with each service having its own configuration file.

whoami Project

Since we are taking a simple Whoami service as an example, we need to create a Whoami project in addition to the Traefik project. The Whoami project is very simple and also placed in the directory where all Docker projects are stored, containing only a docker-compose.yml file.

1
2
whoami/
  └── docker-compose.yml

Traefik Installation, Configuration, and Testing Process

1. Create traefik-net Network in Docker

First, we create a public network in Docker called traefik-net (you can use a different name, but it must be consistent in subsequent configurations):

1
docker network create traefik-net

2. Create the traefik Project Directory

Create a traefik directory under the directory where all Docker projects are stored, and create the above files and subdirectories in that directory.

docker-compose.yml

docker-compose.yml如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
version: "3.8"

services:
  traefik:
    image: traefik:v3.4.0
    container_name: traefik
    command:
      - "--configFile=/etc/traefik/traefik.yml"
      - "--entryPoints.web.address=:80"
      - "--entryPoints.websecure.address=:443"
      - "--providers.docker=true"
      - "--providers.docker.network=traefik-net"
      - "--providers.docker.exposedByDefault=false"
      - "--providers.file.directory=/etc/traefik/dynamic"
      - "--providers.file.watch=true"
      - "[email protected]"
      - "--certificatesResolvers.le.acme.storage=/letsencrypt/acme.json"
      - "--certificatesResolvers.le.acme.httpChallenge.entryPoint=web"
      - "--api.dashboard=true"
      - "--log.level=INFO"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"    # comment out if you don’t need the dashboard
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/etc/traefik/traefik.yml:ro"
      - "./dynamic:/etc/traefik/dynamic:ro"
      - "./acme.json:/letsencrypt/acme.json"
    environment:
      - CF_API_KEY=${CF_API_KEY}
      - CF_API_EMAIL=${CF_API_EMAIL}
    networks:
      - traefik-net
    restart: unless-stopped

networks:
  traefik-net:
    external: true

where traefik-net is the network we created earlier. The Traefik configuration file traefik.yml, dynamic configuration directory dynamic/, and the file for storing SSL certificates acme.json are mounted into the container.

.env

In .env, we store the CloudFlare API key and email address used for automatically obtaining SSL certificates. You need to replace the following content with your own Cloudflare API key and email address. In theory, providing just the key should be enough, but I haven’t tested it. If you are using a DNS provider other than Cloudflare (for example, Alibaba Cloud), you need to replace the relevant API key and email address with those of your DNS provider. For details, please refer to the Traefik documentation.

1
2
CF_API_KEY=your_cloudflare_api_key
CF_API_EMAIL=your_cloudflare_email
traefik.yml

traefik.yml is the main configuration file for Traefik. Below is a basic configuration example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

providers:
  file:
    directory: /etc/traefik/dynamic
    watch: true

api:
  dashboard: true
  insecure: false

certificatesResolvers:
  le:
    acme:
      email: [email protected]
      storage: /letsencrypt/acme.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"

#log:
#  level: "DEBUG"

Here we specify two entry points: web (HTTP) and websecure (HTTPS), and set the directory for dynamic configuration files to /etc/traefik/dynamic. We also enable the Traefik API dashboard and configure the ACME certificate resolver for Cloudflare DNS Challenge. If you are using a different DNS provider, you can replace provider: cloudflare with the name of your DNS provider and configure the corresponding API key and email address according to its documentation.

acme.json

acme.json is the file used to store SSL certificates. You need to create this file first (an empty file is sufficient) and set its permissions to 600 to ensure that Traefik can write certificate information:

1
2
touch acme.json
chmod 600 acme.json
dynamic Directory

In the dynamic directory, we can create a configuration file for each service. Below is a very simple configuration file for the Whoami service, and this article will use the deployment of a Whoami service as an example to introduce the use of Traefik.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
http:
  routers:
    whoami-router:
      entryPoints:
        - websecure
      rule: "Host(`whoami.example.com`)"
      tls:
        certResolver: le
      service: whoami-service

  services:
    whoami-service:
      loadBalancer:
        servers:
          - url: "http://whoami:80"

3. Create the whoami Project Directory

Create a whoami directory under the directory where all Docker projects are stored, and create a docker-compose.yml file in that directory. The content is also very simple:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
version: '3.8'
services:
  whoami:
    image: traefik/whoami:v1.11.0
    container_name: whoami
    restart: always
    networks:
      traefik-net:
        aliases:
          - whoami

networks:
  traefik-net:
    external: true

This docker-compose.yml file defines a Whoami service that uses the official Whoami image provided by Traefik and connects it to the previously created traefik-net network.

4. Start the Whoami and Traefik Services

  1. If you have previously deployed an Nginx service on this computer, you need to stop the Nginx service first to avoid port conflicts with Traefik:

    1
    
    sudo systemctl stop nginx
    

    To prevent Nginx from starting again after the computer restarts, you can disable the Nginx service:

    1
    
    sudo systemctl disable nginx
    
  2. Enter the whoami directory and use the following command to start the Whoami service:

    1
    
    docker-compose up -d
    
  3. Enter the traefik directory and use the following command to start the Traefik service:

    1
    
    docker-compose up -d
    
  4. Check if the Traefik and Whoami services are running properly:

    1
    
    docker ps
    

    You should see that the containers for the Traefik and Whoami services are running.

5. Test Traefik Reverse Proxy

First, make sure you have resolved your domain name (e.g., whoami.example.com) to your server’s IP address with your DNS provider.

Then, you can test Traefik’s reverse proxy functionality by accessing https://whoami.example.com. You need to replace whoami.example.com with your own domain name and ensure that DNS resolution is correctly configured.

If everything is working properly, you should be able to access the Whoami service, and you should see a page containing request information, similar to the content below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Hostname: 5ded297e3bf3
IP: 127.0.0.1
IP: ::1
IP: 192.168.144.2
RemoteAddr: 192.168.144.4:33354
GET / HTTP/1.1
Host: whoami.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, br
Accept-Language: en
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 2600:1700:37a0:70e0:b8c8:f187:aaa1:1d07
Cf-Ipcountry: US
Cf-Ray: 948a2cd22a1958ee-ORD
Cf-Visitor: {"scheme":"https"}
Priority: u=0, i
Sec-Ch-Ua: "Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "macOS"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 172.69.17.115
X-Forwarded-Host: whoami.example.com
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: bca3e42c8951
X-Real-Ip: 172.69.17.115

If you cannot access https://whoami.example.com, it means there is a problem with the configuration above. You can uncomment the log.level: "DEBUG" line in traefik.yml, so Traefik will output more detailed log information to help you troubleshoot the issue.

If you encounter SSL certificate errors when accessing the site, it may be because Traefik has not yet obtained the SSL certificate. You can wait for a while, and Traefik will automatically obtain the SSL certificate and configure HTTPS.

comments powered by Disqus