I run most of my services in Docker and previously I was using
nginx as a reverse and TLS termination proxy together with Let's Encrypt. That worked great but everytime I wanted to try something new I had to copy-paste another conf and change a few values. I probably could have automated that to some extent and there are others who have but with my recent migration to VPSes I figured I'd give Traefik a try, if nothing else for their awesome logo!
Here I'll show you how to set up Traefik with GUI, http redirection and automatic Let's Encrypt certificates. We'll also add basic auth to the Traefik GUI.
⚠️ Update ⚠️
There's a vulnerability in old versions of Traefik so I've updated this post with a safe version. It should work just the same but the GUI will look different from the image below.
This guide assumes some general knowledge of Linux and that you have a server available with these services installed:
This is based on the official guide but with a few additions.
First start with creating a network for your web-facing containers to connect to.
docker network create web
Then we create a directory and the necessary files, as sudo if needed.
sudo su mkdir -p /opt/traefik touch /opt/traefik/docker-compose.yml touch /opt/traefik/acme.json && chmod 600 /opt/traefik/acme.json touch /opt/traefik/traefik.toml
Now let's add our
version: '2' services: proxy: # Always use a proper version! (edited) image: traefik:v1.6.6-alpine # Feel free to change the loglevel if needed command: --web --docker --logLevel=INFO restart: unless-stopped # Here's the network we created networks: - web # The traefik entryPoints ports: - "80:80" - "443:443" labels: # Make sure this domain points to your IP so that traefik can request a cert - "traefik.frontend.rule=Host:traefik.example.com" # Traefik will proxy to its own GUI - "traefik.port=8080" volumes: - /var/run/docker.sock:/var/run/docker.sock - /opt/traefik/traefik.toml:/traefik.toml - /opt/traefik/acme.json:/acme.json networks: web: external: true
☝️ Remember to replace
... and the config for Traefik...
debug = false defaultEntryPoints = ["https","http"] # The syntax is somewhat esoteric IMHO so this is mostly copy-paste [entryPoints] [entryPoints.http] address = ":80" [entryPoints.http.redirect] entryPoint = "https" [entryPoints.https] address = ":443" [entryPoints.https.tls] [retry] [docker] endpoint = "unix:///var/run/docker.sock" domain = "traefik.example.com" watch = true exposedbydefault = false [acme] email = "firstname.lastname@example.org" storage = "acme.json" entryPoint = "https" OnHostRule = true [acme.httpChallenge] entryPoint = "http" # Enable web configuration backend [web] # Web administration port, proxied in docker-compose.yml address = ":8080"
☝️ Add your domain and email under
... and we should be good to go!
docker-compose up -d
Check the logs (
docker-compose logs) and head to your configured domain and you should see something like this.
Since we're gonna expose the GUI of Traefik we'd like to have some authentication. Basic auth is supported so let's add that. Run this for the username you want - for example
admin - and enter your password.
htpasswd -n username
Here's what I got for admin/admin.
Now that needs to go in the
docker-compose.yaml but to work any
$ signs have to be escaped with another
Add this to the
Now stop and rebuild your service...
docker-compose stop docker-compose up -d
...and you should have basic auth!
Add a container
Now of course to have any use for this we need a container! Why not a blog with
Create a directory and a
docker-compose.yml, remember to change the domain and add the hostname to your DNS! 👍
mkdir -p /opt/ghost nano /opt/ghost/docker-compose.yml
version: '2' services: server: image: ghost:alpine container_name: ghost restart: unless-stopped networks: - web labels: - "traefik.enable=true" - "traefik.frontend.rule=Host:blog.example.com" - "traefik.port=2368" - "traefik.docker.network=web" volumes: - /opt/ghost/blog:/var/lib/ghost/content environment: - NODE_ENV=production - url=https://blog.example.com networks: web: external: true
Run the usual
docker-compose up -d and voilà blog up with SSL/TLS and all, pure magic 😀