# Roundcube Webmail (Docker) Docker-based Roundcube Webmail stack with config baked into a custom image and secrets supplied via environment variables. Suitable for deployment behind a reverse proxy (e.g. Traefik) with a private container registry and CI/CD. ## Architecture - **Custom image**: Built from the official [Roundcube image](https://hub.docker.com/r/roundcube/roundcubemail). The Dockerfile copies this repo’s config files into the image; no config is mounted from the host at runtime. - **Secrets and per-deployment values**: All sensitive and site-specific settings (DB credentials, session key, IMAP/SMTP hosts, plugin DSNs, etc.) are read from environment variables at runtime. The image is safe to push to a registry. - **Stack**: - **webmail**: Roundcube (custom image). Connects to MariaDB for Roundcube DB and, if using the password plugin, to a separate DB (e.g. Postfix/mailbox) via a Unix socket. Enigma plugin uses a named volume for GPG keys. - **db**: MariaDB for Roundcube’s own database (user prefs, etc.). - **Networks**: Internal `backend` (webmail ↔ db) and external `traefik` for the reverse proxy. The compose file assumes Traefik and a `traefik` network already exist. ## Repository layout | Path | Purpose | | ---------------------- | ------------------------------------------------------------------------------------------------- | | `config/` | Main Roundcube config (`config.inc.php`, `config.smtp.inc.php`). Values are read from env in PHP. | | `plugins/enigma/` | Enigma (PGP) plugin config. | | `plugins/managesieve/` | Managesieve plugin config; host from env. | | `plugins/password/` | Password-change plugin config; DB DSN built from env. | | `docker-compose.yml` | Stack definition; webmail image points at the image produced by the build pipeline. | | `Dockerfile` | Extends official Roundcube image and copies the config files above. | | `.env.example` | Template for required and optional env vars (no secrets). | ## Environment variables Copy `.env.example` to `.env` and set values. Required for a working stack: - **Database (Roundcube)**: `DB_ROOT_PASSWORD`, `DB_PASSWORD`, `DB_NAME`, `DB_USER` (and thus `ROUNDCUBEMAIL_DB_*` used by the app). - **IMAP/SMTP**: `ROUNDCUBEMAIL_DEFAULT_HOST`, `ROUNDCUBEMAIL_DEFAULT_PORT`, `ROUNDCUBEMAIL_SMTP_SERVER`, `ROUNDCUBEMAIL_SMTP_PORT`. - **Session key**: `ROUNDCUBEMAIL_DES_KEY` — must be exactly 24 characters; used to encrypt stored IMAP passwords in the session. Optional / plugin-related: - `ROUNDCUBEMAIL_SUPPORT_URL`, `ROUNDCUBEMAIL_PLUGINS`, `ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE`. - **Managesieve**: `ROUNDCUBEMAIL_MANAGESIEVE_HOST` (e.g. `tls://mail.example.com:4190`). - **Password plugin**: `ROUNDCUBEMAIL_PASSWORD_DB_USER`, `ROUNDCUBEMAIL_PASSWORD_DB_PASSWORD`, `ROUNDCUBEMAIL_PASSWORD_DB_NAME` (DB used for mailbox password changes). - **Image tag**: `IMAGE_TAG` (default `latest`) to pin the webmail image. The webmail service expects the host’s MySQL socket at `/var/run/mysqld/mysqld.sock` for the password-plugin DB; adjust the volume mount if your socket path differs. ## Docker Compose and Traefik - **Image**: The `webmail` service uses a single image tag (e.g. `your-registry/your-org/mail-roundcube:latest`). Set the image name in `docker-compose.yml` to match the image built and pushed by your CI. - **Traefik labels**: The sample labels in `docker-compose.yml` are for TLS and host-based routing. Replace the `Host(...)` rules and any other host-specific labels with your own hostnames and middleware. - **Volumes**: `roundcube-keys` is used by the Enigma plugin and is marked `external: true`; create it (or adjust) before first deploy. `temp` is for Roundcube temp files. ## CI/CD (Woodpecker) Three pipelines: 1. **ci** — Lint and format (Prettier, yamllint). Runs on pull requests and pushes to the default branch. 2. **build** — Builds the Docker image and pushes it to your container registry. Depends on `ci`. Configure registry URL and repo name in the pipeline file and in `package.json` scripts if you use them locally. 3. **deploy** — Triggers a webhook (e.g. reverse-proxy or stack redeploy). Depends on `ci` and `build` so the new image is pushed before the webhook runs. Required secrets (in your CI): registry login, webhook URL, and any notification tokens you use. Do not commit `.env` or real secrets; use CI secret storage. ## Local build and run - **Build image**: From the repo root, run your usual Docker build (e.g. `docker build -t your-registry/your-org/mail-roundcube:latest .`). The `package.json` scripts are optional helpers; point them at your registry if desired. - **Run stack**: Ensure `.env` is populated, create the external volume for Enigma if needed, then `docker compose up -d`. For the password plugin to work, the host must run MySQL/MariaDB and expose the socket at `/var/run/mysqld/mysqld.sock`, or you must change the webmail volume and plugin config accordingly. ## Security notes - Never commit `.env` or any file containing real credentials. `.env.example` is a template only. - The 24-character `ROUNDCUBEMAIL_DES_KEY` must be unique and kept secret; it encrypts session data. - Keep registry and CI credentials in your CI secret store, not in the repo. - Traefik labels in the repo are examples; replace hostnames and middleware names with your own before use.