Aller au contenu

Traefik#

Traefik est le « reverse-proxy » du serveur. Il a un travail de reroutage : c'est lui qui intercepte toutes les requêtes Internet, puis, selon l'URL entrée, il redirige vers le bon service.

La documentation peut se trouver ici : https://docs.traefik.io/

Configuration#

Traefik est un service à part entière. Sa configuration dans le fichier docker-compose.yml :

  traefik:
    image: traefik
    ports:
      - "80:80"
      - "443:443"
    restart: always
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/srv/auth:/var/auth"
    command:
      - "--log.level=INFO"
      - "--api=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
      - "--certificatesresolvers.mytlschallenge.acme.email=contactATtfjm.org"
      - "--certificatesresolvers.mytlschallenge.acme.storage=/root/acme.json"
    labels:
      - "traefik.http.routers.http_catchall.rule=HostRegexp(`{any:.+}`)"
      - "traefik.http.routers.http_catchall.entrypoints=web"
      - "traefik.http.routers.http_catchall.middlewares=https_redirect"
      - "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.https_redirect.redirectscheme.permanent=true"

      - "traefik.http.middlewares.auth.basicauth.usersFile=/var/auth/admins.htpasswd"

      - "traefik.http.routers.traefik.rule=Host(`traefik.tfjm.org`)"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls.certresolver=mytlschallenge"
      - "traefik.http.routers.traefik.middlewares=auth"

Détaillons chaque étape.

On lance le service traefik. Les ports 80 et 443 sont exposés : c'est ce service qui viendra intercepter toutes les requêtes Web, sur les ports sécurisé (443) et non sécurisé (80).

On veut évidemment que le service soit en permanence allumé.

Traefik a besoin de communiquer avec le serveur Docker afin de gérer proprement la redirection de services, c'est pourquoi on volume /var/docker/docker.sock.

Le dossier /var/auth contient les hashs des mots de passe pour les sites protégés par mot de passe.

On indique ensuite vouloir accéder à l'API, et que Traefik gère Docker. De plus, chaque service Docker est exposé dans Traefik par défaut.

On ajoute ensuite les deux points d'entrées, qu'on nomme web pour le port 80 et websecure pour le port 443.

Traefik a l'avantage de générer automatiquement des certificats de sécurité SSL. On configure ensuite la génération des certificats, en l'activant, donnant contact@tfjm.org en mail de contact et /root/acme.json en fichier contenant les certificats de sécurité. Il n'est pas nécessaire de sauvegarder les certificats, ils peuvent se regénérer sans problème à chaque fois que Traefik est redémarré (ce qui n'arrive pas souvent normalement). Attention toutefois : il peut être bien de volumer ce fichier acme.json en cas de maintenance de Traefik : il n'est pas possible de générer plus de 5 fois dans une semaine un certificat pour un nom de domaine.

Traefik est désormais fonctionnel à ce stade. Cependant, Traefik est lui-même un service, donc il peut interagir ! Les 5 premiers labels indiquent que sur le point d'entrée web (donc sur le port 80), en filtrant sur tous les noms de domaine, on redirige sur la page https sur la même URL, avec une redirection permanente. Cela permet de s'assurer que toutes les connexions seront toujours sécurisées, et que le port 80 ne sera jamais exploité autrement qu'en redirigeant sur le port 443.

La ligne suivante ajoute un nouveau middleware (une couche intermédiaire entre la requête et la réponse) qui permet de protéger très simplement un service par un identifiant et un mot de passe, donnés par le fichier /var/auth/admins.htpasswd (qui est donc volumé via /srv/auth/admins.htpasswd). Ce middleware pourra être utilisé par tous les services.

La dernière chose que permet Traefik est l'accès à son API. On crée donc un nouveau routeur appelé traefik qui vient récupérer les connexions à traefik.tfjm.org sur le point d'entrée websecure (connexion HTTPS). On spécifie le service utilisé (ici api@internal), et on indique que Traefik doit lire l'entrée sur le port 8080 de son propre service. De plus, on veut restreindre l'accès, donc on utilise le middleware de protection par mot de passe.

Utilisation#

Une fois le char d'assault mis en place, la configuration service par service est assez simple. Dans le docker-compose.yml, il suffit de rajouter les labels suivant pour chaque service :

  labels:
    - "traefik.http.routers.mon-routeur.rule=Host(`subdomain.domain.ext`)"
    - "traefik.http.routers.mon-routeur.entrypoints=websecure"
    - "traefik.http.routers.mon-routeur.tls.certresolver=mytlschallenge"

En remplaçant mon-routeur par le nom de votre service.

La première ligne spécifie que ce service est exposé à Docker. Elle est en réalité superflue puisque Traefik est configuré pour regarder tous les services, il est recommandé de ne pas la mettre (sauf pour préciser que Traefik n'expose pas ce conteneur).

La seconde ligne indique que l'on va lire les entrées sur subdomain.domain.ext. À noter qu'il est possible d'avoir des filtres plus puissants à base d'expressions rationnelles ou d'analyse du chemin.

La troisième ligne dit qu'on ne regarde que les entrées sur le point d'entrée websecure, c'est-à-dire les entrées HTTPS.

Enfin, on indique à Traefik qu'on veut un certificat de sécurité pour ce site.

Traefik se charge de deviner quel port est utilisé dans le service, en regardant la liste des ports exposés. Toutefois, il peut arriver que plusieurs ports soient exposés, on peut donc rajouter la ligne :

    - "traefik.http.routers.mon-routeur.service=mon-service"
    - "traefik.http.services.mon-service.loadbalancer.server.port=XXXXX"

En remplaçant mon-routeur et mon-service par le nom de votre service, et XXXXX par le port voulu. À noter que la première ligne n'est pas obligatoire si vous n'avez qu'un seul service : Traefik devinera efficacement.

Pour utiliser la protection par mot de passe, il suffit d'ajouter la ligne :

    - "traefik.http.routers.mon-routeur.middlewares=auth"

Et le service utilisera le middleware auth défini dans Traefik.

C'est tout pour Traefik :)

Pour aller plus loin#

Traefik permet de faire des choses beaucoup plus complexes, mais surtout très compliquées à comprendre. Cette doc ne répertorie que les actions essentielles. Ne pas hésiter à consulter la documentation de Traefik en cas de besoin.


Dernière mise à jour: 11 juillet 2020