6.0 KiB
EternityMail
Docker Compose deployment for Stalwart Mail and Roundcube.
Requirements
- Docker Engine with the Compose plugin
- A Linux host for the production deployment
- DNS records pointing the mail hostname to the server
- The
ep-roundcube-skinrepository available as a sibling directory if the custom skin is enabled
Configuration
Create the real environment file from the template:
cp .env.example .env
Edit .env and set production values, especially:
MAIL_HOSTNAMEandMAIL_DOMAINRC_DB_PASSWORDRC_DB_ROOT_PASSWORDRC_DES_KEYSTALWART_RECOVERY_ADMIN
The real .env file is ignored by Git. Do not commit credentials or recovery settings.
Roundcube uses MAIL_HOSTNAME for IMAP and SMTP submission by default. To connect Roundcube to Stalwart by IP instead, add ROUNDCUBE_IMAP_HOST=<ip-address> and ROUNDCUBE_SMTP_HOST=<ip-address> to .env. These change only Roundcube's IMAP and SMTP endpoints; MAIL_HOSTNAME remains the Stalwart hostname and Docker network alias.
For a local Stalwart test installation using its generated self-signed certificate, set ROUNDCUBE_ALLOW_SELF_SIGNED_CERT=true in .env. This disables certificate verification for Roundcube's IMAP and SMTP connections and must be set to false after configuring a trusted Stalwart certificate.
Generate a DES key
On Linux or macOS:
chmod +x scripts/generate-des-key.sh
scripts/generate-des-key.sh
On Windows PowerShell:
.\scripts\generate-des-key.ps1
Put the generated 24-character value in RC_DES_KEY in .env.
Persistent Stalwart data
Stalwart configuration, mail, and certificates are stored in Docker-managed volumes. This avoids host filesystem ownership problems after Docker Desktop or WSL restarts. The stalwart-data-init service assigns the ownership Stalwart requires before it starts.
Do not use docker compose down --volumes or docker volume rm for this project unless you intend to permanently delete Stalwart's configuration and mail data.
To protect against laptop loss, disk failure, or a Docker Desktop reset, back up the three eternitymail-stalwart-* volumes to storage outside Docker Desktop. Docker volumes protect data across normal container recreation, not a destroyed Docker data disk.
The legacy Linux bind-mount preparation command applies only to deployments which still use DATA_ROOT bind mounts:
chmod +x scripts/setup-data-dirs.sh
sudo ./scripts/setup-data-dirs.sh
The script uses DATA_ROOT from .env when it is exported in the shell; otherwise it defaults to /opt/eternitymail. To use the value from .env directly, run the setup command with it loaded or pass the path explicitly:
sudo DATA_ROOT=/opt/eternitymail ./scripts/setup-data-dirs.sh
Custom Roundcube skin
The default configuration expects the skin at:
../ep-roundcube-skin/eternity
relative to this repository. Override the location in .env with ROUNDCUBE_SKIN_PATH if needed. The skin directory is mounted read-only and selected with ROUNDCUBE_SKIN_NAME.
The bundled roundcube-config/eternity-logo.php override sets the login and mailbox logos to the Eternity skin's images/logo.svg through Roundcube's static.php asset endpoint. This is required because Eternity inherits Elastic's templates, which would otherwise display Elastic's default logo. Keep this file and its mount in docker-compose.yml when using the Eternity skin.
Start and stop
Validate the rendered configuration:
docker compose config --quiet
Start the services:
docker compose up -d
View service status and logs:
docker compose ps
docker compose logs -f stalwart
Stop the services without deleting persistent data:
docker compose down
Persistent data is stored under DATA_ROOT in the stalwart, roundcube-db, and roundcube-config directories.
Backup, restore, and server migration
Backups include Stalwart configuration, certificates, mailboxes, Roundcube's database/configuration, .env, and docker-compose.yml. The backup stops the mail services briefly so the RocksDB and MariaDB files are consistent, then starts them again.
On Linux, create a backup outside Docker Desktop or the server's Docker data disk:
chmod +x scripts/backup-server.sh scripts/restore-server.sh
./scripts/backup-server.sh /mnt/backup/eternitymail
On Windows PowerShell:
.\scripts\backup-server.ps1 -Destination D:\Backups\EternityMail
Restore that backup to Docker Desktop with:
.\scripts\restore-server.ps1 -Archive D:\Backups\EternityMail\eternitymail-<timestamp>.tar.gz
Copy the resulting .tar.gz archive, this repository, and the ep-roundcube-skin checkout to the new Linux server. Install Docker Engine with the Compose plugin, then restore from the repository root:
sudo ./scripts/restore-server.sh /mnt/backup/eternitymail/eternitymail-<timestamp>.tar.gz
docker compose ps
Restore refuses to replace an existing deployment unless --force (Linux) or -Force (PowerShell) is supplied. That option stops the stack and permanently replaces its Stalwart volumes and Roundcube bind-mount data. Keep the same .env from the archive, particularly RC_DES_KEY, passwords, hostname, and recovery administrator setting. Before moving production traffic, update the new server's DNS, firewall, and TLS configuration, then verify IMAPS and SMTP.
Network ports
The host bindings are configurable in .env:
- SMTP:
STALWART_SMTP_PORT(default25) - Submission:
STALWART_SUBMISSION_PORT(default587) - IMAPS:
STALWART_IMAPS_PORT(default993) - Stalwart administration:
STALWART_ADMIN_BINDandSTALWART_ADMIN_PORT(defaults127.0.0.1:8081); setSTALWART_ADMIN_BIND=to listen on all host interfaces - Roundcube:
ROUNDCUBE_BINDandROUNDCUBE_PORT(defaults127.0.0.1:8091); setROUNDCUBE_BIND=to listen on all host interfaces
The Stalwart and Roundcube containers communicate over the private eternitymail Docker network.