Salut a tous,

Pour faire suite a ma question d'ici et apres avoir mis ca en place, je me suis dit pourquoi ne pas en faire un tuto. Je ne vais pas rentrer ici dans les details en ce qui concerne l'obtention du certificat, la configuration d'apache pour le https ou la configuration d'autres logiciels mais juste presenter le concept et comment mettre ca en place (par contre il faudra que vous fassiez d'autres recherches pour la configuration complete des logiciels). Je ne presente ici que le concept et les etapes strictement necessaires, a vous de regarder plus en detail les parametrages de chaque logiciel utilise.

Je presente ici la methode que moi j'ai trouve la plus logique et la plus simple a mettre en place (ce ne sera peut etre pas le cas pour vous), et meme si ce n'est peut etre pas la meilleure methode, d'apres les quelques tests que j'ai fais, ca marche (mon certificat a ete auto-renouvelle il y a quelques jours sans meme que je ne m'en apercoive🙂)

Comme je l'ai mentionne dans ma question l'idee est d'avoir plusieurs serveurs qui hebergent le meme nom de domaine, c'est a dire que l'on va avoir dans la definition du DNS :

domaine.fr			IN	A	1.1.1.1
domaine.fr				IN	A	1.1.1.2
serv1.domaine.fr			IN	A	1.1.1.1
serv2.domaine.fr			IN	A	1.1.1.2
letsencrypt.domaine.fr		IN	A	1.1.1.1

Ce qui veux dire que sur serv1 et serv2 tourne un serveur web (Apache2 dans mon cas) et le serveur DNS va rediriger les clients souhaitant se connecter a domaine.fr soit vers serv1 soit vers serv2 et tout les 2 doivent pouvoir repondre en HTTPS (ici dans l'exemple il n'y a que 2 serveurs, mais c'est realisable egalement avec plus de 2 serveurs). Le sous-domaine letsencrypt.domaine.fr est redirige vers serv1 (ce sera le serveur « maitre » pour le renouvellement du certificat).

INSTALLATION DE CERTBOT (aussi connu sous le nom de letsencrypt)

Cette operation est a faire uniquement sur un des serveurs (qui sera considere comme « maitre », alors que les autres seront consideres comme « esclaves »), dans mon cas c'est sur serv1. Personnellement j'ai installe certbot depuis les depots backports de Debian Jessie.

On rajoute le depot backports au fichier sources.list :

# vim /etc/apt/sources.list
#jessie-backports
deb http://ftp.fr.debian.org/debian jessie-backports main

On fait un update et on install le paquet certbot depuis le depot backports :

# apt-get update && apt-get install certbot -t jessie-backports

CONFIGURATION DU SERVEUR WEB (apache2 dans mon cas)

Je ne vais pas presenter ici l'installation et la configuration d'apache, mais uniquement la partie qui nous interesse, notamment celle liee a l'obtention et le renouvellement du certificat.

Sur serv1 (le « maitre ») :

On cree les dossiers necessaires :

# mkdir -p /var/www/domaine.fr/www
# mkdir -p /var/www/domaine.fr/letsencrypt/.well-known/acme-challenge

On modifie le fichier de configuration d'apache :

# vim /etc/apache2/sites-available/000-default.conf
<VirtualHost 1.1.1.1:80>

    ServerName domaine.fr
    ServerAlias www.domaine.fr
    ServerAlias serv1.domaine.fr

    ServerAdmin webmaster@domaine.fr
    DocumentRoot /var/www/domaine.fr/www

    ProxyPass "/.well-known/acme-challenge/" "http://letsencrypt.domaine.fr/.well-known/acme-challenge/"

    ErrorLog ${APACHE_LOG_DIR}/domaine.fr/www/error.log
    CustomLog ${APACHE_LOG_DIR}/domaine.fr/www/access.log combined

</VirtualHost>


<VirtualHost 1.1.1.1:80>

    ServerName letsencrypt.domaine.fr

    ServerAdmin webmaster@domaine.fr
    DocumentRoot /var/www/domaine.fr/letsencrypt

    <Directory />
            Order Deny,Allow
            Deny from all
            Allow from 1.1.1.1 # on autorise uniquement serv1 et
            Allow from 1.1.1.2 # serv2 a acceder a letsencrypt.domaine.fr
    </Directory>

    <Directory "/var/www/domaine.fr/letsencrypt/.well-known/acme-challenge/">
            Options +MultiViews +Indexes +SymLinksIfOwnerMatch +IncludesNoExec
            Require method GET POST OPTIONS
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/domaine.fr/letsencrypt/error.log
    CustomLog ${APACHE_LOG_DIR}/domaine.fr/letsencrypt/access.log combined

</VirtualHost>

A present sur serv2 :

On modifie le fichier /etc/apache2/sites-available/000-default.conf :

# vim /etc/apache2/sites-available/000-default.conf
<VirtualHost 1.1.1.2:80>

    ServerName domaine.fr
    ServerAlias www.domaine.fr
    ServerAlias serv2.domaine.fr

    ServerAdmin webmaster@domaine.fr
    DocumentRoot /var/www/domaine.fr/www

    ProxyPass "/.well-known/acme-challenge/" "http://letsencrypt.domaine.fr/.well-known/acme-challenge/"

    ErrorLog ${APACHE_LOG_DIR}/domaine.fr/www/error.log
    CustomLog ${APACHE_LOG_DIR}/domaine.fr/www/access.log combined

</VirtualHost>

Donc ce qu'on a fait la c'est : lorsqu'un client solicite http://domaine.fr/.well-known/acme-challenge (ce que Let's Encrypt fait lors de l'obtention ou du renouvellement du certificat) ou ses equivalents (www.domaine.fr, serv1.domaine.fr, serv2.domaine.fr) il sera redirige vers http://letsencrypt.domaine.fr/.well-known/acme-challenge, la ou se trouveront les fichiers de verification de certbot au moment de l'obtention ou du renouvellement du certificat.

OBTENTION DU CERTIFICAT

Maintenant que le serveur web est configure et que le paquet certbot est installe sur serv1 on peut executer la commande d'obtention du certificat (a nouveau uniquement sur serv1) :

# certbot certonly --rsa-key-size 4096 --webroot -w /var/www/domaine.fr/letsencrypt/ -d domaine.fr -d www.domaine.fr -d serv1.domaine.fr -d serv2.domaine.fr --email moi@domaine.fr –agree-tos

Normalement si tout c'est bien passe vous devrier avoir vos certificats dans /etc/letsencrypt/live/domaine.fr/ (qui en realite sont des liens symboliques vers /etc/letsencrypt/archive/domaine.fr/

Le soucis a present est que le certificat ne se trouve que sur serv1, il faut donc trouver un moyen de l'envoyer sur serv2. A noter que l'idee ici est que le certificat doit se trouver sur serv1 ET sur serv2 ; il ne faut pas uniquement donner acces a serv2 au certificat sur serv1. En plus clair, ca veut dire qu'il faut trouver un moyen de copier les certificats sur serv2, car si on ne fait que lui donner acces au certificats sur serv1, si serv1 est HS, serv2 ne pourra pas acceder aux certificats et ne pourra donc pas servir le site en HTTPS.

La solution que j'ai trouve dans ce cas est de faire un rsync entre serv1 et serv2 pour synchroniser le dossier /etc/letsencrypt.

MISE EN PLACE DE LA SYNCHRONISATION

Sur serv2 il faut installer rsync et le configurer (a vous de regarder comment lancer le demon au lancement du systeme) :

# apt-get install rsync
# vim /etc/rsyncd.conf
log file = /var/log/rsyncd/rsyncd
pid file = /var/run/rsyncd.pid
secrets file = /etc/rsyncd.secrets

[letsencrypt]
        comment = Letsencrypt
        path = /etc/letsencrypt
        read only = no
        list = no
        auth users = root
        max connections = 4
        lock file = /var/run/rsyncd.letsencrypt.lock
        uid = root
        gid = root
        transfer logging = yes

Rajouter l'utilisateur root et un mot de passe :

# vim /etc/rsyncd.secrets
root:p4$$wd

Je vous laisse regarder du cote de rsync et rsyncd pour plus de parametres.

Il faut egalement créer le dossier /etc/letsencrypt sur serv2 :

# mkdir /etc/letsencrypt

Sur serv1 on va installer rsync et creer quelques fichiers.

Installation de rsync

# apt-get install rsync

Le script qui fera la synchronisation a proprement parler (modifier la valeur SERVER avec l'ip de serv2 dans le script) :

# vim /root/.certbot/rsync
#!/bin/bash

SERVER="1.1.1.2"
TMP_FILE="/var/log/letsencrypt/rsync"
PING="`/bin/ping -q -c 1 $SERVER | grep received | awk '{print $4}'`"
PID="/tmp/rsync-letsencrypt.pid"

if [ -f $PID ]; then
        exit
fi

touch $PID

while [ "$PING" != "1" ]; do
        sleep 10                
        PING="`/bin/ping -q -c 1 $SERVER | grep received | awk '{print $4}'`"
done

RSYNC="`which rsync`"

if [ -z $RSYNC ]; then
        echo "rsync non installe" > $TMP_FILE
        if [ -f $PID ]; then
                rm -f $PID
        fi
        exit
fi

$RSYNC -n -r -t -p -o -g -v --progress --delete -l -H --password-file=/root/.certbot/rsync_passwd --exclude-from="/root/.certbot/rsync_exclude" --bwlimit=20000 /etc/letsencrypt/ root@$SERVER::letsencrypt >> $TMP_FILE

if [ "$?" != "0" ]; then
        echo "Probleme lors de l'execution de rsync letsencrypt" >> $TMP_FILE
fi

if [ -f $PID ]; then
        rm -f $PID
fi

Et on le rend executable :

# chmod +x /root/.certbot/rsync

On cree ensuite le fichier de mot de passe pour rsync et on y met le mot de passe defini sur serv2 (uniquement le mot de passe, pas l'utilisateur) :

# vim /root/.certbot/rsync_passwd
p4$$wd

Et le fichier d'exclusion (se sont des dossiers qui se trouvent sur serv1 et dont serv2 n'a pas besoin) :

# vim /root/.certbot/rsync_exclude
accounts
csr
keys
renewal

Donc pour resumer, on a cree l'acces rsync pour que serv1 puisse synchroniser /etc/letsencrypt avec celui de serv2. Maintenant il faut trouver un moyen pour executer le script /root/.certbot/rsync lorsque le certificat est renouvele (si vous avez installe certbot depuis le depot backports, le renouvelement se fait automatiquement, vous n'avez rien a parametrer, a vous de voir si c'est le cas chez vous). Et la solution dans ce cas est inotify-tools et notamment inotifywait qui permet de surveiller un dossier et executer une commande lors d'une activite sur ce dossier (creation, suppression, etc). Il faut donc installer ce paquet :

# apt-get install inotify-tools

Et creer le script /root/.certbot/certbot qui permet de lancer la surveillance du dossier /etc/letsencrypt et lancer les commandes /root/.certbot/services et /root/.certbot/rsync

# vim /root/.certbot/certbot
#!/bin/bash

sleep 60

while true
do
        inotifywait -qr -o /var/log/letsencrypt/inotifywait -e modify,move,create,delete /etc/letsencrypt && sleep 60 && /root/.certbot/services && /root/.certbot/rsync
done

Ainsi que le script /root/.certbot/services qui recharge la configuration des logiciels utilisant le certificat une fois le renouvellement realise :

# vim /root/.certbot/services
#!/bin/bash

systemctl reload apache2 &

Dans mon cas je recharge apache2 pour qu'il prenne en compte le nouveau certificat (si vous configurez d'autres services pour qu'ils utilisent le certificat letsencrypt, n'oubliez pas de les rajouter ici).

On rend les 2 scripts executables :

# chmod +x /root/.certbot/services
# chmod +x /root/.certbot/rsync

Et enfin en tant que root on fait un :

# crontab -e
@reboot /bin/bash /root/.certbot/certbot &

Pour lancer le script /root/.certbot/certbot au demmarage du serveur.

Sur serv2 il faut refaire a peu pres les memes etapes :

Le script /root/.certbot/services qui permettra de recharger la configuration des logiciels utilisant le certificat :

# vim /root/.certbot/services
#!/bin/bash

systemctl reload apache2 &

Installation de inotify-tools

# apt-get install inotify-tools

Creation du script certbot qui permet de surveiller /etc/letsencrypt pour lancer le script /root/.certbot/services lorsque serv1 aura synchronise son dossier /etc/letsencrypt avec celui de serv2

# vim /root/.certbot/certbot
#!/bin/bash

sleep 60

while true
do
        inotifywait -qr -o /var/log/letsencrypt/inotifywait -e modify,move,create,delete /etc/letsencrypt && sleep 60 && /root/.certbot/services
done

On les rends executables :

# chmod +x /root/.certbot/services
# chmod +x /root/.certbot/rsync

Et on rajoute le script /root/.certbot/certbot a crontab pour qu'il se lance au demarrage du serveur :

# crontab -e
@reboot /bin/bash /root/.certbot/certbot &

Il ne reste plus qu'a redemmarer les 2 serveurs.

CONCLUSION

La logique a suivre ici est :

  • Les serveurs serv1 et serv2 demarrent, et grace au crontab @reboot lance le script /root/.certbot/certbot sur chacune des machines (a chaque redemarrage)

  • Le moment venu, le certificat est renouvelle par certbot sur serv1 et le nouveau certificat se retrouve dans /etc/letsencrypt/ sur serv1

  • Les scripts /root/.certbot/services et /root/.certbot/rsync sur serv1 sont lances car il y a eu une modification dans le dossier /etc/letsencrypt sur serv1 ; le premier script recharge la configuration des logiciels utilisant le certificat et le second lance la synchronisation vers serv2

  • Une fois ces etapes franchi, tout est en place sur serv1, il ne reste maintenant que serv2

  • Lorsque la synchronisation a ete effectuee sur serv2, le script /root/.certbot/services est lance (au travers de inotifywait) pour recharger les services qui utilisent le certificat

  • Le nouveau certificat se trouve a present sur les 2 serveurs et les services utilisant ce certificat peuvent a present offrir un acces securise

Dans ce tuto je ne suis pas rentre dans les details, a vous donc de paramtrer apache2 ou nginx pour l'utilisation du https (et peut etre utiliser un vpn entre les 2 serveurs afin que le rsync ne se fasse pas en clair mais au travers du vpn).
Comme je l'ai dit au debut du tuto, mon certificat a ete renouvelle automatiquement sur les 2 serveurs il y a quelques jours, donc on peut dire que ca marche ; si ca ne marche pas pour vous regardez les differents logs (apache, rsync, scripts…), soit vous n'avez pas suivis toutes les etapes, soit vous etes tombez sur une situation que je n'ai pas prevu.

J'espere avoir ete clair dans mes explications (?) et que mon barratin est comprehensible 🙂
Pour toute question, remarque, amelioration a apporter, direction le topic initial.

Salut,

Merci 🙂
Peut être une question un peu HS mais étant plus porté sur du load-balancing via HAProxy, quel est l'intérêt de la duplication d'un Apache/Nginx sur plusieurs serveurs ? Hors contexte de site à très fort trafic et duplication à chaud en cas de pépin.

    Aerya Aucun interet en tant que tel. Je suis en train de monter divers trucs et pour l'instant je suis pas encore a la partie load-balancing (au vrai sens du terme, car le serveur DNS redirige les queries a peu pres de maniere egale mais c'est pas du vrai load-balancing).
    Donc j'avais besoin que les 2 serveurs dont je dispose puisse repondre au meme nom de domaine ; j'ai un serveur chez Online et un serveur chez Kimsufi, et comme c'est des bas de gamme je ne suis pas a l'abri d'une defaillance du disque ou du reseau (c'est deja arrive) ; je voudrais donc que le service offert par ces 2 serveurs soit toujours accessible dans ce cas la.
    Et oui, le mieux c'est de virtualiser tout ca et d'avoir des instances pretes a repondre en cas de pepin (et j'y arriverais surement un jour), mais pour l'instant c'est la solution que j'ai mis en place et qui me va (en meme temps nous ne sommes que 2 sur ces serveurs pour l'instant ; et je ne les utilisent pas comme seedbox, plutot serveurs web, mail, fichiers personnels, et surtout pour apprendre).
    On verra a l'avenir 🙂

    7 jours plus tard
    Répondre…