Introduction

Traefik est une solution open-source française qui permet d'exposer ses services (site, blog, etc.) sur internet à travers une solution de routage des urls sans rendre, ces services accessibles directement, on appelle ça un proxy inverse (reverse proxy en anglais).

On peut y ajouter une couche de sécurité avec le fait de forcer le HTTPS sur les différents services accessibles et donc de demander la génération de certificats via Let's encrypt. Ce dernier permettra d'obtenir des certificats d'une durée de 3 mois qui sont renouvelés automatiquement.

De plus, Traefik propose aussi de superviser le trafic des différents services qu'il encapsule, de générer des logs d'accès ou des traces lors des différents échanges de flux.

Il s'intègre parfaitement dans des solutions conteneurisées (Docker, Kubernetes, etc.) et c'est précisément ce que nous allons voir ici en mettant en place Traefik devant notre Gitea que nous avons installé sur notre raspberry dans l'article précédent.

Installation

Avant de commencer

Pour poursuivre sur la partie "Installation", il faut plusieurs prérequis :

  • Posséder un serveur ou un raspberry qui est accessible sur internet à travers les ports 80 et 443 (très important pour la génération de certificat via Let's encrypt)
  • Avoir un nom de domaine qui pointe vers votre serveur ou raspberry, et, créer un ou deux sous-domaines pour accéder à l'interface de Traefik et de Gitea
  • Installer docker et docker-compose sur votre serveur ou raspberry

Il reste néanmoins possible d'exécuter Traefik en local, mais la génération de certificats ne sera pas possible et il faudra accepter le certificat par défaut "TRAEFIK DEFAULT CERT" afin de se connecter aux différents services exposés.

Enfin, ce qui concerne Gitea et ses fichiers de configuration ont été détaillés dans l'article précédent, ils ne seront pas réexpliqués ici.

C'est parti !

Le code du projet à cloner est disponible ci-dessous via mon compte Github.

https://github.com/axinorm/traefik-over-gitea

Une fois le projet cloné, il faut configurer quelques variables d'environnement en fonction de votre système d'exploitation et de l'architecture de votre processeur afin de générer le docker-compose qui correspond à votre système.

Le README.md indique comment installer jinja pour générer ce dernier.

Dans le cas d'un raspberry :

export TOG_SRV_OS=linux
export TOG_SRV_ARCH=arm

Dans le cas d'une machine sur macOS :

export TOG_SRV_OS=macos
export TOG_SRV_ARCH=x86

Il faut aussi mettre les deux urls de nos deux services qui vont être exposés sur internet (le tableau de bord de Traefik et Gitea) :

export TOG_URL_TRAEFIK=admin.example.com
export TOG_URL_GITEA=git.example.com

Une fois ces quatre variables complétées avec ces informations, la commande ci-dessous permet de générer le docker-compose.yml :

python3 generate_compose_file.py

Le fichier de configuration de Traefik s'appelle traefik.yml, il se compose de plusieurs blocs qui sont détaillés ici :

# Activation du tableau de bord pour Traefik (interface graphique)
api:
  dashboard: true

# Définition de deux points d'entrée pour le HTTP et HTTPS
entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"

# Utilisation de docker via les "labels" pour configurer les services
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false

# Définition de l'utilisation de Let's encrypt
certificatesResolvers:
  http:
    acme:
      email: myemail@mondomaine.com # A changer avec un email valide
      storage: acme.json
      # caServer a utiliser dans le cadre du développement et à supprimer en
      # production pour la génération d'un "vrai" certificat
      caServer: "https://acme-staging.api.letsencrypt.org/directory"
      httpChallenge:
        entryPoint: http

Il est important de modifier le champ email dans le bloc certificatesResolvers avec un email valide pour être informé en cas d'échec du renouvellement des certificats.

Comprendre Traefik

Avant d'exécuter quoi que ce soit, il est important de comprendre le rôle des "labels" présents dans le docker-compose.yml.

Voici un schéma de l'architecture de Traefik :

architecture-overview

L'ensemble des différentes informations est disponible ici.

  • Les "Providers" découvrent les services qui s'exécutent sur l'infrastructure
  • Les "Entrypoints" écoutent le trafic entrant
  • Les "Routers" analysent les requêtes (hôte, headers, SSL, etc.)
  • Les "Services" transmettent la requête au service de l'infrastructure
  • Les "Middlewares" peuvent mettre à jour la requête ou ajouter de l'authentification, des limitations de débit, etc.

Avec un exemple du docker-compose.yml :

labels:
  # On active le conteneur dans Traefik car il y a 
  # exposedByDefault = false dans la configuration
  - "traefik.enable=true"
  # On définit l'url git.example.com pour atteindre le service en HTTP
  - "traefik.http.routers.gitea.entrypoints=http"
  - "traefik.http.routers.gitea.rule=Host(`git.example.com`)"
  # On force la redirection vers le HTTPS
  - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
  - "traefik.http.routers.gitea.middlewares=https-redirect"
  # On définit l'url git.example.com pour atteindre le service en HTTPS
  - "traefik.http.routers.gitea-secure.entrypoints=https"
  - "traefik.http.routers.gitea-secure.rule=Host(`git.example.com`)"
  # Modification des en-têtes définies au niveau de Traefik
  - "traefik.http.routers.gitea-secure.middlewares=tls-chain"
  # On active la génération de certificat pour ce domaine
  - "traefik.http.routers.gitea-secure.tls=true"
  - "traefik.http.routers.gitea-secure.tls.certresolver=http"
  # Définition du service gitea qui écoute sur le port 3000
  - "traefik.http.routers.gitea-secure.service=gitea"
  - "traefik.http.services.gitea.loadbalancer.server.port=3000"
  # On utilise le réseau web pour se connecter au conteneur
  - "traefik.docker.network=web"

Plus haut, au niveau de Traefik, on retrouve ces mêmes labels avec des caractéristiques propres à celui-ci, mais surtout un ensemble de modification dans les en-têtes :

- "traefik.http.middlewares.tls-rep.redirectregex.permanent=true"
- "traefik.http.middlewares.tls-header.headers.SSLRedirect=true"
- "traefik.http.middlewares.tls-header.headers.forceSTSHeader=true"
- "traefik.http.middlewares.tls-header.headers.STSSeconds=315360000"
- "traefik.http.middlewares.tls-header.headers.STSIncludeSubdomains=true"
- "traefik.http.middlewares.tls-header.headers.STSPreload=true"
- "traefik.http.middlewares.tls-header.headers.browserXSSFilter=true"
- "traefik.http.middlewares.tls-header.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.tls-header.headers.frameDeny=true"
- "traefik.http.middlewares.tls-header.headers.customFrameOptionsValue=SAMEORIGIN"
- "traefik.http.middlewares.tls-header.headers.featurePolicy=accelerometer 'none'; ambient-light-sensor 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; usb 'none'; midi 'none'; sync-xhr 'none'; vr 'none'"
- "traefik.http.middlewares.tls-header.headers.referrerPolicy=strict-origin-when-cross-origin"

- "traefik.http.middlewares.tls-chain.chain.middlewares=tls-rep,tls-header"

C'est ce groupe "tls-chain" que l'on retrouve dans les "labels" de Gitea et qui ajoute un certain nombre de sécurités aux requêtes.

L'heure du verdict

Maintenant que le projet est configuré et que le fichier docker-compose est généré en fonction de plusieurs critères spécifiques, il ne reste qu'une seule chose à faire, lancer le docker-compose avec cette commande :

docker-compose up -d

Traefik devrait être disponible à l'adresse définie dans la variable d'environnement TOG_URL_TRAEFIK et de même pour Gitea pour la variable TOG_URL_GITEA. La génération des certificats prend un peu de temps, cela reste néanmoins visible dans les logs du docker-compose. Si ce n'est pas le cas, le certificat par défaut de Traefik est utilisé.

Pour aller plus loin

Nous venons de voir comment configurer Traefik pour exposer Gitea à travers internet de façon sécurisée mais nous avons vu uniquement la méthode via Docker (et docker-compose), ce qui n'est pas le plus adapté pour les services qui doivent être hautement disponibles. Si cette problématique vous concerne, il serait intéressant de regarder comment installer Traefik dans un cluster Kubernetes.

De plus, nous n'avons pas abordé les aspects de supervision, de logs d'accès, ou de trace, cela fera l'objet d'un prochain article.

Conclusion

Traefik est un outil simple et léger à mettre en place. C'est personnellement ce que j'utilise pour mon blog et je n'ai pas été déçu jusqu'à présent !

Dans un prochain article, nous verrons la partie décrite dans la section "Pour aller plus loin" qui permet de superviser notre Traefik.