Deploying a MailCow App
Introduction
MailCow is an open-source mail server suite (Postfix, Dovecot, SOGo, Rspamd) with a modern admin UI. Deploying MailCow with a Dockerfile on Klutch.sh provides reproducible builds, managed secrets, and persistent storage for mail, logs, and configuration—all managed from klutch.sh/app. This guide covers installation, repository prep, a production-ready Dockerfile, deployment steps, Nixpacks overrides, sample SMTP usage, and production tips.
Prerequisites
- A Klutch.sh account (create one)
- A GitHub repository containing your MailCow configuration (GitHub is the only supported git source)
- Docker familiarity and basic mail server administration
- Domain DNS control (MX, SPF, DKIM, DMARC records)
- Storage for mailboxes, queue, and logs
For onboarding, see the Quick Start.
Architecture and ports
- MailCow’s web UI/API serves HTTP; set the internal container port to
8080for the UI. - SMTP (25/587), IMAP (143/993), and POP3 (110/995) are additional TCP services; deploy separate Klutch.sh TCP apps if you expose them, using external port
8000mapped to the internal service port. - Persistent storage is required for
/var/lib/mailcow(mail data, queue) and/etc/mailcow(config).
Repository layout
mailcow/├── Dockerfile # Must be at repo root for auto-detection├── config/ # MailCow config overrides (optional)├── data/ # Mail data (mount as volume)└── .env.example # Template only; no secretsKeep secrets out of Git; store them in Klutch.sh environment variables.
Installation (local) and starter commands
Local smoke test with the upstream image:
docker run --rm -p 8080:8080 \ -e MAILCOW_HOSTNAME=mail.example.com \ -e MAILCOW_TIMEZONE=UTC \ -v $(pwd)/data:/var/lib/mailcow \ -v $(pwd)/config:/etc/mailcow \ mailcow/mailcow-dockerized:latestOptional helper start.sh for portability and Nixpacks fallback:
#!/usr/bin/env bashset -euo pipefailexec /start-mailcow.shMake it executable with chmod +x start.sh.
Dockerfile for MailCow (production-ready)
Place this Dockerfile at the repo root; Klutch.sh auto-detects it (no Docker selection in the UI):
FROM mailcow/mailcow-dockerized:latest
WORKDIR /app
# Optional: copy custom config overridesCOPY config /etc/mailcow
EXPOSE 8080 25 587 143 993 110 995CMD ["/start-mailcow.sh"]Notes:
- Pin the image tag for reproducible behavior.
- Only expose the ports you actually use; in Klutch.sh UI set HTTP for the web UI (8080) and TCP apps for SMTP/IMAP/POP3 if needed.
Environment variables (Klutch.sh)
Set these in the Klutch.sh app settings (Secrets tab) before deploying:
PORT=8080MAILCOW_HOSTNAME=mail.example.comMAILCOW_TIMEZONE=UTCMAILCOW_ADMIN_USER=adminMAILCOW_ADMIN_PASSWORD=<strong-password>SKIP_LETS_ENCRYPT=y(if terminating TLS at the edge; otherwise set up ACME)- Any additional MailCow env vars your deployment requires
If you deploy without the Dockerfile and need Nixpacks overrides:
NIXPACKS_BUILD_CMD="echo MailCow uses prebuilt image"NIXPACKS_START_CMD=/start-mailcow.shNIXPACKS_JDK_VERSION=17(not required for MailCow itself, provided for completeness)
Attach persistent volumes
In Klutch.sh storage settings, add mount paths and sizes (no names required):
/var/lib/mailcow— required for mail data, queue, and databases managed by MailCow./etc/mailcow— required for configuration and certificates.
Ensure these paths are writable inside the container.
Deploy MailCow on Klutch.sh (Dockerfile workflow)
- Push your repository (with the Dockerfile at the root) to GitHub.
- Open klutch.sh/app, create a project, and add an app.
- Connect the GitHub repository; Klutch.sh automatically detects the Dockerfile.
- Choose HTTP traffic for the MailCow web UI and set the internal port to
8080. - Add the environment variables above (hostname, admin credentials, timezone, and any
NIXPACKS_*overrides if you temporarily deploy without the Dockerfile). - Attach persistent volumes for
/var/lib/mailcowand/etc/mailcow, choosing sizes that fit your mailbox and config needs. - Deploy. The web UI will be reachable at
https://example-app.klutch.sh; attach a custom domain if desired.
For SMTP/IMAP/POP3, create separate Klutch.sh TCP apps with internal ports 25, 587, 143, 993, 110, or 995 as needed, reachable externally at example-app.klutch.sh:8000.
Sample SMTP test
Send a test message via curl and openssl (replace placeholders):
openssl s_client -starttls smtp -crlf -connect example-app.klutch.sh:8000 <<'EOF'EHLO example.comAUTH LOGINBASE64_USERNAMEBASE64_PASSWORDMAIL FROM:<you@example.com>RCPT TO:<you@example.com>DATASubject: Test from Klutch.sh MailCow
Hello from MailCow on Klutch.sh..QUITEOFHealth checks and production tips
- Add a reverse proxy probe to the web UI (e.g.,
/) for basic health; for mail protocols, use SMTP/IMAP checks via your monitoring tool. - Enforce HTTPS at the edge for the web UI; forward HTTP to port 8080 internally.
- Pin image tags; upgrade intentionally and take backups beforehand.
- Monitor disk usage on
/var/lib/mailcowand resize before it fills. - Maintain DNS (MX, SPF, DKIM, DMARC) and reverse DNS to ensure deliverability.
- Rotate admin credentials regularly; store them only in Klutch.sh secrets.
MailCow on Klutch.sh combines reproducible Docker builds with managed secrets, durable mail storage, and flexible HTTP/TCP routing. With the Dockerfile at the repo root and ports set appropriately (8080 for UI, TCP apps for mail protocols), you can run a self-hosted mail suite without extra YAML or workflow overhead.