Easy Self Hosting with Traefik proxy

I've been running Traefik to self-host some of the applications I like for a few month now, I'm really happy with its performance as well as convenience and therefore would like to share my setup and experience in this article. I will give a brief introduction of what Traefik is for, how I used it, and general suggestions on using Traefik.

What is Traefik?

By definition, Traefik is a reverse proxy and load balancer ^1. It is a member of the CNCF (Cloud Native Computing Foundation) foundation, the community version of this application is written in Go, open-sourced under MIT license, and hosted on GitHub. ^2

My experience with Traefik

Why I chose Traefik

In the past, I've been a avid user of NGINX and Apache, if I were to create a web server for some purpose, I would choose to use NGINX or Apache. One has to agree they are the de facto standard for web server and/or reverse proxy. However, what I don't like about them is their configuration. It is just simply difficult to comprehend and get used to.

Nowadays, I usually choose to use run applications within a Docker container. While I was setting up one of the applications, they mentioned Docker and how to setup Traefik with Docker. Upon reading through the documentation of Traefik, I made the decision to switch to use Traefik. Mainly because how easy it is to setup if you are using Docker/Docker Compose or Kubernetes.

Prerequisites

  • A machine where you are going to run your containers on. (VPS, or Raspberry Pi, etc.)
  • An application or two that you want to run in container.
  • Docker already installed
  • (Optional) Domain name

You would (of course) need to have a VPS up and running and a domain name if you want to make those applications public accessible. For the VPS part, I am using the free-tier instance from GCP.^3 I opted to use the 10 GB "balanced" storage instead of the standard storage to get faster speed, which costs 1 USD per month. The performance is good enough for my current workload, I might double the size of the SSD at some point in the future.

Setup Traefik

The setup of Traefik is intuitive, but not friction-free. Here's the Docker-compose file I used:

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
40
41
42
version: '3'

services:
reverse-proxy:
# The official v2 Traefik docker image
image: traefik:v2.9
# Enables the web UI and tells Traefik to listen to docker
command:
- "--log.level=DEBUG"
- "--api.dashboard=true"
- "--accesslog"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.websecure.forwardedHeaders.trustedIPs=127.0.0.1/32,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12"
- "--providers.docker=true"
- "--providers.docker.exposedByDefault=false"
- "--providers.docker.network=traefik-proxy"
networks:
- "traefik-proxy"
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`example.domain.com`)"
- "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
# Check
- "traefik.http.middlewares.auth.basicauth.users=YOUR USERNAME AND PASSWORD"
- "traefik.port=8080"
- "traefik.ping=true"
ports:
# The HTTP port
- "80:80"
- "443:443"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
#Docker Networks
networks:
traefik-proxy:
external: true

I won't go into everything in this file. Once you do the docker-compose up with this file, you will have a running Docker container with Traefik proxy running in it. This configuration also expose the dashboard web UI by default at example.domain.com domain. You will want to setup the basicauth for the dashboard to protect information, this is done as traefik.http.middlewares.auth.basicauth.users=YOUR USERNAME AND PASSWORD, the password needs to be hashed, more information can be found at Traefik documentation on this topic.

As you can guess, Traefik setup the proxy and its relevant configuration through labels on a docker container. Some might find this not clean, I'm okay with it. There are other ways to do the configuration as documented in Traefik documentation.

Setup an application

As an example, I will setup CyberChef to run as a docker container, and behind the Traefik proxy. If you are not familiar with CyberChef, I highly recommend give it a go. It describes itself as:

A simple, intuitive web app for analysing and decoding data without having to deal with complex tools or programming languages. CyberChef encourages both technical and non-technical people to explore data formats, encryption and compression.

Technically speaking, most of the things it does can be done in command line, I would say it is still nice to have a Web UI. I probably use less than 5% of its feature, mostly using it to format JSON, and occasionally decode BASE64 or other stuff.

As with most self-host applications, it is open source. The code is written in JavaScript, and open sourced under Apache 2.0 license.^4

If you were to put to it into a container, you should consider using this docker image. Below is an example of a docker-compose file where you put the CyberChef behind the traefik proxy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '3'
services:
cyberchef:
image: mpepping/cyberchef
expose:
- 8000
networks:
- "traefik-proxy"
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-proxy"
- "traefik.http.routers.cyberchef.rule=Host(`cyberchef.example-domain.com`)"
- "traefik.http.routers.cyberchef.tls=true"
- "traefik.http.routers.cyberchef.entrypoints=web,websecure"
- "traefik.http.services.cyberchef.loadbalancer.healthcheck.path=/"
- "traefik.http.services.cyberchef.loadbalancer.healthcheck.interval=15m"
- "traefik.http.services.cyberchef.loadbalancer.healthcheck.timeout=3s"
- "traefik.http.services.cyberchef.loadbalancer.healthcheck.scheme=http"
- "traefik.http.services.cyberchef.loadbalancer.server.port=8000"
networks:
traefik-proxy:
external: true

As with the previous setup, this file also contains the usual stuff, where the traefik.http.routers part specifies the domain name, as well as some TLS stuff, the entrypoints part contains both web and websecure, which means this application can be accessed from both http and https. The labels that contains loadbalancer will provide a simple health check mechanism for traefik to check the health of the container, the server.port indicates where the Traefik go to for this downstream application.

Now, if you run docker-compose up --force-recreate --build -d && docker image prune -f && docker compose logs -f, you will be greeted with CyberChef if you go to the domain you setup.

Conclusion

If you do not have any prior experience with NGINX or Apache, I tend to think this will be much easier to setup than NGINX or Apache. You can organize different applications you would like to self host by folders and put the respective docker-compose file under that folder. I would highly recommend checking this repository for some inspiration


References

https://traefik.io/traefik/
https://github.com/traefik/traefik
https://github.com/cloudcommunity/Cloud-Free-Tier-Comparison#3-google-cloud
https://github.com/gchq/CyberChef
https://github.com/BaptisteBdn/docker-selfhosted-apps