Wednesday, October 17, 2018

traefik in a box

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)
  • choose hardware and operating system
  • optionally install docker-machine
  • init a docker swarm
  • create a swarm network
  • create the 3 config files
  • Launch
  • Basic Authentication
  • my app configuration
  • Launch my app
  • All in one
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.

No comments:

Post a Comment

static site generators

Static site generators are pretty cool. Granted they are an oversimplification of the java/json/xml/xslt site manifestation from the olden d...