# Docker deployment Two independent images, both built from the same source tree: - **`Dockerfile`** — mailgoserver only. - **`Dockerfile.rspamd`** — mailgoserver + the latest [rspamd](https://rspamd.com) in the *same* container, already wired together (see below). Use this one if you want stronger spam filtering than the built-in heuristic score alone. `docker-compose.yml` defines both as Compose **profiles** so a plain `docker compose up` can't accidentally start both at once: ```bash cd docker-deploy # mailserver only docker compose --profile standalone up -d --build # mailserver + rspamd, bundled docker compose --profile with-rspamd up -d --build ``` Either way, the app itself now binds the real standard mail ports by default — 25 (SMTP), 465 (direct-TLS SMTP), 143 (IMAP), 993 (direct-TLS IMAP) — and the admin/webmail UI on its usual non-privileged 5000/5001 (HTTP/HTTPS); put your own reverse proxy or a `80:5000`/`443:5001` port mapping in front if you want those on 80/443 too. Binding the low mail ports needs no extra capability here since the container runs as root. Copy `.env.example` to `.env` in this folder to change any host-side port — useful if something else on the host already owns 25/143/etc., or if you want to run both profiles side by side. ## What happens on first boot There's no baked-in config. On first start, the binary generates a fresh `settings.ini` with defaults (mirroring `internal/config/config.go`), a self-signed TLS certificate, DKIM/mailstore master keys, and an empty SQLite database — all inside the `/app/data` volume, so it survives container restarts/rebuilds. The web UI seeds one admin account: username `admin`, password `Password123!`, and forces an immediate username + password change on first login — see the main [README](../README.md) for the full first-login walkthrough. **Before using this for real mail**, exec into the container (or edit the volume from the host) and update `settings.ini`: ```bash docker exec -it mailgoserver sh -c 'vi /app/data/settings.ini' docker restart mailgoserver ``` At minimum, set `[Server] HOSTNAME` / `helo_hostname` to your real mail domain, and if you'll use passkeys, `[Auth] rp_id` / `rp_origin` to match the exact domain the admin dashboard is reached at (`rp_id` can't be `localhost` once you're on a real domain — see the main README's WebAuthn note). There's no environment-variable override mechanism — `settings.ini` in the volume is the one source of config truth. ## Enabling rspamd (the `with-rspamd` profile) The bundled rspamd's default config already listens on `127.0.0.1:11333` for scanning requests — exactly what `[Rspamd] url` defaults to in `settings.ini`, and since both processes share the container's network namespace, no networking setup is needed. All that's left is turning it on: ```ini [Rspamd] enabled = true url = http://127.0.0.1:11333 reject_score = 15 ``` ...then restart the container. The built-in heuristic spam score (`internal/mailstore/spam.go`) always runs regardless of this setting — rspamd is additive, not a replacement, and if it's ever unreachable, mail still flows on the heuristic score alone (rspamd errors are logged, never fatal to delivery). This bundle intentionally skips Redis — rspamd runs fine without it for SPF/DKIM/RBL/ regexp-based scoring, but Bayes learning and greylisting need it. Add a `redis` service to `docker-compose.yml` and point rspamd's `redis.conf` at it if you need those. ## Persistence | Volume | What's in it | |---|---| | `mailserver-data` / `mailserver-rspamd-data` | `settings.ini`, the SQLite DB, encrypted mailbox storage, DKIM/mailstore master keys, TLS certs, the CSRF app secret — everything mailgoserver itself owns. | | `rspamd-data` (rspamd profile only) | rspamd's own Bayes/fuzzy-hash storage, so spam-learning state survives image rebuilds. | Back up the `*-data` volume like you would the equivalent bare-metal `server_data/` directory — losing the mailstore master key makes all stored mail unrecoverable, same as a non-Docker install. ## Logs / health ```bash docker compose --profile standalone logs -f # or --profile with-rspamd docker inspect --format '{{.State.Health.Status}}' mailgoserver ``` Both images expose `GET /health` (used by the container `HEALTHCHECK`), matching the JSON the admin dashboard's own health check reads.