====== Loomio derrière un reverse proxy ======
===== Pré-requis =====
* Pour l'installation de **Loomio** / **Framavox**, suivre la documentation rédigée avec soins par Framasoft sur le [[http://framacloud.org/cultiver-son-jardin/installation-de-loomio/| Framacloud]].
* Pour la création des certificats, le client officiel ayant pas mal bougé ces derniers temps, nous vous conseillons de passer par le site officiel [[https://letsencrypt.org/]]. Le tuto [[public:avec_un_peu_d_huile_de_cloud|Avec un peu d huile de cloud]] sera également mis à jour prochainement concernant la création des certificats.
* Deux certificats ont été créés : un pour loomio.example.com et un pour faye.loomio.example.com, et chaque vhost a une configuration séparée dans le reverse proxy (cf. plus bas)
===== Pourquoi ce tuto =====
L'utilisation d'un reverse proxy n'est pas en soit une configuration //exotique//, c'est quelque chose de très pratiqué et qui en général ne pose que très peu voire aucun problème. \\
Sauf que dans le cas de Loomio, par défaut amené avec l'excellent Let'sEncrypt, cela donne du fil à retordre ! \\
Quel étrange casse-tête... Après des jours à essayer de faire marcher Loomio en reverse proxy, avec des erreurs d'upstream dans les logs nginx du conteneur et ceux du reverse proxy ; un, deux certificats ; un, deux, trois, quatre virtualhosts dans la conf du reverse Nginx, des problèmes de contenu mixed (lorsque le navigateur Web détecte des flux HTTP sur une connexion HTTPS)...
A force de tests, d'échanges (merci à Minus - https://www.debian-fr.org/t/loomio-derriere-un-reverseproxy/70055/6) et un peu aussi d'acharnement, nous sommes finalement arrivé (un peu par hasard !) à faire fonctionner Loomio derrière un reverse proxy Nginx, sans HTTPS côté Loomio, sans warning de contenu mixed sur HTTPS et avec mise à jour dynamique du contenu sans aucun rechargement.
...et toujours des alertes sur l'upstream du NGINX Loomio ! Les erreurs semblent en lien avec le conteneur //Worker//, mais finalement sans grande gravité.
Au final la configuration détaillée ci-dessous tourne avec un reverse proxy Nginx écoutant en 443 et redirigeant vers le port 80 du Nginx Loomio, c'est merveilleux :joy:
===== Schéma de l'installation =====
| |!@4| |
| AAA |AAA=**Reverse-proxy Nginx** \\ écoute en HTTPS \\ Upstream redirige vers \\ CoreOs HTTP port 8001
| |!@4| |
| BBB |BBB=**CoreOs** \\ écoute sur le port 8001 \\ Redirection gérée par Docker \\ vers conteneur Nginx en HTTP (port 80)
| |:| |
| |L|~@2| CCC |CCC=**Docker-compose avec Loomio**
| | | |!| |
| | | |)|~| DDD |DDD=loomiodeploy_nginx_1
| | | |!| |
| | | |)|~| DDD |DDD=loomiodeploy_mailin_1
| | | |!| |
| | | |)|~| DDD |DDD=loomiodeploy_loomio_1
| | | |!| |
| | | |)|~| DDD |DDD=loomiodeploy_worker_1
| | | |!| |
| | | |)|~| DDD |DDD=loomiodeploy_db_1
| | | |!| |
| | | |`|~| DDD |DDD=loomiodeploy_faye_1
===== Configuration Docker-compose =====
On enlève tout ce qui se rapport à Let'sEncrypt, la partie HTTPS est à la seule charge du reverse proxy. On indique également de ne mapper que le port 8001 vers le port 80 pour Nginx :
#letsencrypt:
# image: jrcs/letsencrypt-nginx-proxy-companion
# volumes:
# - /var/run/docker.sock:/var/run/docker.sock:ro
# - ./certificates:/etc/nginx/certs:rw
# volumes_from:
# - nginx
nginx:
image: jwilder/nginx-proxy
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx/vhost.d:/etc/nginx/vhost.d
- ./nginx/html:/usr/share/nginx/html
ports:
- 8001:80
links:
- loomio
- faye
loomio:
image: loomio/loomio
expose:
- 3000
env_file: ./env
links:
- db
environment:
- DATABASE_URL=postgresql://postgres:password@db/loomio_production
volumes:
- ./attachments:/loomio/public/system/
worker:
image: loomio/loomio
env_file: ./env
links:
- db:db
environment:
- DATABASE_URL=postgresql://postgres:password@db/loomio_production
volumes:
- ./attachments:/loomio/public/system/attachments
command: "bundle exec rake jobs:work"
db:
image: postgres
volumes:
- ./pgdata:/pgdata
environment:
- POSTGRES_PASSWORD=password
- PGDATA=/pgdata
mailin:
image: loomio/mailin-docker
ports:
- 25:25
links:
- loomio
environment:
- WEBHOOK_URL=http://loomio.example.com/email_processor/
faye:
build: faye/.
env_file: ./faye_env
Pour les fichiers **env** et **faye_env** :
# this is the hostname of your app used by loomio
CANONICAL_HOST=loomio.example.com
# this is to tell nginx that you want requests for this hostname to come to the app
VIRTUAL_HOST=loomio.example.com
# this is to configure letsencrypt to automatically issue and renew your hostname
#LETSENCRYPT_HOST=loomio.example.com
#LETSENCRYPT_EMAIL=hostmaster@example.com
# the number of dots in your hostname
TLD_LENGTH=2
# smtp settings
SUPPORT_EMAIL=postmaster@example.com
SMTP_DOMAIN=loomio.example.com
SMTP_SERVER=mail.example.com
SMTP_PORT=25
#SMTP_USERNAME=smtpusername
#SMTP_PASSWORD=smtppassword
FAYE_URL=https://faye.loomio.nomagic.fr/faye
REPLY_HOSTNAME=loomio.example.com
# helper bot is the account which welcomes people to their groups.
HELPER_BOT_EMAIL=no-reply@loomio.example.com
RAILS_ENV=production
FORCE_SSL=1
DEVISE_SECRET=monDeviseSecret
SECRET_COOKIE_TOKEN=monSecretCookieToken
PRIVATE_PUB_SECRET_TOKEN=monSecretToken
# this is to tell nginx that you want requests for this hostname to come to the app
VIRTUAL_HOST=faye.loomio.example.com
# this is to configure letsencrypt to automatically issue and renew your hostname
#LETSENCRYPT_HOST=faye.loomio.example.com
#LETSENCRYPT_EMAIL=hostmaster@example.com
PRIVATE_PUB_SECRET_TOKEN=monPrivatePubScretToken
Démarrer / redémarrer les conteneurs :
$ docker-compose down
Stopping loomiodeploy_nginx_1 ... done
Stopping loomiodeploy_mailin_1 ... done
Stopping loomiodeploy_loomio_1 ... done
Stopping loomiodeploy_worker_1 ... done
Stopping loomiodeploy_db_1 ... done
Stopping loomiodeploy_faye_1 ... done
Removing loomiodeploy_nginx_1 ... done
Removing loomiodeploy_mailin_1 ... done
Removing loomiodeploy_loomio_1 ... done
Removing loomiodeploy_worker_1 ... done
Removing loomiodeploy_db_1 ... done
Removing loomiodeploy_faye_1 ... done
$ docker-compose up -d
Creating loomiodeploy_faye_1
Creating loomiodeploy_db_1
Creating loomiodeploy_worker_1
Creating loomiodeploy_loomio_1
Creating loomiodeploy_mailin_1
Creating loomiodeploy_nginx_1
Et on contrôle les logs :
docker-compose logs
===== Reverse proxy Nginx =====
Côté reverse proxy, on ne déclare que la partie HTTPS. On a créé deux certificats : un pour //loomio.example.com// et un autre pour //faye.loomio.example.com//. On a utilisé Let'Encrypt pour générer les certificats. \\
On déclare 2 hôtes virtuels :
## loomio ##############################################
upstream coreos-loomio {
keepalive 100;
server coreos.example.com:8001;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name
loomio.example.com
;
# SSL specifique
ssl_certificate /etc/letsencrypt/certs/loomio_ca.crt;
ssl_certificate_key /etc/letsencrypt/private/loomio.key;
## HTTPS config
ssl_session_timeout 10m;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
## Send header to tell the browser to prefer https to http traffic
add_header Strict-Transport-Security max-age=31536000;
# Logging
access_log /var/log/nginx/loomio_access.log;
access_log /var/log/nginx/loomio_upstream.log upstreamlog;
error_log /var/log/nginx/loomio_error.log;
location / {
# mêmes paramètres pour tout le monde
include conf.d/proxy.ini;
# le reste du chemin est en HTTP dans le LAN
# cf conf.d/upstream.ini
proxy_pass http://coreos-loomio;
## assure de garder le keepalive actif
proxy_set_header Connection "";
proxy_read_timeout 300;
proxy_connect_timeout 300;
}
}
## faye ################################################
upstream coreos-loomio-faye {
keepalive 100;
server server coreos.example.com:8001;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name
faye.loomio.example.com
;
# SSL specifique
ssl_certificate /etc/letsencrypt/certs/faye.loomio_ca.crt;
ssl_certificate_key /etc/letsencrypt/private/faye.loomio.key;
## HTTPS config
ssl_session_timeout 10m;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
## Send header to tell the browser to prefer https to http traffic
add_header Strict-Transport-Security max-age=31536000;
# Logging
access_log /var/log/nginx/loomio-faye_access.log;
access_log /var/log/nginx/loomio-faye_upstream.log upstreamlog;
error_log /var/log/nginx/loomio-faye_error.log;
location / {
# mêmes paramètres pour tout le monde
include conf.d/proxy.ini;
# le reste du chemin est en HTTP dans le LAN
proxy_pass http://coreos-loomio-faye;
## assure de garder le keepalive actif
proxy_set_header Connection "";
proxy_read_timeout 300;
proxy_connect_timeout 300;
}
}
Dans notre exemple on utilise un fichier commun pour les paramètres du proxy :
# Proxy config
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_http_version 1.1;
proxy_next_upstream off;
On test puis redémarre notre reverse-proxy :
# service nginx configtest
Testing nginx configuration:.
# service nginx restart
On se met en écoute sur les logs des hôtes virtuels :
# tail /var/log/nginx/loomio*error.log -f
==> /var/log/nginx/loomio_error.log <==
==> /var/log/nginx/loomio-faye_error.log <==
===== Cadeau bonux =====
Pendant les longues heures passées à chercher ce qui n'allait pas, nous avons glané quelques infos pratiques sur Loomio, on les rassemble ici :
=== Accéder à l'interface d'administration du site ===
Sur l'hôte hébergeant Loomio :
* Rentrer dans le conteneur **db**
docker exec -i -t loomiodeploy_db_1 /bin/bash
* Se connecter à la base de données
psql -dloomio_production -Upostgres -W
=> mot de passe par défaut = **password**
* Afficher la liste des utilisateurs
select id, email, is_admin from users;
* Rendre un utilisateur administrateur
update users set is_admin=true where email='myemail@example.com';
=> veiller à ce cet utilisateur soit le seul à posséder cet email (je pense que loomio bloque la création de 2 utilisateurs ayant le même courriel, mais je n'ai pas vérifié).
Vous pouvez maintenant accéder à l'interface d'administration sur https://loomio.example.com/admin, en faisant attention à ne rien casser (!)
=== Changer le mot de passe PostGreSQL ===
Si ça vous gêne d'avoir un mot de passe **password**, indépendamment du fait que la base n'est pas accessible directement depuis l'extérieur, voilà comment procéder :
Sur l'hôte hébergeant Loomio :
* Rentrer dans le conteneur **db**
docker exec -i -t loomiodeploy_db_1 /bin/bash
* Se connecter à la base de données
psql -dpostgres -Upostgres -W
postgres=# \password postgres
(affiché dans la console postgresql) Enter new password:
(affiché dans la console postgresql) Enter it again:
* Déconnectez-vous (''Ctrl-d''), tester de vous reconnecter avec le nouveau mot de passe.
* Sortir du conteneur pour revenir sur l'hôte (''exit'')
* Modifier le fichier **docker-compose.yml** en reportant le changement de mot de passe
* Démarrer / redémarrer les conteneurs :
$ docker-compose down
Stopping loomiodeploy_nginx_1 ... done
Stopping loomiodeploy_mailin_1 ... done
Stopping loomiodeploy_loomio_1 ... done
Stopping loomiodeploy_worker_1 ... done
Stopping loomiodeploy_db_1 ... done
Stopping loomiodeploy_faye_1 ... done
Removing loomiodeploy_nginx_1 ... done
Removing loomiodeploy_mailin_1 ... done
Removing loomiodeploy_loomio_1 ... done
Removing loomiodeploy_worker_1 ... done
Removing loomiodeploy_db_1 ... done
Removing loomiodeploy_faye_1 ... done
$ docker-compose up -d
Creating loomiodeploy_faye_1
Creating loomiodeploy_db_1
Creating loomiodeploy_worker_1
Creating loomiodeploy_loomio_1
Creating loomiodeploy_mailin_1
Creating loomiodeploy_nginx_1
* Et on contrôle les logs :
docker-compose logs
===== Liens =====
Pour tester l'application ou procéder à son installation, c'est par là !
* https://framavox.org/
* http://framacloud.org/cultiver-son-jardin/installation-de-loomio/