This site uses cookies! Learn More

Ce site utilise des cookies !

En continuant à utiliser ce site, vous vous engagez à nous permettre de stocker des cookies sur votre ordinateur.

nasmanu

Mise en place Haproxy & Letsencrypt dans Docker

32 messages dans ce sujet

Hello tout le monde,

Suite à l'expiration de mon certificat (startssl) et du crash de Haproxy en DSM 6, je me suis mis en tête de refaire fonctionner Haproxy via Docker et d'utiliser Letsencrypt qui est mis a disposition.

Non sans mal, j'ai réussis à faire tourner Haproxy via Docker mais je bute sur l'installation (et l'automatisation du renouvellement du certificat) via Letsencrypt.

En effet, je souhaite comme auparavant forcer toutes les connexions en https mais sans certificat je ne peux remettre ce paramétrage donc aujourd'hui je dois accéder au NAS en http classique.

 

Je me suis aidé de ce tuto https://yaple.net/2016/07/10/letsencrypt-haproxy-and-auto-renewal/ mais je bloque sur la création du certificat, j'ai le message d'erreur suivant en exécutant le script : cert_renewal.sh

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
An unexpected error occurred:
ConnectionError: HTTPSConnectionPool(host='acme-v01.api.letsencrypt.org', port=443): Max retries exceeded with url: /directory (Caused by NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7f69f4785790>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',))
Please see the logfiles in /var/log/letsencrypt for more details.

 

Mon traceroute -n -p 443 acme-v01.api.letsencrypt.org n'arrive pas à joindre l’hôte mais je ne sais pas pourquoi ...

 

Quelqu'un aurait une idée ou un meilleur tuto pour faire fonctionner Letsencrypt avec Haproxy sous Dockerv?

 

Merci par avance pour votre aide,

Partager ce message


Lien à poster
Partager sur d’autres sites

Ton docker n'a pas accès au net.

J'ai regardé vite fait le tuto et le Dockerfile lié, autant en refaire un toi même, il sera plus petit et plus rapide (surtout si tu utilises autre chose que certbot)

D'autres exemples :

http://www.automationlogic.com/using-lets-encrypt-and-docker-for-automatic-ssl/

https://techan.fr/securiser-haproxy-avec-lets-encrypt-dans-docker/

Dans tous les cas, le principe reste le même :

  1. tu fais en sorte que le port 80 de ton routeur tombe sur un conteneur contenant un reverse proxy (haproxy, nginx, varnish, apache ...)
  2. ce conteneur intercepte les requêtes vers .well-known et les renvoi vers un autre conteneur
  3. ce 2nd conteneur tu ne le lances qu'au moment du renouvellement

Tout le reste c'est de l'automatisation pour mettre à jour les certificats des différentes appli (quelques lignes de script).

Il existe une autre approche (que j'utilise), la validation par DNS.

Sinon, le plus simple : tu utilises le synology pour gérer tes certificats, la seule contrainte est de couper ton docker le temps du renouvellement afin de libérer le port 80

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a 37 minutes, Fenrir a dit :

Sinon, le plus simple : tu utilises le synology pour gérer tes certificats, la seule contrainte est de couper ton docker le temps du renouvellement afin de libérer le port 80

Et encore plus simple, il coche utiliser le même réseau que docker host lors de la création et plus de problème de conflit ou blocage de port

Partager ce message


Lien à poster
Partager sur d’autres sites

merci à vous deux pour vous êtes penché sur mon cas.

A chaud, j'ai refais un conteneur en cochant la case pour utiliser le même réseau mais j'ai la même erreur, le problème doit être plus profond au niveau de mon paramétrage...

au niveau du routeur j'ai laissé comme avant pour haproxy avec l'ouverture des ports 80 et 443.

Faut-il faire différemment pour que cela fonctionne pour le conteneur ?

 

je vais regarder encore un peu plus tout cela mais ce n'est pas simple...

merci encore

Partager ce message


Lien à poster
Partager sur d’autres sites

Ton nas a accès au net ?

ps : je suis entrain de faire un Dockerfile avec tout ça, juste pour jouer, si ça fonctionne je te le passerai

Partager ce message


Lien à poster
Partager sur d’autres sites

oui mon nas a accès a Internet et Haproxy fonctionne bien en http
j'ai que le problème pour ajouter un certificat ssl et de tout passer en htpps.

en tout cas @Einsteinium a vu juste pour un point, j'ai bloqué toutes les connexions hors de la France...en décochant ce paramètre au niveau du pare feu cela avance mais il y a un soucis pour l'obtention du certificat

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for mon.domaine.fr
Waiting for verification...
Cleaning up challenges
Failed authorization procedure. mon.domaine.fr (tls-sni-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Incorrect validation certificate for tls-sni-01 challenge. Requested 63f7d0b45c32ae6ad7d7c3b49dbcecb4.93129daba91877f18bdd8125a8142eb0.acme.invalid from MONIP:443. Received 1 certificate(s), first certificate had names "mon.domaine.fr"
IMPORTANT NOTES:
 - If you lose your account credentials, you can recover through
   e-mails sent to email@domaine.fr.
 - The following errors were reported by the server:

   Domain: mon.domaine.fr
   Type:   unauthorized
   Detail: Incorrect validation certificate for tls-sni-01 challenge.
   Requested
   63f7d0b45c32ae6ad7d7c3b49dbcecb4.93129daba91877f18bdd8125a8142eb0.acme.invalid
   from MONIP:443. Received 1 certificate(s), first
   certificate had names "mon.domaine.fr"

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A record(s) for that domain
   contain(s) the right IP address.
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.

 

Partager ce message


Lien à poster
Partager sur d’autres sites

La c'est un problème concernant l'autorisation de ton domaine maintenant, je n'utilise pas donc je laisse les autres répondre

Partager ce message


Lien à poster
Partager sur d’autres sites

C'est le "challenge" qui a échoué => LE n'est pas arrivé à contacter certbot => il faut vérifier :

  • dns
  • transfert de port (en intégrant
  • fw
  • haproxy

Partager ce message


Lien à poster
Partager sur d’autres sites

merci @Fenrir.

Peux-tu préciser un peu plus les points que je dois checker car je ne vois pas bien quoi faire..dsl (et j'ai l'impression qu'il manque un mot ou deux dans tes phrases)

Partager ce message


Lien à poster
Partager sur d’autres sites

:lol: non il ne manque pas de mots, il y en a même 2 en trop (en intégrant)

Tout ce que je disais, c'est qu'il faut vérifier les différents points :

  • dns : le nom de domaine pour lequel tu souhaites émettre un certificat est il bien dirigé vers ton IP publique ?
  • transfert de port : le port 80 est il bien transféré vers le port qui va bien (celui utilisé par haproxy) sur le nas ?
  • fw : le parefeu du nas autorise t'il bien le trafic venant d'Internet vers ce port ?
  • haproxy : la conf de haproxy est elle bonne ?

Partager ce message


Lien à poster
Partager sur d’autres sites

lol je viens de comprendre aussi que "LE" = Letsencrypt et non pas le particule "le" ^^'

alors pour répondre en ordre :

dns : oui ca fait des années que je l'utilise
transfert de port : oui j'ai utilisé mon ancienne conf d'haproxy donc mon port 80 est redirigé vers le port 7070 mais maintenant j'ai des doutes
fw : par défaut non mais même quand je désactive le fw j'ai la meme erreur
haproxy : voici la conf...

global
	debug
	log 172.17.0.2:514 local1
	tune.ssl.default-dh-param 2048

defaults
	log global
	mode http
        timeout connect 2000ms
        timeout client 50000ms
        timeout server 50000ms

frontend http 
	log global
	bind *:7070
	option http-server-close
	option forwardfor
	acl letsencrypt-request path_beg -i /.well-known/acme-challenge/
	use_backend letsencrypt_backend if letsencrypt-request
	use_backend dsm if { hdr_beg(Host) -i nas. }

frontend https
        log global
	bind *:7071 ssl crt /etc/haproxy/certs/cert.pem npn spdy/2 ciphers ECDHE-RSA-AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM
	option http-server-close
	option forwardfor
	http-request set-header X-Forwarded-Port %[dst_port]
	http-request set-header X-Forwarded-Proto https if { ssl_fc }
	http-request set-header X-Forwarded-Host %[dst]
	rspirep ^Location:\ http://(.*)$    Location:\ https://\1
	rspadd Strict-Transport-Security:\ max-age=31536000;\ includeSubDomains
	reqadd X-Forwarded-Proto:\ https
	acl letsencrypt-request path_beg -i /.well-known/acme-challenge/
	use_backend letsencrypt_backend if letsencrypt-request
	use_backend dsm if { hdr_beg(Host) -i nas. }
		
backend dsm
	server dsm localhost:7080 check

backend letsencrypt_backend
	server letsencrypt 127.0.0.1:49494

 

Modifié par nasmanu

Partager ce message


Lien à poster
Partager sur d’autres sites

je ne suis pas un expert d'haproxy (pour tout te dire, je ne l'utilise pas, j'ai remis le nez dedans hier suite à ton poste), mais avec juste ce qui suit, ça fonctionne :

frontend ssl_redirector
    bind *:443 ssl crt /etc/haproxy/ssl/
    http-request del-header X-Forwarded-Proto
    http-request set-header X-Forwarded-Proto https if { ssl_fc }

    acl letsencrypt-request path_beg -i /.well-known/acme-challenge/
    use_backend letsencrypt_backend if letsencrypt-request

    default_backend user_backend

frontend http_redirect
    bind *:80

    acl letsencrypt-request path_beg -i /.well-known/acme-challenge/
    redirect scheme https code 301 if !letsencrypt-request

    use_backend letsencrypt_backend if letsencrypt-request

backend letsencrypt_backend
    server letsencrypt 127.0.0.1:11444

backend user_backend
    server server01 127.0.0.1:11080

Sinon j'ai bientôt terminé bien mon Dockerfile (haproxy + acme.sh), qui devrait faire à peu près la même chose ...

Modifié par Fenrir

Partager ce message


Lien à poster
Partager sur d’autres sites

Voici la version 0.0.1, pas du tout optimisé, mais fonctionnelle (testé sur mon syno).

L'image fait environ 120mo et le conteneur utilise 25mo de ram, donc ça ne devrait pas consommer trop de ressources (à comparer avec le tiens, mais comme c'est certbot, il doit être obèse et bouffer un max de ram lors de mise à jour des certificats).

  1. Création de l'image : docker build -t acme-haproxy /chemin/vers/le/dockerfile/
  2. Lancement du conteneur : docker run -d --restart always --name haproxy -p 80:80 -p 443:443 -v /volume1/docker/acme-haproxy/cert:/root/.acme.sh -v /volume1/docker/acme-haproxy/conf:/etc/haproxy/conf.d -v /volume1/docker/acme-haproxy/ssl:/etc/haproxy/ssl acme-haproxy
    • les 3 volumes exposés sont :
      • /root/.acme.sh : dossier dans lequel les certificats LE seront enregistrés
      • /etc/haproxy/conf.d : conf d'haproxy (le fichier doit s'appeler user.cfg)
      • /etc/haproxy/ssl : dossier des certificats d'haproxy, ça te permets d'en ajouter d'autres si besoin (par défaut il y a un certificat autosigné temp.pem)
  3. Création d'un certificat : docker exec haproxy /docker-certissue.sh -d www.domaine.fr
    • tu peux ajouter des SAN avec plusieurs -d xxx
  4. Renouvellement de tous les certificats LE : docker exec haproxy /docker-certrenew.sh
    • à mettre en crontab sur le syno
  5. Installation d'un certificat dans haproxy : docker exec haproxy /docker-certinstall.sh www.domaine.fr
    • à lancer pour chaque certificat s'il y en a plusieurs
    • ça permet aussi de relancer haproxy si besoin (un changement dans la conf par exemple)
    • à mettre en crontab sur le syno juste après le renouvellement

J'ai séparé les points 3, 4 et 5 pour permettre plus de flexibilité (par exemple pour gérer des certificats qui ne seront pas utilisés dans haproxy), mais libre à toi de tout regrouper.

Pour tester, j'ai laissé les options --staging (ça créé des certificats non valides mais qui ne comptent pas dans le quota hebdomadaire de LE), --debug et --force =>s'il n'y pas de problèmes, tu peux les enlever.

Pour le reste, tu peux facilement modifier le Dockerfile, il est très simple (il n'y a presque que des "echo").

# fenrir/example
# HAproxy and LetsEncrypt
# TODO : zero downtime
#
# VERSION 0.0.1
#
FROM debian:stretch-slim
MAINTAINER Fenrir <dont@want.spam>

ENV	DEBIAN_FRONTEND noninteractive

# Configure APT and install packages
RUN	echo 'APT::Install-Suggests "false";' > /etc/apt/apt.conf &&\
	echo 'APT::Install-Recommends "false";' >> /etc/apt/apt.conf &&\
	echo 'Aptitude::Recommends-Important "false";' >> /etc/apt/apt.conf &&\
	echo 'Aptitude::Suggests-Important "false";' >> /etc/apt/apt.conf &&\
	apt-get update &&\
	apt-get -y dist-upgrade &&\
	apt-get -y install \
	ca-certificates \
	curl \
	haproxy \
	netcat &&\
	apt-get autoclean && apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb /tmp/* /var/tmp/*

# Configure docker
RUN	mkdir -p /root/.acme.sh &&\
	mkdir -p /etc/haproxy/conf.d &&\
	mkdir -p /etc/haproxy/ssl &&\
	mkdir -p /run/haproxy &&\
# Create entrypoint
	echo "#!/bin/bash" > /docker-entrypoint.sh &&\
	echo "if [ ! -f /etc/haproxy/conf.d/user.cfg ]; then" >> /docker-entrypoint.sh &&\
	echo "	mv /etc/haproxy/haproxy.cfg /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	sed -i '3 d' /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	sed -i '2 d' /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	sed -i '20i        tune.ssl.default-dh-param 2048' /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo 'frontend ssl_redirector' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	bind *:443 ssl crt /etc/haproxy/ssl/' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	http-request del-header X-Forwarded-Proto' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	http-request set-header X-Forwarded-Proto https if { ssl_fc }' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	acl letsencrypt-request path_beg -i /.well-known/acme-challenge/' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	use_backend letsencrypt_backend if letsencrypt-request' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	default_backend website_backend' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo 'frontend http_redirect' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	bind *:80' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	acl letsencrypt-request path_beg -i /.well-known/acme-challenge/' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	redirect scheme https code 301 if !letsencrypt-request' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	use_backend letsencrypt_backend if letsencrypt-request' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo 'backend letsencrypt_backend' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	server letsencrypt 127.0.0.1:11444' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo 'backend website_backend' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "	echo '	server server01 127.0.0.1:11080' >> /etc/haproxy/conf.d/user.cfg" >> /docker-entrypoint.sh &&\
	echo "fi" >> /docker-entrypoint.sh &&\
	echo "if [ ! -f /etc/haproxy/ssl/temp.pem ]; then" >> /docker-entrypoint.sh &&\
	echo "	openssl req -subj '/CN=temp/O=ora/C=RY' -new -newkey rsa:2048 -sha256 -days 100 -nodes -x509 -keyout /tmp/temp.key -out /tmp/temp.crt" >> /docker-entrypoint.sh &&\
	echo "	cat /tmp/temp.key /tmp/temp.crt > /etc/haproxy/ssl/temp.pem" >> /docker-entrypoint.sh &&\
	echo "	curl -o /root/.acme.sh/acme.sh https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh" >> /docker-entrypoint.sh &&\
	echo "	chmod +x /root/.acme.sh/acme.sh" >> /docker-entrypoint.sh &&\
	echo "fi" >> /docker-entrypoint.sh &&\
	echo "/usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/conf.d/user.cfg -p /run/haproxy.pid" >> /docker-entrypoint.sh &&\
	chmod +x /docker-entrypoint.sh &&\
# Certificate issue
	echo "#!/bin/bash" > /docker-certissue.sh &&\
	echo '/root/.acme.sh/acme.sh --issue --staging --standalone --httpport 11444 --force --debug $@' >> /docker-certissue.sh &&\
	chmod +x /docker-certissue.sh &&\
# Certificate renew
	echo "#!/bin/bash" > /docker-certrenew.sh &&\
	echo "/root/.acme.sh/acme.sh --renew-all --staging --standalone --httpport 11444 --force --debug" >> /docker-certrenew.sh &&\
	chmod +x /docker-certrenew.sh &&\
# Certificate apply
	echo "#!/bin/bash" > /docker-certinstall.sh &&\
	echo 'DOMAIN=$1' >> /docker-certinstall.sh &&\
	echo 'ACMESTORE="/root/.acme.sh"' >> /docker-certinstall.sh &&\
	echo 'HAPROXYSTORE="/etc/haproxy/ssl"' >> /docker-certinstall.sh &&\
	echo 'if [ -f $ACMESTORE/$DOMAIN/$DOMAIN.cer ]; then' >> /docker-certinstall.sh &&\
	echo '	cat $ACMESTORE/$DOMAIN/$DOMAIN.key $ACMESTORE/$DOMAIN/$DOMAIN.cer $ACMESTORE/$DOMAIN/ca.cer > $HAPROXYSTORE/$DOMAIN.pem' >> /docker-certinstall.sh &&\
	# echo '	eval $(xargs -0 < /proc/$(pidof haproxy)/cmdline | awk -F '-sf' '{print $1}') -sf $(pidof haproxy)' >> /docker-certinstall.sh &&\
	echo '	haproxy -f /etc/haproxy/conf.d/user.cfg -p /run/haproxy.pid -sf $(cat /run/haproxy.pid)' >> /docker-certinstall.sh &&\
	echo "fi" >> /docker-certinstall.sh &&\
	chmod +x /docker-certinstall.sh

EXPOSE 80/tcp 443/tcp
	
VOLUME ["/root/.acme.sh", "/etc/haproxy/conf.d", "/etc/haproxy/ssl"]

ENTRYPOINT	["/docker-entrypoint.sh"]

nb : je déteste les conteneurs qui vont chercher plein de fichiers de conf sur le net, donc je les fabrique directement dans le Dockerfile, ça limite les surprises

Modifié par Fenrir

Partager ce message


Lien à poster
Partager sur d’autres sites

wow c'est impressionnant le boulot que tu as fait, un grand merci à toi

malheureusement  je n'ai pas réussis a tout dérouler..je suis bloqué au point 2 qui me dit le port 443 est déjà utilisé...

docker: Error response from daemon: driver failed programming external connectivity on endpoint haproxy (074c3a6822546a1ecbb2c0733e03d34d0523257538c0721d461446f98d7c2d1c): Error starting userland proxy: listen tcp 0.0.0.0:443: bind: address already in use.

 

une idée  ? je pense que c'est loin d'être terminé...

Partager ce message


Lien à poster
Partager sur d’autres sites

Il te suffit de choisir un autre port

Il y a 17 heures, Fenrir a dit :

docker run -d --restart always --name haproxy -p 80:80 -p 443:443 -v /volume1/docker/acme-haproxy/cert:/root/.acme.sh -v /volume1/docker/acme-haproxy/conf:/etc/haproxy/conf.d -v /volume1/docker/acme-haproxy/ssl:/etc/haproxy/ssl acme-haproxy

bien entendu le nat de ta box doit suivre ...

Modifié par Fenrir

Partager ce message


Lien à poster
Partager sur d’autres sites

oui c'est vrai que je n'ai pas bcp réfléchis là...juste pour info j'ai du créer l'arborescence des dossiers a la main pour les dossiers /volume1/docker/acme-haproxy/ssl conf etc

ok pour le point 2 et 3, c'est nickel :)

Pour le point 5, j'ai ce message d'erreur, je n'ai rien trouvé de concluant sur le net à ce sujet. enfin ca parle de la section "log global" mais cela n'a rien changé..

~# docker exec haproxy /docker-certinstall.sh mon/domaine.fr
[WARNING] 132/203245 (14) : config : log format ignored for frontend 'ssl_redirector' since it has no log address.
[WARNING] 132/203245 (14) : config : log format ignored for frontend 'http_redirect' since it has no log address.

(l'option  --staging devra être enlevé qu'au succès de cette dernière demande non ?)

Modifié par nasmanu

Partager ce message


Lien à poster
Partager sur d’autres sites

En pratique, il y a plusieurs soucis/bugs dans mon Dockerfile, par exemple les logs, mais aussi l'installation de acme.sh (curl+chmod), le fait de devoir relancer haproxy à chaque changement de certificat ... c'est une première version faite à l'arrache ... mais écrite de manière à être facilement corrigeable (TOUT est dans le Dockerfile)

  • Pour les dossiers c'est normal, je ne peux pas savoir comment est organisé ton nas, mais tu peux changer le chemin si besoin
  • Le warning est lié aux réglages d'haproxy, il dit juste que le format des logs est ignoré car je les ai désactivés => tu as la réponse dans le lien que tu as posté => c'est normal (pas propre mais normal)
    • =>Tu as tout le loisir de modifier la conf d'haproxy en éditant le fichier user.cfg, c'est fait pour
  • Enfin pour le --staging, ça permet de tester, donc c'est à enlever une fois les tests concluants, si le message dans la console n’empêche pas le fonctionnement d'haproxy, que le certificat généré en staging est correcte (bon nom de domaine, bien installé, ...) et que tout le reste fonctionne, alors tu peux modifier le Dockerfile pour recréer l'image et le conteneur (pense aussi à supprimer le contenu des dossiers cert, conf et ssl).

ps : je pensais que tu étais plus à l'aise avec LE, haproxy et docker :confused:

Partager ce message


Lien à poster
Partager sur d’autres sites

ok  je vais m'y pencher plus, j'avais testé plusieurs conf pour Haproxy mais sans succès pour le moment.

Concernant LE et Docker c'est la première fois que je m'en sert :)

En tout cas, un grand merci pour toute ton aide, je vous tiens au courant pour la suite et le but aussi serait de faire un jolie tuto pour tout le monde si cela fonctionne bien :)

Partager ce message


Lien à poster
Partager sur d’autres sites

v0.5.0

Changements :

  • syslog en variable d'environnement
  • export de tout le dossier /etc/haproxy
  • renommage des scripts
  • corrections de bugs

Pour rappel et pour ceux qui commenceraient par ce post, il s'agit d'un Dockerfile permettant d'installer haproxy et de créer des certificats LetsEncrypt.

Les dossiers d'haproxy et de LetsEncrypt sont exposés afin de pouvoir modifier directement la configuration d'haproxy ou de réutiliser ailleurs les certificats générés.

=>vous devez ajuster la configuration d'haproxy (par défaut dans le fichier /volume1/docker/acme-haproxy/haproxy/haproxy.cfg) selon vos besoins !

  1. Création des dossiers permettant d'accueillir les volumes (à adapter selon vos besoins)  :
    1. dossier de configuration d'haproxy : /volume1/docker/acme-haproxy/haproxy
    2. dossier des certificats letsencrypt : /volume1/docker/acme-haproxy/letsencrypt
  2. Création de l'image : docker build -t acme-haproxy /chemin/vers/le/dockerfile/
  3. Lancement du conteneur : docker run -d --restart always --name haproxy -e SYSLOG=127.0.0.1:514 -p 80:80 -p 443:443 -v /volume1/docker/acme-haproxy/letsencrypt:/root/.acme.sh -v /volume1/docker/acme-haproxy/haproxy:/etc/haproxy acme-haproxy
    • par défaut les ports utilisés sont : 80 et 443
    • la variable d'environnement facultative SYSLOG permet de définir un serveur de logs, par exemple : -e SYSLOG=adresse.ip.du.nas:514
  4. Création d'un certificat : docker exec haproxy /docker-certissue -d www.domaine.fr
    • il est possible de préciser plusieurs SAN avec plusieurs -d, par exemple : -d www.domaine.fr -d mail.domaine.fr -d domaine.fr
  5. Renouvellement de tous les certificats LE : docker exec haproxy /docker-certrenew
    • à mettre en crontab sur le syno
  6. Installation d'un certificat dans haproxy : docker exec haproxy /docker-certinstall www.domaine.fr
    • à lancer pour chaque certificat s'il y en a plusieurs (c'est le nom du dossier /volume1/docker/acme-haproxy/letsencrypt/<nom de domaine> qui sert de clef)
    • à mettre en crontab sur le syno juste après le renouvellement
  7. Appliquer un changement de configuration : docker exec haproxy /docker-restart

Les étapes 4, 5, 6 et 7 sont indépendantes pour permettre plus de flexibilité (par exemple pour gérer des certificats qui ne seront pas utilisés dans haproxy), mais peuvent être regroupées si besoin.

Pour tester, j'ai laissé les options --staging (ça créé des certificats non valides mais qui ne comptent pas dans le quota hebdomadaire de LE), --debug et --force => ces options sont à retirer avant mise en production (donc après avoir bien tout testé)

# fenrir/acme-haproxy
# HAproxy and LetsEncrypt
# TODO :zero downtime
# TODO :staging as ENV
# TODO :scripts in PATH
# TODO :...
#
# VERSION 0.5.0
#
FROM debian:stretch-slim
MAINTAINER Fenrir <dont@want.spam>

ENV	DEBIAN_FRONTEND noninteractive
ENV SYSLOG 127.0.0.1:514

# Configure APT and install packages
RUN	echo 'APT::Install-Suggests "false";' > /etc/apt/apt.conf &&\
	echo 'APT::Install-Recommends "false";' >> /etc/apt/apt.conf &&\
	echo 'Aptitude::Recommends-Important "false";' >> /etc/apt/apt.conf &&\
	echo 'Aptitude::Suggests-Important "false";' >> /etc/apt/apt.conf &&\
	apt-get update &&\
	apt-get -y dist-upgrade &&\
	apt-get -y install \
	ca-certificates \
	curl \
	haproxy \
	netcat &&\
	apt-get autoclean && apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb /tmp/* /var/tmp/*

# Configure docker
RUN	mv /etc/haproxy /etc/haproxy.dist &&\
	mkdir -p /run/haproxy &&\
	mkdir -p /root/.acme.sh &&\
# Create entrypoint
	echo "#!/bin/bash" > /docker-entrypoint &&\
# Create haproxy.cfg
	echo "if [ ! -f /etc/haproxy/haproxy.cfg ]; then" >> /docker-entrypoint &&\
	echo "	mkdir -p /etc/haproxy/ssl" >> /docker-entrypoint &&\
	echo "	cp -r /etc/haproxy.dist/* /etc/haproxy/." >> /docker-entrypoint &&\
	echo "	sed -i '3 d' /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	sed -i '2 d' /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	sed -i '2ilog $SYSLOG local1' /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	sed -i '20itune.ssl.default-dh-param 2048' /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo 'frontend ssl_redirector' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	bind *:443 ssl crt /etc/haproxy/ssl/' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	http-request del-header X-Forwarded-Proto' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	http-request set-header X-Forwarded-Proto https if { ssl_fc }' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	acl letsencrypt-request path_beg -i /.well-known/acme-challenge/' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	use_backend letsencrypt_backend if letsencrypt-request' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	default_backend website_backend' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo 'frontend http_redirect' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	bind *:80' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	acl letsencrypt-request path_beg -i /.well-known/acme-challenge/' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	redirect scheme https code 302 if !letsencrypt-request' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	use_backend letsencrypt_backend if letsencrypt-request' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo 'backend letsencrypt_backend' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	server letsencrypt 127.0.0.1:11444' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo 'backend website_backend' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "	echo '	server server01 127.0.0.1:11080' >> /etc/haproxy/haproxy.cfg" >> /docker-entrypoint &&\
	echo "fi" >> /docker-entrypoint &&\
# Create temp cert file
	echo "if [ ! -f /etc/haproxy/ssl/temp.pem ]; then" >> /docker-entrypoint &&\
	echo "	openssl req -subj '/CN=temp/O=ora/C=RY' -new -newkey rsa:2048 -sha256 -days 100 -nodes -x509 -keyout /tmp/temp.key -out /tmp/temp.crt" >> /docker-entrypoint &&\
	echo "	cat /tmp/temp.key /tmp/temp.crt > /etc/haproxy/ssl/temp.pem" >> /docker-entrypoint &&\
	echo "fi" >> /docker-entrypoint &&\
# Install acme.sh
	echo "if [ ! -f /root/.acme.sh/acme.sh ]; then" >> /docker-entrypoint &&\
	echo "	curl -o /root/.acme.sh/acme.sh https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh" >> /docker-entrypoint &&\
	echo "	chmod +x /root/.acme.sh/acme.sh" >> /docker-entrypoint &&\
	echo "fi" >> /docker-entrypoint &&\
	echo "/usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid &" >> /docker-entrypoint &&\
	echo "sleep infinity" >> /docker-entrypoint &&\
	chmod +x /docker-entrypoint &&\

# Certificate issue
	echo "#!/bin/bash" > /docker-certissue &&\
	echo '/root/.acme.sh/acme.sh --issue --staging --standalone --httpport 11444 --force --debug $@' >> /docker-certissue &&\
	chmod +x /docker-certissue &&\

# Certificate renew
	echo "#!/bin/bash" > /docker-certrenew &&\
	echo "/root/.acme.sh/acme.sh --renew-all --staging --standalone --httpport 11444 --force --debug" >> /docker-certrenew &&\
	chmod +x /docker-certrenew &&\

# Certificate install
	echo "#!/bin/bash" > /docker-certinstall &&\
	echo 'DOMAIN=$1' >> /docker-certinstall &&\
	echo 'ACMESTORE="/root/.acme.sh"' >> /docker-certinstall &&\
	echo 'HAPROXYSTORE="/etc/haproxy/ssl"' >> /docker-certinstall &&\
	echo 'if [ -f $ACMESTORE/$DOMAIN/$DOMAIN.cer ]; then' >> /docker-certinstall &&\
	echo '	cat $ACMESTORE/$DOMAIN/$DOMAIN.key $ACMESTORE/$DOMAIN/$DOMAIN.cer $ACMESTORE/$DOMAIN/ca.cer > $HAPROXYSTORE/$DOMAIN.pem' >> /docker-certinstall &&\
	echo "fi" >> /docker-certinstall &&\
	echo 'haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -sf $(cat /run/haproxy.pid) &' >> /docker-certinstall &&\
	chmod +x /docker-certinstall &&\

# Restart haproxy
	echo "#!/bin/bash" > /docker-restart &&\
	echo 'haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -sf $(cat /run/haproxy.pid) &' >> /docker-restart &&\
	chmod +x /docker-restart &&\
	echo "end"

EXPOSE 80/tcp 443/tcp
	
VOLUME ["/root/.acme.sh", "/etc/haproxy"]

ENTRYPOINT	["/docker-entrypoint"]
# ENTRYPOINT	["/bin/bash"]

 

Modifié par Fenrir

Partager ce message


Lien à poster
Partager sur d’autres sites

whouaa, merci, je venais juste de comprendre mon erreur pour haproxy, je modifiais le fichier /etc/haproxy/usr.cfg et non pas celui dans /volume1/docker/acme-haproxy/haproxy/

merci, je vais repartir de zéro avec cette version, je tiens au courant

Partager ce message


Lien à poster
Partager sur d’autres sites

Je n'ai plus ma précédente erreur mais le certificat ne veut pas se créer au point 4.

je ne vois pourtant pas de différence avec ton ancienne version mais on dirait un soucis de syntaxe, tout se déroule bien jusqu’à là :

[Sun May 14 15:28:02 UTC 2017] Diagnosis versions:
openssl:openssl
OpenSSL 1.1.0e  16 Feb 2017
apache:
apache doesn't exists.
nc:
[v1.10-41+b1]
connect to somewhere:   nc [-options] hostname port[s] [ports] ...
listen for inbound:     nc -l -p port [-options] [hostname] [port]
options:
        -c shell commands       as `-e'; use /bin/sh to exec [dangerous!!]
        -e filename             program to exec after connect [dangerous!!]
        -b                      allow broadcasts
        -g gateway              source-routing hop point[s], up to 8
        -G num                  source-routing pointer: 4, 8, 12, ...
        -h                      this cruft
        -i secs                 delay interval for lines sent, ports scanned
        -k                      set keepalive option on socket
        -l                      listen mode, for inbound connects
        -n                      numeric-only IP addresses, no DNS
        -o file                 hex dump of traffic
        -p port                 local port number
        -r                      randomize local and remote ports
        -q secs                 quit after EOF on stdin and delay of secs
        -s addr                 local source address
        -T tos                  set Type Of Service
        -t                      answer TELNET negotiation
        -u                      UDP mode
        -v                      verbose [use twice to be more verbose]
        -w secs                 timeout for connects and final net reads
        -C                      Send CRLF as line-ending
        -z                      zero-I/O mode [used for scanning]
port numbers can be individual or ranges: lo-hi [inclusive];
hyphens in port names must be backslash escaped (e.g. 'ftp\-data').

 

donc la création de mon.domaine.fr.pem ne se fait pas.

une idée ?

Modifié par nasmanu

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a 14 minutes, nasmanu a dit :

apache doesn't exists.

le message n'est pas tout à fait vrai (ce n'est pas un apache), mais cette erreur indique que depuis Internet, ton haproxy n'est pas accessible

Partager ce message


Lien à poster
Partager sur d’autres sites

ok it's good, j'avais fait une bête erreur :D

Tout ce que tu as fait fonctionne a merveille, bien joué et merci beaucoup.

Maintenant il faut que je revois mes règles d'Haproxy car les anciennes ne fonctionnent plus depuis le Docker

Partager ce message


Lien à poster
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !


Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.


Connectez-vous maintenant