Files
roundcube-vblog/README.md
T

108 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Roundcube Webmail en docker-compose
Stack Roundcube **1.7.4** prête à l'emploi : nginx + php-fpm + MariaDB, skin Elastic recompilé avec la charte vBlog.io (surcharges LESS dans `theme/`).
```
:8080 (127.0.0.1 par défaut, derrière un reverse proxy TLS)
│
┌─────────────▼─────────────┐ réseau frontend (sortie IMAP/SMTP)
│ nginx 1.30-alpine │ sert le statique depuis le volume www (ro)
└─────────────┬─────────────┘
│ FastCGI :9000
┌─────────────▼─────────────┐
│ roundcube (php-fpm 8.4) │ image locale = roundcube/roundcubemail:1.7.4-fpm-alpine
│ │ + skin Elastic recompilé + aspell + mailcap
└─────────────┬─────────────┘
│ réseau backend (internal: pas d'accès sortant)
┌─────────────▼─────────────┐
│ mariadb 11.8 (LTS) │
└───────────────────────────┘
```
![Login](docs/apercu-login.png)
## Démarrage
```sh
cp .env.example .env # renseigner mots de passe, RC_DES_KEY (24 car.), IMAP/SMTP
docker compose up -d --build
docker compose ps # les 3 services doivent passer "healthy"
```
Puis `http://127.0.0.1:8080/`. Le premier démarrage copie les sources dans le volume `www` et crée le schéma SQL (`bin/initdb.sh`), compter ~30 s.
## Arborescence
| Chemin | Rôle |
|---|---|
| `compose.yaml` | Les 3 services, volumes, réseaux, healthchecks |
| `.env.example` | Toutes les variables (versions, BDD, IMAP/SMTP, plugins...) |
| `roundcube/Dockerfile` | Build multi-étage : compilation LESS (node) puis image finale |
| `roundcube/zz-healthcheck.conf` | `ping.path` php-fpm pour le healthcheck |
| `nginx/templates/default.conf.template` | vhost, rendu par l'entrypoint nginx (envsubst `NGINX_*`) |
| `config/*.php` | Config Roundcube additionnelle, montée sur `/var/roundcube/config` |
| `theme/` | Surcharges du skin Elastic (`_variables.less`, `_styles.less`, `fonts/`, `images/`) |
| `scripts/sync-theme.sh` | Réimporte une customisation (défaut `../roundcube-custom/vblog`) |
## Choix techniques
- **Image officielle `fpm-alpine`** ([roundcube/roundcubemail-docker](https://github.com/roundcube/roundcubemail-docker)) : son entrypoint génère `config.docker.inc.php` depuis les `ROUNDCUBEMAIL_*`, inclut `/var/roundcube/config/*.php`, initialise/migre la base. Pas de réimplémentation.
- **Volume `www` partagé** (rw côté Roundcube, ro côté nginx) : pattern documenté upstream pour la variante FPM. À chaque démarrage, l'entrypoint resynchronise `/usr/src/roundcubemail` vers le volume (`bin/installto.sh`) : une image reconstruite (version ou thème) est donc propagée au simple `up -d`.
- **nginx** : depuis 1.7, seul `public_html/` est le docroot et les ressources sont appelées en `/static.php/<chemin>`. Le vhost les sert directement depuis le volume (préfixes et extensions alignés sur `ALLOWED_PATHS`/`SUPPORTED_TYPES` de `static.php`, cache 30 j, les URL portent `?s=<mtime>`). Seuls `index.php` et `static.php` atteignent PHP ; `installer.php` et le reste renvoient 404.
- **Thème compilé au build** : Elastic est livré en CSS minifié ; `_variables.less`/`_styles.less` ne sont pris en compte qu'à la compilation (`@import (optional)` dans `styles/variables.less` et `styles/styles.less`). Un étage `node:22-alpine` recompile `styles`, `print` et `embed` avec `lessc` (même commande que `skins/elastic/Makefile`). Aucune dépendance Node dans l'image finale.
- **Dictionnaires aspell et `mailcap` intégrés au build** plutôt qu'installés à chaque démarrage (`ROUNDCUBEMAIL_ASPELL_DICTS` fait un `apk add` au runtime). `mailcap` fournit `/etc/mime.types`, absent de l'image upstream (sinon warning « Mimetype to file extension mapping doesn't work properly »).
- **`des_key` imposée par `.env`** : sinon l'entrypoint la génère aléatoirement dans `config.inc.php`, perdue si le volume `www` est recréé.
- **Healthchecks** : MariaDB `healthcheck.sh --connect --innodb_initialized` ; Roundcube : port FPM 9000 ; nginx : `GET /fpm-ping` relayé à php-fpm (chaîne nginx → FPM validée, URL limitée à 127.0.0.1). Ordre de démarrage piloté par `depends_on: condition: service_healthy`.
- **Réseau `backend` en `internal: true`** : MariaDB n'a ni port publié ni accès sortant.
## Thème vBlog.io
Les fichiers de `theme/` et `config/20-vblog.inc.php` sont une copie de `roundcube-custom/vblog/`. Pour resynchroniser après modification :
```sh
sh scripts/sync-theme.sh [dossier_source]
docker compose up -d --build
```
Pour revenir à l'Elastic d'origine : vider `theme/`, supprimer `config/20-vblog.inc.php`, rebuild.
## Configuration
- **Variables** : voir `.env.example` (commentaires sur leur propre ligne : Compose peut intégrer un commentaire de fin de ligne à la valeur).
- **Options Roundcube** : déposer des `*.php` dans `config/` (inclus par ordre alphabétique), puis `docker compose restart roundcube`. Référence : `config/defaults.inc.php` dans le conteneur. `config/10-base.inc.php` fixe langue, `proxy_whitelist`, durée de session, rate-limit de login.
- **Plugins** : intégrés → `RC_PLUGINS` ; tiers → `RC_COMPOSER_PLUGINS` (installés par composer au démarrage, nécessite l'accès à packagist) + ajout dans `RC_PLUGINS`.
- **Taille des pièces jointes** : `UPLOAD_MAX_FILESIZE` applique la même limite à PHP et nginx. Le message encodé en base64 pèse ~1,37× la pièce jointe.
## Reverse proxy TLS
La stack écoute en HTTP sur `127.0.0.1:8080`. Le proxy frontal (Traefik, HAProxy, nginx...) doit transmettre `X-Forwarded-For` et `X-Forwarded-Proto: https`. Restreindre `proxy_whitelist` (`config/10-base.inc.php`) à l'IP du proxy en production. Si Roundcube est publié sous un sous-chemin, régler `ROUNDCUBEMAIL_REQUEST_PATH`.
## Exploitation
```sh
docker compose logs -f roundcube # logs Roundcube et php-fpm (log_driver = stdout)
# Sauvegarde : base + volume enigma si le plugin est utilisé
docker compose exec -T mariadb sh -c 'mariadb-dump -uroot -p"$MARIADB_ROOT_PASSWORD" --single-transaction "$MARIADB_DATABASE"' > roundcube-$(date +%F).sql
```
**Mise à jour Roundcube** : modifier `RC_VERSION` dans `.env` puis `docker compose up -d --build`. L'entrypoint exécute `installto.sh` puis `initdb.sh --update` (migrations SQL). Sauvegarder la base avant.
**Proxy TLS d'entreprise pendant le build** (npm, apk) : fournir sa CA en secret BuildKit, optionnel :
```sh
docker build -f roundcube/Dockerfile --secret id=ca,src=/chemin/ca.pem -t local/roundcube:1.7.4 .
docker compose up -d --no-build
```
## Validation effectuée
Stack construite et démarrée avec Docker 29.6 / Compose 5.3 : 3 services `healthy`, schéma SQL créé, login IMAP réussi contre un Dovecot 2.4.5 de test (utilisateur enregistré en base), charte vBlog appliquée (captures `docs/`), `installer.php` et `static.php/config/...` en 404, statique servi par nginx avec cache. Non testé dans l'environnement de validation (dépôt Alpine bloqué) : l'étape `apk add` des dictionnaires/mailcap, et l'envoi SMTP.
## Sources
- Image et entrypoint : https://github.com/roundcube/roundcubemail-docker et https://hub.docker.com/r/roundcube/roundcubemail
- Options de config : https://github.com/roundcube/roundcubemail/blob/master/config/defaults.inc.php
- Skin Elastic, points d'extension LESS : https://github.com/roundcube/roundcubemail/tree/master/skins/elastic
- Image nginx (templates envsubst) : https://hub.docker.com/_/nginx ; image MariaDB (`healthcheck.sh`) : https://hub.docker.com/_/mariadb