Installation proxy sous-domaines

Billet

Les images Docker de Dotclear permettent d'utiliser un multiblog par sous-domaine, nous allons voir à travers cet article comment mettre en place et régler ce multiblog.

1. Le but

Le but est d'avoir plusieurs blogs accessibles chacun par un sous domaine dédié hébergé par un ou plusieurs multiblog Dotclear. Ou autrement dit, si on tape https://blog.mondomaine.tld dans notre navigateur, il affiche notre blog.
Pour cela on va avoir besoin :

  • accéder à la gestion de nos noms de domaines pour les rediriger vers notre serveur
  • une application qui va gérer la distribution des sous domaines
  • une application qui va héberger les blogs
  • une application qui va héberger les bases de données.

En réalité Docker va nous simplifier la chose car on va pouvoir lancer toutes les applications à partir d'un seul fichier de configuration.
On continue donc de préciser ce qu'il va falloir :

  • Pour la gestion des domaines, on laisse ça à notre registrar (J'utilise souvent OVH)
  • Pour la distribution des sous domaines et des certificats, on va utiliser Nginx Proxy Manager
  • Pour les blog, ben ça sera Dotclear hein
  • Pour les bases de données, ce sera Mariadb

On va même compliquer la chose en ajoutant un second multiblog Dotclear pour d'éventuels tests.

2. Le serveur

Détail qui n'en est pas un, votre serveur doit être accessible depuis les internets ! Par exemple les blogs dotclear.watch sont hébergés sur des serveurs privés virtuels (VPS) chez OVH. Vous pouvez bien entendu héberger chez vous avec peut-être des DNS dynamiques mais ce n'est pas le but de cet article. On part du principe ici que la machine sera prête, c'est à dire qu'un système sera installé avec les principaux outils et qu'un pare-feu sera opérationnel. Dans mon cas, OVH me facilite la tâche en proposant un système Debian avec Docker préconfiguré, mais pas le pare-feu et autre fail2ban. Encore une fois ce n'est pas le but de cet article.

Donc On aura besoin d'avoir les ports suivant ouverts :

  • SSH, en TCP, par défaut port 22 mais un autre peut être configuré,
  • NPM, en TCP, par défaut port 81, accès au proxy manager, mais on va changer ce port
  • HTTP, en TCP, port 80, accès web
  • HTTPS, en TCP, port 443, accès web sécurisé
  • ICMP, en UDP, port 53, normalement la machine reste ouverte en UDP pour l'ICMP

Coté logiciels :

  • L'environnement Docker (avec docker compose) doit être installé et l'utilisateur courant doit avoir les droits dessus. (Il existe de nombreux tuto sur le web pour ça)
  • un éditeur de texte (comme par exemple nano)


3. Gestion des sous domaines

Quand vous tapez une adresse web dans le navigateur, derrière ça il y a quelqu'un qui dit que telle adresse doit renvoyer vers telle machine, et on utilise les adresses IP pour cela, c'est la Zone DNS. Ce quelqu'un est ce qu'on appelle un registrar, il y en a des milliers et vous pouvez même être votre propre registrar.
On va partir du principe qu'on est l'heureux propriétaire du nom de domaine mondomaine.tdl et donc il va va falloir créer des zones DNS pour nos sous domaines. On va en créer 3 :

  • blog.mondomaine.tld
  • perso.mondomaine.tld
  • test.mondomaine.tld

Les deux premiers iront sur le multiblog de production et le dernier sur celui de test mais on en est pas là.
Suivant votre registrar, il peut avoir des outils simplifiés pour modifier la Zone DNS, on simplement une modification en mode texte. Dans tous les cas il va falloir dire que ces 3 sous domaines pointent vers la machine qui va héberger nos blogs. Il y a deux champs à modifier :

  • Le champs A qui correspond à l'IPv4 de notre machine
  • Le champs AAAA qui correspond à l'IPv6 de notre machine

Si notre machine a comme IP 1.2.3.4 et 2001:1234:5678::abcd, la partie correspondante du fichier DNS donnera :

blog        IN A     1.2.3.4
blog        IN AAAA     2001:1234:5678::abcd
perso       IN A     1.2.3.4
perso       IN AAAA     2001:1234:5678::abcd
test        IN A     1.2.3.4
test        IN AAAA     2001:1234:5678::abcd

Dans le manager d'OVH l'outil ressemble à ça :
Zone DNS OVH manager
Voilà, nos sous-domaines arrive jusqu'à notre machine, maintenant il va falloir les attraper et les distribuer.

4. Distribution des sous-domaines

On va utiliser un serveur proxy en entrée de notre machine pour redistribuer les sous-domaines vers nos blogs. Ce sera Nginx Prox Manager qu'on lancera dans un container Docker à l'aide de Docker compose. Logo Nginx Proxy Manager
On se connect en SSH à notre machine, on créé un premier répertoire nommé npm qui servira de volume persistant à notre container et on édite le fichier docker-compose.yml :

mkdir npm
nano docker-compose.yml

Puis on y configure notre premier container :

networks:
  default:
    name: npm

services:
  # Nginx proxy manager
  npmapp:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    container_name: npmapp
    ports:
      - 80:80
      - 443:443
      - 61345:81
    volumes:
      - ./npm/data:/data
      - ./npm/letsencrypt:/etc/letsencrypt
    healthcheck:
      test: ["CMD", "/usr/bin/check-health"]
      interval: 10s
      timeout: 3s

Ici le service sera nommé npmapp, il créera un container nommé npmapp basé sur l'image jc21/nginx-proxy-manager:latest, le container écoutera sur les ports 61345,80,443, il utilisera deux volumes persistant npm/data et npm/letsencrypt. Un réseau nommé npm sera créer qui permettra aux containers de se parler en utilisant leurs noms.
On exécute la composition avec :

docker compose up -d

On attend un peu que l'image soit téléchargé et que les containers soient démarrés, puis dans notre navigateur web on se connecte à l'adresse IP de notre serveur sur le port 61345 : http://1.2.3.4:61345, d'origine c'est le port 81 mais on l'a changé dans le fichier de configuration et on a ouvert le port du pare-feu.
La page de login de NPM s'affiche, lors de la première connexion l'utilisateur est admin@exemple.com et le mot de passe changeme une fois connecter il va demander de créer un utilisateur et un mot de passe. Utilisez un mot de passe complexe.
Page de login de Nginx Proxy Manager
On commence par créer des cetificats SSL pour nos sous domaines, cela permet d'avoir des adresses en https. Pour cela on va dans l'onglet SSL Certificates, on clique le bouton Add SSL Certificate, on ajoute nos deux premiers sous domaines, on ajoute notre adresse mail (valide si possible) puis pour la vérification on utilise la méthode qu'on préfère. Personnellement j'ai accès aux API de mes registrar donc j'utilise le DNS Challenge. On accepte les termes et on sauve en cliquant Save. Le processus va mouliner un petit moment puis le certificat sera créé.
Création de certificat Let's Encrypt sous Nginx Proxy Manager
Maintenant on va pouvoir enfin rediriger nos sous domaines vers notre futur multiblog. Pour cela, dans l'onglet Hosts -> Proxy Hosts, on clique sur Add Proxy Host, une fenêtre de configuration s'ouvre.
Création du Proxy Host
On configure comme suis :

  • Détails -> Domain Names : nos deux noms de sous domaines
  • Détails -> Scheme : http
  • Détails -> Forward Hostname : dcstableapp (le nom du futur container Docker)
  • Détails -> Forward Port : 80
  • SSL -> SSL Certiicate : on sélectionne le certificat qu'on a créée précédemment
  • SSL -> Force SSL : coché
  • SSL -> HTTP/2 : coché
  • SSL -> HSTS : coché

Puis on clique sur Save.

On recrée un autre certificat SSL et un autre Proxy Host pour notre troisième sous domaine, car il ira sur un autre container. La seule différence dans la configuration sera le Forward Hostname qu'on mettra à dcunstableapp, qui sera notre container de test.
Voila nos redirections sous configurées.

5. Les containers de blog

Le container hébergeant nos deux premiers blogs sera basé sur la version stable Doclear et utilisera une base de donnée Mysql.
On retourne dans notre terminal SSH et on creé le répertoire du volume persistant et on modifie le fichier docker-compose.yml qu'on a créé un peu plus tôt.

mkdir dcstable
nano docker-compose.yml

On ajoute les deux services Dotclear et MariaDB :

networks:
  default:
    name: npm

services:
  # Nginx proxy manager
  npmapp:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    container_name: npmapp
    ports:
      - 80:80
      - 443:443
      - 81:81
    volumes:
      - ./npm/data:/data
      - ./npm/letsencrypt:/etc/letsencrypt
    healthcheck:
      test: ["CMD", "/usr/bin/check-health"]
      interval: 10s
      timeout: 3s

  # Mariadb database
  dcstabledb:
    image: mariadb:latest
    container_name: dcstabledb
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
      - ./dcstable/db:/var/lib/mysql
    depends_on:
      npmapp:
        condition: service_healthy
    environment:
      MYSQL_ROOT_PASSWORD: dotclear_root
      MYSQL_DATABASE: dotclear_db
      MYSQL_USER: dotclear_user
      MYSQL_PASSWORD: dotclear_pwd
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      start_period: 10s
      interval: 10s
      timeout: 5s
      retries: 3

  # Doclear web application
  dcstableapp:
    image: jcpd/docker-dotclear:latest
    container_name: dcstableapp
    restart: unless-stopped
    volumes:
      - ./dcstable/app:/var/www/dotclear
    depends_on:
      dcstabledb:
        condition: service_healthy
    environment:
      DC_DBDRIVER: mysqlimb4
      DC_DBHOST: dcstabledb
      DC_DBNAME: dotclear_db
      DC_DBUSER: dotclear_user
      DC_DBPASSWORD: dotclear_pwd
      DC_DBPREFIX: dc_
      DC_ADMINMAILFROM: contact@exemple.com

Ne pas oublier de remplacer dotclear_root, dotclear_user et dotclear_pwd par des valeurs personnelles !
On voit que les 3 services sont configurés depuis le même fichier, c'est pratique ! Et une astuce ici est d'attendre qu'un service soit fonctionnel pour démarrer le suivant, on commence par le Proxy puis la base de données et enfin le serveur web, grâce à la directive depends_on.
On exécute la composition avec :

docker compose up -d

Et on attend que tous les services soient fonctionnels puis dans notre navigateur web on entre l'adresse du premier blog http://blog.mondomaine.tld la phase finale de configuration de Dotclear devrait apparaitre.
Création du super admin Dotclear
On rentre les informations de notre utilisateur super admin, on valide deux fois et on arrive dans l'interface d'administration du multiblog.

Par défaut les images Docker de Dotclear sont configurées pour fonctionner en local en sous-répertoire, car elles ont été pensé pour simplement tester Dotclear dans son coin, chez soi. Mais nous travaillons dans notre exemple, à distance en sous-domaine. Il va donc falloir faire quelques ajustements.
Le premier changement est que nous travaillons avec des certificats SSL en https, il faut modifier l'adresse de l'administration de Dotclear dans son fichier de configuration, pour cela dans le terminal SSH on édite le fichier config.php :

nano dcstable/app/config.php

On cherche la ligne :

// Admin URL. You need to set it for some features.
define('DC_ADMIN_URL','http://blog.mondomaine.tld/admin/');

Qu'on remplace par :

// Admin URL. You need to set it for some features.
define('DC_ADMIN_URL','https://blog.mondomaine.tld/admin/');

La différence ? On a ajouté le S à http. On enregistre et on retourne dans l'interface web d'administration.

Le premier blog est configuré par le script d'installation de Dotclear pour être en sous répertoire, il faut donc modifier la façon dont Dotclear va gérer certaines URLs.
On parcourt les menus Blog -> Paramètres du blog -> Paramètres avancés du blog
( https://blog.mondomaine.tld/admin/index.php?process=BlogPref#advanced-pref )
et on modifie Url du blog de http://blog.mondomaine.tld/default/ à https://blog.mondomaine.tld/. Et on valide.
Ensuite on parcourt les menus Réglages système -> about:config -> system
( https://blog.mondomaine.tld/admin/index.php?process=Plugin&p=aboutConfig#l_system )
et on modifie l'entrée public_url de /default/public à /public . et on valide.

Le premier blog créer par le script d'installation de Dotclear porte l'ID default, la configuration d'origine des images Docker va rediriger le sous domaine nommé blog vers l'ID default, si le sous domaine du premier blog n'est pas nommé blog, il faudra aussi modifier le fichier de configuration de Nginx :

nano dcstable/app/servers/subdomain.conf

Et modifier :

# Redirect a particular subdomain
    if ($dc_blog_id = 'blog') {
            set $dc_blog_id default;
    }

en remplaçant par le sous domaine de votre premier blog :

# Redirect a particular subdomain
    if ($dc_blog_id = 'plop') {
            set $dc_blog_id default;
    }

Voilà, notre premier blog est prêt.

On va maintenant créer notre second blog. Pour cela on parcourt les menus Réglages système -> Blogs -> Créer un nouveau blog et on remplie le formulaire. L'identifiant sera le sous domaine perso, le nom du blog sera ce que vous voulez, et l'URL sera https://perso.mondomaine.tld/ (ne pas oublier le / à la fin ! ). On valide. Voila notre second blog est prêt, rien d'autre à faire.

Vous aurez compris la démarche pour ajouter autant de blog que vous voulez à votre multiblog.
Créer la Zone DNS, créer un Certificat SSL, créer un Proxy Host, créer un blog.

6. Le blog de test

On aurait pu s'arrêter là mais comme on est gourmand on va ajouter un multiblog de test à notre installation, vous vous rappelez au début on a configuré 3 sous domaines chez notre registrar, il nous reste donc à utiliser le troisième test.mondomaine.tld.
Les premières étapes sont identiques, si on ne les a pas fait au début, on créé un certificat pour ce sous domaine, on créé un Proxy Host qui aura comme Forward Hostname le nom du futur container dcsunstableapp, le reste est identique à ce qu'on à fait précédemment.
Ensuite on va ajouter notre container de test, on va dans le terminal SSH et on ajoute le dossier pour le volume persistant et on édite le fichier de docker-compose.yml :

mkdir dcunstable
nano docker-compose.yml

On complète notre composition en ajoutant à la fin notre dernier container pour le multiblog de test :

networks:
  default:
    name: npm

services:
  # Nginx proxy manager
  npmapp:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    container_name: npmapp
    ports:
      - 80:80
      - 443:443
      - 81:81
    volumes:
      - ./npm/data:/data
      - ./npm/letsencrypt:/etc/letsencrypt
    healthcheck:
      test: ["CMD", "/usr/bin/check-health"]
      interval: 10s
      timeout: 3s

  # Mariadb database
  dcstabledb:
    image: mariadb:latest
    container_name: dcstabledb
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
      - ./dcstable/db:/var/lib/mysql
    depends_on:
      npmapp:
        condition: service_healthy
    environment:
      MYSQL_ROOT_PASSWORD: dotclear_root
      MYSQL_DATABASE: dotclear_db
      MYSQL_USER: dotclear_user
      MYSQL_PASSWORD: dotclear_pwd
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      start_period: 10s
      interval: 10s
      timeout: 5s
      retries: 3

  # Doclear web application
  dcstableapp:
    image: jcpd/docker-dotclear:latest
    container_name: dcstableapp
    restart: unless-stopped
    volumes:
      - ./dcstable/app:/var/www/dotclear
    depends_on:
      dcstabledb:
        condition: service_healthy
    environment:
      DC_DBDRIVER: mysqlimb4
      DC_DBHOST: dcstabledb
      DC_DBNAME: dotclear_db
      DC_DBUSER: dotclear_user
      DC_DBPASSWORD: dotclear_pwd
      DC_DBPREFIX: dc_
      DC_ADMINMAILFROM: contact@exemple.com

  # Dotclear test
  dcunstableapp:
    image: jcpd/docker-dotclear:dev
    container_name: dcunstableapp
    restart: unless-stopped
    volumes:
      - ./dcunstable/app:/var/www/dotclear
    depends_on:
      npmapp:
        condition: service_healthy
    environment:
      DC_DBDRIVER: sqlite
      DC_DBNAME: \var\www\dotclear\sqlite.db
      DC_ADMINMAILFROM: contact@exemple.com

On voit ici qu'on utilise l'image Docker de Doclear en version dev (de la branche unstable) et qu'on aura une base de données SQLite qui sera dans le même container. On enregistre en on relance la composition.

docker compose up -d

Comme le sous domaine par défaut de notre multiblog de test n'est pas blog mais test, il faut aussi modifier le fichier de configuration de Nginx :

nano dcunstable/app/servers/subdomain.conf

Et modifier :

# Redirect a particular subdomain
    if ($dc_blog_id = 'blog') {
            set $dc_blog_id default;
    }

en remplaçant par :

# Redirect a particular subdomain
    if ($dc_blog_id = 'test') {
            set $dc_blog_id default;
    }

On se rend dans le navigateur web à l'adresse du troisième blog https://test.mondomaine.tld et on suit les étapes comme pour les deux premiers blogs.

Voilà, notre environnement multiblog Dotclear est prêt !

7. Plus loin On va aller un peu plus loin en créant un petit script qui va mettre à jour notre environnement en une seul commande. Rien de bien méchant, il va juste mettre à jour les images des containers. (Et donc mettre à jour Dotclear également).
Dans le terminal SSH, on édite le fichier update.sh :

nano update.sh

Dedans on va arrêter les containers, mettre à jour les images et redémarrer les container, ce qui donne :

#!/bin/sh -x

docker compose -p npmapp stop \
&& docker compose -p dcstabledb stop \
&& docker compose -p dcstableapp stop \
&& docker compose -p dcunstableapp stop \
&& docker pull jc21/nginx-proxy-manager:latest \
&& docker pull mariadb:latest \
&& docker pull jcpd/docker-dotclear:latest \
&& docker pull jcpd/docker-dotclear:unstable\
&& docker compose -f docker-compose.yml up -d \
&& docker image prune -af

On enregistre et on rend le fichier exécutable :

sudo chmod +x update.sh

On test :

update.sh

On doit voir les containers s'arrêter, les images se mettre à jour, et les containers redémarrer.

L'utilisation d'un proxy amène un autre problème, les IPs des utilisateurs ne sont pas transmises à Dotclear, ce qui va empêcher l'antispam de fonctionner correctement. On va corriger cela en ajoutant une règle dans notre configuration Nginx.
D'abord on va chercher l'IP interne de NPM, dans le terminal SSH on lance la commande :

docker network inspect npm

S'affiche alors un liste de configuration réseau des containers. On repère les lignes IPv4Address, par exemple 172.20.0.2/16, cela va nous servir de base. On édite le fichier de configuration Nginx :

nano dcstable/app/servers/subdomain.conf

On ajoute juste après servers { la règle suivant :

real_ip_header    X-Forwarded-For;
    set_real_ip_from  172.20.00./16;

On a pris une des IP listée ci-dessus et qu'on a simplifié en mettant 0 dans la place du dernier chiffre. Pour faire simple, on va transférer l'IP entrante pour tout ce qui vient du bloc d'IP 172.20.x.x. Une fois enregistré, on relance le container pour que ce soit pris en compte.

docker -p dcstableapp restart

L'antispam Dotclear nous dira merci.

8. FIN

Cette article est terminé. Il est loin d'être complet et à adapter à vos besoins mais c'est un bonne base pour savoir utiliser les images Docker de Dotclear.

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

La discussion continue ailleurs

URL de rétrolien : https://docker.dotclear.watch/trackback/249