Mailu installation complète en docker derrière un reverse proxy (nginx)

Suivi en détail de l’installation sur un serveur du service mail et des interfaces web d’administration et de webmail.

Et comme un beau dessin vaut mieux qu’un long discours, voici l’infrastructure expliquée.

Mailu Deployment Diagram – edit

Ma configuration server:

  • server example.com
    • service nginx (443 + 80) avec les certificats letsencrypt sur le domaine
      • multiples web configurations
    • docker
      • mariadb
      • mailu docker compose
        • mailu_nginx
        • mailu_imap
        • mailu_smtp
        • mailu_…

Pré-requis

Avant toute chose, nous avons besoin de préparer quelques données.

  • Hostname: example.com

DB:

  • host: IP à récupérer après la création
  • nom de la base de donnée: mailu
  • nom de l’utilisateur: mailu
  • mot de passe de l’utilisateur: mailu_db_password (il faudra être créatif ici)
  • nom du réseau pour la db: mariadb_internal

Le répertoire d’installation de mailu: /opt/mailu

Je vais considérer que la machine hôte est une debian 10 pour plus de facilités mais ça marchera pour tout système qui fonctionne avec des .deb (ubuntu …)

Sur la machine hôte il faut aussi installer docker et docker-compose (voir référence en bas) et enfin il faut ouvrir les ports, comme certaine machine sont protégée par la société qui s’occupe du hosting et d’autres le sont avec iptable en interne

MariaDB

Tout d’abord créer la docker mariadb, la base de données, les utilisateurs et récupérer l’adresse ip.

Mais avant tout créons le réseau avec lequel sera connecté la base de donnée

sudo docker network create mariadb_internalCode language: Bash (bash)

Maintenant nous pouvons créer la docker mariadb

sudo docker run --net mariadb_internal --name mariadb -e MARIADB_ROOT_PASSWORD=******** -d mariadb:latestCode language: Bash (bash)

Remplacer les * par le mot de passe root et ensuite on test l’installation

docker run -it --network mariadb_internal --rm mariadb mysql -hmariadb -uroot -pCode language: Bash (bash)

Vous devriez arriver dans un terminal mysql

On va en profiter pour créer la base de donnée et un utilisateur qui a les droits complet sur cette base de donnée.

CREATE DATABASE mailu;
CREATE USER 'mailu'@'%' IDENTIFIED BY '************';
GRANT ALL PRIVILEGES ON mailu.* TO 'mailu'@'%';
FLUSH PRIVILEGES;
Code language: SQL (Structured Query Language) (sql)

Et ensuite récupérer l’adresse ip de la docker, plusieurs possibilités la plus facile est d’examiner la docker.

sudo docker inspect mariadb | grep IPAddressCode language: Bash (bash)

Ici je récupère l’adresse 172.19.0.5 que je vais utiliser dans la suite de ce document.

Mailu

La configuration par défaut est d’avoir le serveur nginx de mailu qui adresse l’ensemble des requêtes et s’occupe du chiffrement avec les certificats SSL récupérés sur let’s encrypt.

Comme il y a déjà un serveur nginx en front il va falloir faire des aménagements.

La documentation de mailru docker compose est assez claire. Je vais donc reprendre à partir de là et expliquer les changements.

Tout d’abord suivre le wizard pour créer les fichiers de configuration:

  • docker-compose.yml
  • mailu.env

Le plus simple est de les récupérer via wget:

cd /opt/
mkdir mailu
wget https://setup.mailu.io/1.8/file/<<some unique uuid>>/docker-compose.yml
wget https://setup.mailu.io/1.8/file/<<some unique uuid>>/mailu.env
Code language: Bash (bash)

Dans le fichier mailu.env les aménagements sont les suivants:

Ajouter la liste des domaines qui seront utilisés pour créer les certificats letsencrypt et qui assurerons la couche sécurisée dans les échanges imap et smtp

# Hostnames for this server, separated with comas
HOSTNAMES=<strong>smtp.example.com,mail.example.com</strong>
Code language: Bash (bash)

Bien entendu sélectionner mail-letsencrypt comme système de certification pour TLS

# Choose how secure connections will behave (value: letsencrypt, cert, notls, mail, mail-letsencrypt)
TLS_FLAVOR=mail-letsencryptCode language: Bash (bash)

Configurer le compte par défaut

INITIAL_ADMIN_ACCOUNT=admin
INITIAL_ADMIN_DOMAIN=example.com
INITIAL_ADMIN_PW=thisismypasswordinclear:-)

Configurer les accès DB pour l’ensemble des dockers et pour roundcube si vous installez le webmail roundcude

###################################
# Database settings
###################################
DB_FLAVOR=mysql
DB_USER=mailu
DB_PW=mailu_db_password
DB_HOST=<strong>172.19.0.5</strong>
DB_NAME=mailu
ROUNDCUBE_DB_USER=mailu
ROUNDCUBE_DB_PW=mailu_db_password
ROUNDCUBE_DB_NAME=mailu
Code language: Bash (bash)

