Skip to content

Deploying a Mailu App

Introduction

Mailu is an open-source mail server suite (Postfix, Dovecot, Rspamd, and web admin) packaged for containerized deployments. Deploying Mailu with a Dockerfile on Klutch.sh provides reproducible builds, managed secrets, and persistent storage for mail data, DKIM keys, and configuration—all orchestrated from klutch.sh/app. This guide covers installation, repository prep, a production-ready Dockerfile, deployment steps, Nixpacks overrides, sample SMTP usage, and production best practices.


Prerequisites

  • A Klutch.sh account (create one)
  • A GitHub repository containing your Mailu configuration (GitHub is the only supported git source)
  • Docker familiarity and mail server administration basics
  • Domain DNS control (MX, SPF, DKIM, DMARC records and reverse DNS)
  • Storage for mailboxes, queue, DKIM keys, and logs

For onboarding, see the Quick Start.


Architecture and ports

  • Mailu web/admin serves HTTP; set the internal container port to 80 for the UI/API.
  • Mail protocols use TCP ports: SMTP 25/465/587, IMAP 143/993, POP3 110/995. Expose these via separate Klutch.sh TCP apps (external port 8000 mapped to the internal protocol port).
  • Persistent storage is required for mail data and DKIM keys.

Repository layout

mailu/
├── Dockerfile # Must be at repo root for auto-detection
├── config/ # Optional overrides
├── data/ # Mail and state (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

Smoke-test Mailu locally:

Terminal window
docker run --rm -p 80:80 -p 25:25 -p 587:587 \
-e MAILU_SECRET_KEY=$(openssl rand -hex 16) \
-e HOSTNAME=mail.example.com \
-e DOMAIN=example.com \
-e TZ=UTC \
-v $(pwd)/data:/data \
-v $(pwd)/config:/overrides \
mailu/mailu:2.0

Optional helper start.sh for portability and Nixpacks fallback:

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

Make it executable with chmod +x start.sh.


Dockerfile for Mailu (production-ready)

Place this Dockerfile at the repo root; Klutch.sh auto-detects it (no Docker selection in the UI):

FROM mailu/mailu:2.0
WORKDIR /app
# Optional: copy custom overrides
COPY config /overrides
EXPOSE 80 25 465 587 110 995 143 993
CMD ["/start.py"]

Notes:

  • Pin the image tag (e.g., mailu/mailu:2.0) for reproducible behavior.
  • Only expose the ports you actually need in Klutch.sh; set HTTP for the web UI (80) and separate TCP apps for mail protocols.

Environment variables (Klutch.sh)

Set these in the Klutch.sh app settings (Secrets tab) before deploying:

  • PORT=80
  • MAILU_SECRET_KEY=<secure-hex> (required)
  • HOSTNAME=mail.example.com
  • DOMAIN=example.com
  • TZ=UTC
  • ADMIN=<admin@example.com>
  • PASSWORD=<strong-admin-password>
  • TLS_FLAVOR=letsencrypt (or mail, cert)
  • LOG_LEVEL=INFO

If you deploy without the Dockerfile and need Nixpacks overrides:

  • NIXPACKS_BUILD_CMD="echo Mailu uses prebuilt image"
  • NIXPACKS_START_CMD=/start.py
  • NIXPACKS_JDK_VERSION=17 (not required for Mailu, provided for completeness)

Attach persistent volumes

In Klutch.sh storage settings, add mount paths and sizes (no names required):

  • /data — required for mail data, queue, and state.
  • /overrides — optional for custom configuration and templates.

Ensure these paths are writable inside the container.


Deploy Mailu 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 Mailu admin/UI and set the internal port to 80.
  3. Add the environment variables above (secret key, hostname, domain, TLS flavor, admin credentials, and any NIXPACKS_* overrides if you temporarily deploy without the Dockerfile).
  4. Attach persistent volumes for /data (and /overrides if used), selecting sizes that fit your mailbox and config needs.
  5. Deploy. The Mailu 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, 465, 587, 143, 993, 110, or 995 as needed, reachable externally at example-app.klutch.sh:8000.


Sample SMTP test

Use openssl to send a quick SMTP command (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 Mailu on Klutch.sh
Hello from Mailu on Klutch.sh.
.
QUIT
EOF

Health checks and production tips

  • Probe the web UI (/) for basic health; use SMTP/IMAP checks via monitoring tools for protocol health.
  • Enforce HTTPS at the edge; forward HTTP to port 80 internally.
  • Pin image tags and upgrade intentionally; back up data before updates.
  • Monitor disk usage on /data and resize volumes before they fill.
  • Maintain DNS records (MX, SPF, DKIM, DMARC) and reverse DNS for deliverability.
  • Rotate admin credentials regularly; store them only in Klutch.sh secrets.

Mailu 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 (80 for UI, TCP apps for mail protocols), you can run a self-hosted mail suite without extra YAML or workflow overhead.