Using Traefik on NixOS - MSF-OCB/NixOS Wiki

Enabling the Traefik service

We have a standard configuration for Traefik which can easily be activated by setting

settings.services.traefik.enable = true;

in the server's configuration file.

Having traffic forwarded to a container

Note: if you need certificates to be obtained via a DNS challenge (for websites that are not publicly reachable), please check the following section as well.

When Traefik is enabled, a container can be exposed through Traefik by setting the following labels in the docker-compose.yml file and registering the container on the web network:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.myapp.rule=Host(`myapp.ocb.msf.org`)"
  - "traefik.http.routers.myapp.entrypoints=websecure"
networks:
  - web
  - default

Careful: only the front-end should be connected to the web network, all other containers will communicate through the default network.

The web network is an external network, defined by the Traefik service. You make it known to your docker-compose project by including the following top-level section:

networks:
  web:
    external: true

The labels mentioned above, will expose the service running in the container over HTTPS on port 443 on the specified domain with a certificate generated by Let's Encrypt.

HTTP port 80 is automatically forwarded to HTTPS and HSTS headers are enabled. Additionally, gzip compression is also enabled by default.

Generating certificates using DNS challenges

For internal servers and servers on the field, that are not reachable from the internet, we can use a DNS challenge to generate the certificates.

If your public URL is myapp.ocb.msf.org, you need to add the following ALIAS record in our public DNS zone:

  _acme-challenge.myapp.ocb.msf.org CNAME _automatic-certificate-validation.ocb.msf.org

For URLs that are re-used in different locations (e.g. applications on the field), this CNAME will usually already be in place.

Due to limitations on the number of ALIAS records allowed to point to a single resource set in Azure, we introduced _two._automatic-certificate-validation.ocb.msf.org, pointing to _automatic-certificate-validation.ocb.msf.org in order to be able to continue to use ALIAS records. We might need to introduce additional such records in the future.

It is not needed to add this entry to any internal DNS servers, as it will only be queried by the Let's Encrypt servers that are outside of our network.

Then, you need to make sure that the required DNS credentials are available on the server in question. To do so, you edit the file secrets/secrets.yml using Ansible Vault, as explained here, and you make sure that the dns_credentials secret is made available to the server in question. After having edited, committed and pushed this file, the NixOS config of the server should be rebuild by running sudo systemctl start nixos_rebuild_config.

After having done this, you follow the steps from the previous section to configure Traefik using labels in the docker-compose.yml file, but you add the following additional label to your docker container to instruct Traefik to use a DNS challenge:

  - "traefik.http.routers.myapp.tls.certresolver=letsencrypt_dns"

and certificates will be generated using DNS challenges.

Connecting to the Traefik dashboard

The Traefik dashboard gives a graphical overview of the services that have been configured. Since it exposes internal information and also exposes an API, it is only accessible on localhost, but you can use an SSH tunnel to connect to the dashboard on any server.

To connect to the dashboard of a server, you can do the following:

  1. Make sure you are using Firefox, since Chromium-based browsers do not allow proxying localhost
  2. Configure Firefox to use a SOCKS proxy on port 9443 (the FoxyProxy extension is useful to toggle proxies with a single click)
  3. Connect to the server with ssh -D 9443 my_server
  4. Browse to https://localhost:8080/dashboard/