Deploying a Postal App
Introduction
Postal is an open-source mail server for transactional and bulk email, combining a web console, SMTP ingress, and message tracking. Deploying Postal with a Dockerfile on Klutch.sh keeps builds reproducible, secrets managed, and storage persistent—all configured from klutch.sh/app. This guide walks through installation, repo setup, Dockerfile, environment, storage, multi-service port strategy, and sample SMTP usage.
Prerequisites
- A Klutch.sh account (sign up)
- A GitHub repository with your Postal Dockerfile (GitHub is the only supported git source)
- External MySQL-compatible database (e.g., MariaDB) and RabbitMQ broker
- DNS control for sending domains, SPF/DKIM/DMARC, and inbound MX pointing to your Postal host
For onboarding, see the Quick Start.
Architecture and ports
- Web console/API: HTTP on internal port
5000→ choose HTTP traffic and set internal port to5000. - SMTP submission: run a second Klutch.sh TCP app (same image/env) on internal port
2525; select TCP traffic and set internal port to2525to accept authenticated SMTP. Connect onexample-app.klutch.sh:8000externally (Klutch TCP listens on8000), so align your clients accordingly. - Inbound MX on port
25is not available in Klutch.sh; use2525for submissions.
Repository layout
postal/├── Dockerfile # Must be at repo root for auto-detection└── README.mdKeep secrets out of Git; store them in Klutch.sh environment variables.
Installation (local) and starter commands
Validate locally (requires running MySQL and RabbitMQ):
docker build -t postal-local .docker run -p 5000:5000 -p 2525:2525 \ -e POSTAL_HOSTNAME=postal.local \ -e POSTAL_DOMAIN=example.com \ -e RABBITMQ_URL=amqp://user:pass@localhost:5672/ \ -e DB_HOST=localhost \ -e DB_USER=postal \ -e DB_PASS=changeme \ -e DB_NAME=postal \ -e SECRET_KEY_BASE=$(openssl rand -hex 64) \ postal-localDockerfile for Postal (production-ready)
Place this at the repo root; Klutch.sh auto-detects Dockerfiles.
FROM ghcr.io/postalserver/postal:latest
ENV PORT=5000ENV SMTP_PORT=2525
EXPOSE 5000 2525CMD ["postal", "run"]Notes:
- Pin to a stable tag (e.g.,
ghcr.io/postalserver/postal:3.3.2) for predictable upgrades. postal runstarts both web and SMTP listeners; ports are parameterized for Klutch.sh.
Environment variables (Klutch.sh)
Configure these before deploying:
PORT=5000(web)SMTP_PORT=2525(SMTP submission)POSTAL_HOSTNAME=postal.example.comPOSTAL_DOMAIN=example.comRABBITMQ_URL=amqp://<user>:<pass>@<host>:5672/DB_HOST=<db-host>DB_USER=<db-user>DB_PASS=<db-password>DB_NAME=postalSECRET_KEY_BASE=<secure-random-hex>RAILS_ENV=production- Optional:
POSTAL_SMTP_USERNAME,POSTAL_SMTP_PASSWORD,POSTAL_SMTP_FROM,SMTP_TLS=true
If you deploy without the Dockerfile and need Nixpacks overrides:
NIXPACKS_START_CMD=postal runNIXPACKS_RUBY_VERSION=3.2
Attach persistent volumes
Add mount paths and sizes in Klutch.sh storage settings (no names required):
/opt/postal/storage— message storage and logs.
Ensure the paths are writable inside the container.
Deploy Postal on Klutch.sh (Dockerfile workflow)
- Push your repo with the Dockerfile at the root to GitHub.
- In klutch.sh/app, create a new app for the Postal web console.
- Select HTTP traffic and set the internal port to
5000. - Add the environment variables above and attach a volume at
/opt/postal/storagesized for your retention. - Deploy. Your console will be reachable at
https://example-app.klutch.sh. - Create a second app (same GitHub repo and env) for SMTP submission: choose TCP traffic, set the internal port to
2525, and attach the same storage path/size. - Point SMTP clients to
example-app.klutch.shon external port8000(Klutch TCP) with credentials you configure in Postal.
Sample SMTP usage
Configure an SMTP client (e.g., msmtp or app settings):
- Host:
example-app.klutch.sh - Port:
8000(Klutch TCP) → maps to internal2525 - TLS: optional (enable if configured)
- Username/Password: values created in Postal
- From: a verified sender on your domain
Test with swaks:
swaks --to you@example.com --from no-reply@example.com \ --server example-app.klutch.sh:8000 \ --auth LOGIN --auth-user postal-user --auth-password postal-pass \ --data "Subject: Test from Klutch\r\n\r\nHello from Postal on Klutch.sh"Health checks and production tips
- Use an HTTP readiness probe on
/(web UI) for the HTTP app. - Monitor RabbitMQ and DB health; keep credentials in Klutch.sh secrets and rotate regularly.
- Enforce SPF/DKIM/DMARC for sending domains; align MX records if you forward inbound mail elsewhere.
- Pin image versions and test upgrades in staging before production rollout.
- Watch storage usage on
/opt/postal/storageand resize volumes proactively.
Postal on Klutch.sh offers a reproducible Docker workflow, isolated web and SMTP services via separate apps, managed secrets, and persistent storage—without extra YAML or CI config. Configure ports, attach volumes, connect MySQL/RabbitMQ, and start sending.