Depuis quelques temps, j'héberge des services qui ne sont pas dockerisés, et je ne pouvais donc pas utiliser le reverse proxy que j'avais mis en place (voir ici).
En cherchant un peu, j'ai trouvé Nginx-Proxy-Manager, qui semblait pouvoir remplacer le reverse proxy et le companion letsencrypt. La seule différence notable est que la publication des services n'est pas automatique avec ce nouveau produit. Mais il a plein de qualités :

  • il gère les redirections,
  • il gère les certificat letsencrypt,
  • il gère les pages d'erreur,
  • il gère les access lists,
  • ...

Il est entièrement paramétrable via une jolie interface web, et on peut aller jeter un oeil au fichier de config, ce qui peut aider à comprendre la syntaxe de nginx.

Installation sur une debian 10 (Buster)

Installation des prérequis pour docker :

apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

Ajout de la clé du dépôt Docker :

curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -

Ajout du dépot Docker :

add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"

Installation de docker :

 apt-get update
 apt-get install docker-ce docker-ce-cli containerd.io

Téléchargement et installation de docker-compose :

curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Création de l'arborescence qui va recevoir nos containers (le -p permet de créer l'ensemble des dossiers parents s'ils n'existent pas) :

mkdir /data/containers/reverse

Dans ce dossier, création d'un fichier config.json qui va définir les noms et mots de passe d'accès à la base de données dédiée (à modifier avant déploiement, ça va de soi) :

 {
   "database": {
     "engine": "mysql",
     "host": "db",
     "name": "npm",
     "user": "npm",
     "password": "npm",
     "port": 3306
   }
 }

Création au même endroit du fichier docker-compose.yml qui va définir notre container :

 version: "3"
 services:
   app:
     image: jc21/nginx-proxy-manager:2
     restart: always
     ports:
       # Public HTTP Port:
       - '80:80'
       # Public HTTPS Port:
       - '443:443'
       # Admin Web Port:
       - '81:81'
     environment:
       # Uncomment this if IPv6 is not enabled on your host
       DISABLE_IPV6: 'true'
     volumes:
       # Make sure this config.json file exists as per instructions above:
       - ./config.json:/app/config/production.json
       - ./data:/data
       - ./letsencrypt:/etc/letsencrypt
     depends_on:
       - db
   db:
     image: jc21/mariadb-aria:10.4
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: 'npm'
       MYSQL_DATABASE: 'npm'
       MYSQL_USER: 'npm'
       MYSQL_PASSWORD: 'npm'
     volumes:
       - ./data/mysql:/var/lib/mysql

Comme le fichier docker-compose le stipule : Les ports 80, 81 et 443 sont mappés au sein du container sur les mêmes ports. Le fichier config.json est mappé vers le fichier /app/config/production.json au sein du container. On a besoin de deux sous dossiers dans notre répertoire : data et letsencrypt. On va donc les créer. Ces dossiers hébergeront les données créées par le container (la base de données, les logs, la conf de nginx dans data, et les certificats dans letsencrypt).

mkdir /data/containers/reverse/data
mkdir /data/containers/reverse/letsencrypt

Et on lance la création de notre container :

docker-compose up -d

Lorsque le container est lancé, l'interface de management est accessible sur le port 81 de la machine.

Petit mode d'emploi

Vu que la publication des services n'est pas automatique, il convient de renseigner l'ensemble des services à la main.

Ajout d'un host

Dans le menu, sélectionner Hosts puis Proxy Hosts.

Cliquer ensuite sur le bouton Add Proxy Host en haut à droite de la fenêtre.

Dans la fenêtre qui apparait, premier onglet (Details), renseigner le nom de domaine auquel la cible devra répondre, l'adresse IP de la cible, le port publié, ainsi que le type de service (http ou https). Le plus simple étant d'avoir tous ses services publiés en interne en http, et le reverse proxy qui (ssl|tls)ise tout ça.

Dans le deuxième onglet (Custom locations), il y a possibilité de définir des alias sous la forme de sous dossiers d'une URL existante. Ca peut servir.

Dans le troisième onglet (SSL), on va définir que l'on souhaite un nouveau certificat letsencrypt (ou en réutiliser un existant), que l'on souhaite forcer l'utilisation du SSL, et que l'on active le HSTS (cela permet de rediriger automatiquement vers le https depuis le http). On renseigne aussi l'adresse de contact pour letsencrypt et on accepte les conditions d'utilisation du service.

Enfin, les barbus trouveront leur compte dans le dernier onglet (Advanced) qui permet de fournir directement des options à Nginx.

Ajout d'une redirection

L'exemple le plus simple est de rediriger les requêtes arrivant sur un site sans les www vers l'URL incluant ces www. Exemple :
Dans le menu, sélectionner Hosts puis Redirection Hosts.

Cliquer ensuite sur le bouton Add Redirection Host en haut à droite de la fenêtre.

Dans la fenêtre qui apparait, premier onglet (Details), renseigner le nom de domaine auquel la cible devra répondre et le nom de domaine vers lequel on sera redirigé.

Dans le deuxième onglet (SSL), dans notre cas pas besoin de SSL, vu que le site cible gère le HSTS (obligation de basculer en https).

Dans le troisième onglet (Advanced), toujours possibilité pour les barbus de renseigner des paramètres spécifiques.

Et tout plein d'autres fonctionnalités intéressantes à découvrir, comme la gestion visuelle des certificats Let's Encrypt, la gestion des ACLs et des pages d'erreurs personnalisées :-)