Richard Bucker

traefik in a box

Posted at — Oct 17, 2018

Before you begin there are a few decisions to be made. The most important is whether or not you want to support wildcard domains or strictly limited to well known host/domains. If you choose to use wildcards then you are limited to dnsChallenge and there are a limited number of providers not to mention that you need credentials. (see providers)

FIRST you need to deploy machine that can be physical or virtual, however, in order for it to deploy SSL via letsencrypt you must have a public IP and registered DNS and nameserver. Depending on the DNS strategy you may need to create the A-record. The host OS you select should or must support Docker. I prefer CoreOS or RancherOS.

Not all OS’ pre-install docker-machine and many container OS’ use read-only partitions in order to maintain immutability. This is how I install docker-machine on CoreOS

sudo mkdir -p /opt/local/bin
base=https://github.com/docker/machine/releases/download/v0.14.0 &&
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
sudo install /tmp/docker-machine /opt/local/bin/docker-machine

Initiate docker swarm… this can be one or more machines. You need to know more about this…

docker swarm init

Docker containers can talk to each other via private virtual networks. Swarm has a variation where the network can span physical machines with additional features like encryption. The basic declaration looks like:

docker network -d overlay webtraefik

Create the three config files:

sudo mkdir -p /opt/traefik
sudo touch /opt/traefik/docker-compose.yml
sudo touch /opt/traefik/acme.json && chmod 600 /opt/traefik/acme.json
sudo touch /opt/traefik/traefik.toml

The acme.json file is left blank as traefik will fill it in as it registers with letsencrypt.

This is the traefik.toml file. There are a number of functions here like redirecting all http to https and the acme(letsencrypt) config. Notice the dnsChallenge section and the acme domains. Sine we are configuring wildcard domains dnsChallenge is required. The other challenge methods do not apply.

traefik.toml:
debug = true

logLevel = “ERROR”
defaultEntryPoints = [“https”,“http”]

[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 = “ooc.systems”
watch = true
exposedByDefault = false

[acme]
email = “richard@bucker.net”
storage = “acme.json”
entryPoint = “https”
onHostRule = true
[acme.dnsChallenge]
provider = “digitalocean” # DNS Provider name (cloudflare, OVH, gandi…)
delayBeforeCheck = 0
entryPoint = “http”

[[acme.domains]]
main = “*.ooc.systems”


docker-compose.yml
version: ‘3.1’

services:
traefik:
image: traefik:latest
restart: always
command: –api –docker –docker.swarmMode –configFile=/traefik.toml
environment:
- DO_AUTH_TOKEN=api token goes here… env and docker secrets have not been resolved
ports:
- 80:80
- 443:443
networks:
- webtraefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/traefik.toml:/traefik.toml
- /opt/traefik/acme.json:/acme.json
deploy:
placement:
constraints:
- node.role == manager
labels:
traefik.docker.network: “webtraefik”
traefik.port: “8080”
traefik.basic.frontend.rule: “Host:t3.ooc.systems”
traefik.frontend.auth.basic.users: “admin:$$apr1$$PfJ7s9fA$$YsXtXor2kSCgjJa.”

networks:
webtraefik:
external: true


Launching traefik is simple but needs to be done as a docker swarm. It’s probably best to know more about how the swarm ingress policy works with traefik. Notice in the docker-compose file above there is a constraint to insure that traefik is only launched on worker nodes.

Also notice that the traefik container offers a basic console and so the labels section registers the URL and configures the Basic Authentication.

Launch:
docker stack deploy -c docker-compose.yml traefik

You should be familiar with BASIC AUTH… but creating the config looks like:

echo $(htpasswd who password “) | sed -e s/\$/\$\$/g

Unfortunately this does not really work because the result never let me in… but I probably don’t know something… Also CoreOS does not have an htpasswd instance. So I found an openssl variation that was also wrong and eventually made this work:

openssl passwd -apr1 mypasswd | sed s/\$/\$\$/g

Now that I have traefik up and running I need to deploy my simple app. Here is the compose file:

version: ‘3.1’

services:
whoami:
image: emilevauge/whoami
networks:
- webtraefik
deploy:
labels:
traefik.port: “80”
traefik.frontend.rule: “Host:ami2.ooc.systems”
traefik.docker.network: “webtraefik”
traefik.enable: “true”
traefik.frontend.entryPoints: “http,https”
traefik.frontend.auth.basic.users: “who:$$apr1$$ItuvI6$$fkOoJ1”

networks:
webtraefik:
external: true

Launch my app. Since there is no role constraint the container can be deployed anywhere in the swarm.

docker stack deploy -c docker-compose.yml whoami

Depending on what you have in mind you can deploy the system in an all-in-one configuration so that the traefik and your service(s) are deployed in one deploy command. This has some advantages when your service domain is an all in one universe but it also means that you have a deep interdependence between services.

WARNING WARNING WARNING

implementing wildcard DNS means that anyone with access to the swarm manager can instantly deploy a service under the domain either intentionally or unintentionally exposing the domain to various security and data problems. On the other hand not all sites have problems with their people or their content.