Skip to content

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 8080 for 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 8000 mapped 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 secrets

Keep secrets out of Git; store them in Klutch.sh environment variables.


Installation (local) and starter commands

Local smoke test with the upstream image:

Terminal window
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:latest

Optional helper start.sh for portability and Nixpacks fallback:

#!/usr/bin/env bash
set -euo pipefail
exec /start-mailcow.sh

Make 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 overrides
COPY config /etc/mailcow
EXPOSE 8080 25 587 143 993 110 995
CMD ["/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=8080
  • MAILCOW_HOSTNAME=mail.example.com
  • MAILCOW_TIMEZONE=UTC
  • MAILCOW_ADMIN_USER=admin
  • MAILCOW_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.sh
  • NIXPACKS_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)

  1. Push your repository (with the Dockerfile at the root) to GitHub.
  2. Open klutch.sh/app, create a project, and add an app.
  1. Connect the GitHub repository; Klutch.sh automatically detects the Dockerfile.
  2. Choose HTTP traffic for the MailCow web UI and set the internal port to 8080.
  3. Add the environment variables above (hostname, admin credentials, timezone, and any NIXPACKS_* overrides if you temporarily deploy without the Dockerfile).
  4. Attach persistent volumes for /var/lib/mailcow and /etc/mailcow, choosing sizes that fit your mailbox and config needs.
  5. 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):

Terminal window
openssl s_client -starttls smtp -crlf -connect example-app.klutch.sh:8000 <<'EOF'
EHLO example.com
AUTH LOGIN
BASE64_USERNAME
BASE64_PASSWORD
MAIL FROM:<you@example.com>
RCPT TO:<you@example.com>
DATA
Subject: Test from Klutch.sh MailCow
Hello from MailCow on Klutch.sh.
.
QUIT
EOF

Health 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/mailcow and 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.