Dans le fichier docker-compose.yml adapter les ports (enlever 443 qui ne sert à rien ici vu que le HTTPS est géré par l’auter nginx et mapper le 8081 –> 80 ça nous permettra de créer l’entrée dans le nginx de l’hôte)

    ports:
      - "::1:8081:80"
      - "10.52.16.225:25:25"
      - "::1:25:25"
      - "10.52.16.225:465:465"
      - "::1:465:465"
      - "10.52.16.225:587:587"
      - "::1:587:587"
      - "10.52.16.225:110:110"
      - "::1:110:110"
      - "10.52.16.225:995:995"
      - "::1:995:995"
      - "10.52.16.225:143:143"
      - "::1:143:143"
      - "10.52.16.225:993:993"
      - "::1:993:993" 

Code language: YAML (yaml)

Vous voyez ici la convention ipv6 utilisée: ::1… on en aura besoin dans le port forwarding dans le nginx de l’hôte.

Ensuite on va créer le lien entre le réseau de mailu et le réseau mariadb.

networks:
  default:
    driver: bridge
    ipam:
       driver: default
       config:
       - subnet: 192.168.203.0/24
  mariadb-internal-network:
    external:
      name: mariadb_internal
Code language: YAML (yaml)

Enfin on donne accès aux deux serveurs web au réseau mariadb

  admin:
    image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-1.8}
    restart: always
    env_file: mailu.env
    volumes:
      - "/mailu/data:/data"
      - "/mailu/dkim:/dkim"
    depends_on:
      - redis
    networks:
      - default
      - mariadb-internal-network

Code language: YAML (yaml)
  webmail:
    image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}roundcube:${MAILU_VERSION:-1.8}
    restart: always
    env_file: mailu.env
    volumes:
      - "/mailu/webmail:/data"
    depends_on:
      - imap
    networks:
      - default
      - mariadb-internal-network

Code language: YAML (yaml)

Maintenant on teste le tout

sudo docker-compose upCode language: Bash (bash)

Et si c’est bon on peut l’installer en tant que service

Installation du service docker compose mailu

Création du fichier décrivant le service

sudo vim /lib/systemd/system/docker-compose-mailu.service

On précise que ce service se lance après le docker service, on précise le répertoire de travail et le chemin absolu de docker-compose

# Mailu docker images for webmail & mail admin
[Unit]
Description=Docker Compose Mailu Service
Requires=docker.service
After=docker.service
 
[Service]
WorkingDirectory=/opt/mailu
ExecStart=/usr/bin/docker-compose up
ExecStop=/usr/bin/docker-compose down
TimeoutStartSec=0
Restart=on-failure
StartLimitIntervalSec=60
StartLimitBurst=3
 
[Install]
WantedBy=multi-user.target
Code language: Bash (bash)

Ensuite on rajoute ce service au service démarré par le système et on le démarre une première fois

sudo systemctl enable docker-compose-mailu.service 
sudo systemctl start docker-compose-mailu.serviceCode language: Bash (bash)

Nginx du serveur hôte

Dernière étape configurer le serveur nginx de l’hôte pour laisser passer le webmail et l’admin mail ainsi que les sous-domaines smtp et mail vers le mailu_nginx.

Dans le fichier de domaine site-enabled/mywebsite créer un upstream pour le mailu_nginx

upstream mailu {
  server [::]:8081 weight=100 max_fails=5 fail_timeout=5;
}

Code language: Nginx (nginx)

Ensuite configurer le pass sur le domaine principal

server {
	listen 443 ssl; # managed by Certbot
	listen [::]:443 ssl; # managed by Certbot

	listen 80;
	listen [::]:80;
        
	ssl on;

	server_name example.com www.example.com;
...
	location /webmail {
		proxy_set_header X-Forwarded-Host $host;
		proxy_set_header X-Forwarded-Server $host;
		proxy_pass http://mailu/webmail;
		sub_filter '"http://mailu/webmail'  '"/';
		sub_filter_once off;
	}

	location /admin {
		proxy_set_header X-Forwarded-Host $host;
		proxy_set_header X-Forwarded-Server $host;
		proxy_pass http://mailu/admin;
		sub_filter '"http://mailu/admin'  '"/';
		sub_filter_once off;
	}

...
}

Code language: Nginx (nginx)

Et finalement configurer le pass sur les sous-domaines smtp et mail

server {
	listen 80;
	listen [::]:80;
	
	server_name mail.example.com;
	server_name smtp.example.com;
	
	access_log /var/log/nginx/mail.sbw.be.access.log; 
	error_log /var/log/nginx/mail.sbw.be.error.log;

	location / {
		proxy_set_header X-Forwarded-Host $host;
		proxy_set_header X-Forwarded-Server $host;
		proxy_pass http://mailu/;
		sub_filter '"http://mailu/'  '"/';
		sub_filter_once off;
	}
}

Code language: Nginx (nginx)

Et voilà!

Il ne reste plus qu’a tester et redémarrer nginx

sudo nginx -t && sudo systemctl restart nginxCode language: Bash (bash)

Références

  1. Mailu simple docker webserver
  2. Nginx webserver and reverse proxy
  3. Install docker
  4. Install docker compose
chevron_left
chevron_right

Leave a comment

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Comment
Name
Email
Website