Production Mailcow Setup: Docker, Traefik Reverse Proxy, and Security Hardening

Build a Production Mailcow Setup with Docker, Traefik, TLS, DNS, hardening, backups, and recovery checks—without confusing a demo with production.

Built With: bash yaml

A Mailcow installation can be online in an afternoon. That is not the same thing as having a production mail system.

The difference appears after the first successful login: a certificate renews while another service owns port 80, a provider blocks outbound SMTP, a Docker network is missing from the proxy, a backup exists but has never been restored, or an update collides with a local change. These are not exotic failures. They are boundary failures, places where Mailcow, Docker, Traefik, DNS, the host, and the mail ecosystem meet.

Production Mailcow setup with Traefik
Production Mailcow setup with Traefik

This guide treats production as a set of verifiable boundaries, not a single Compose command. It focuses on a single-server Mailcow deployment on Linux, with Docker Compose and Traefik at the web edge. Exact commands and settings remain version- and environment-sensitive, so check the current Mailcow documentation and the Traefik documentation before applying changes.

Scope and version boundary

This is an architecture and operations guide, not a universal copy-paste recipe. It assumes a current Mailcow Dockerized release, Traefik v3.x, Linux, public DNS, and a single host. Before production use, pin the exact Mailcow revision, Traefik version, Docker/Compose implementation, operating system, provider, and certificate method in your change record. If your topology differs, keep the principles but re-verify every listener, label, network, and certificate hand-off.

Key Takeaways

Click any topic to expand or collapse
Traefik Traffic Ownership & Routing Boundaries

Traefik should own only the traffic you deliberately give it. Webmail and autodiscover/autoconfig are HTTP concerns; SMTP, submission, IMAP, and POP3 are mail-service concerns with different routing and TLS assumptions.

Explicit Certificate Management Ownership

Certificate ownership must be explicit. Decide which component obtains, stores, renews, and distributes certificates before you write container labels or mount volume files.

Layered Security Infrastructure

Security is layered. Host access control, Docker port exposure, Mailcow administration, DNS authentication records (SPF, DKIM, DMARC), and sender IP reputation are distinct, complementary controls.

Disaster Recovery Testing Beyond Backups

A backup file is not a complete recovery plan. Mailcow’s restore process requires an initialized, running Mailcow environment on a new node; test and document that recovery path prior to an outage.

Production Readiness Verification

Production deployment requires repeatable verification. A setup is operational only when mail delivery flow, automatic certificate renewal, storage capacity, ISP constraints, updates, and restore rehearsals are routinely validated.

Free Resource Production Mailcow Readiness Checklist

Audit your DNS, Traefik edge, TLS, storage, and recovery boundaries before going live. Instant offline file — no email or sign-up required.

The production model: one system, several control planes

Mailcow is not one container. It is a composed platform that brings together mail transport, mailbox access, webmail/groupware, web services, anti-spam, antivirus, DNS support, storage, databases, and caches. The official Mailcow installation documentation explains the supported installation path; the operational challenge is deciding how those components interact with the rest of the host.

Mailcow deployment control planes
Mailcow deployment control planes

A useful mental model is to separate the deployment into five control planes:

  1. Identity and DNS: the hostname, A/AAAA records, MX, reverse DNS/PTR, SPF, DKIM, DMARC, and optional TLSA/DANE records.
  2. Mail transport: inbound SMTP, submission, outbound delivery, queue behavior, and recipient-side reputation.
  3. Mailbox access: IMAP/IMAPS, POP3/POP3S where needed, and client authentication.
  4. Web edge: the Mailcow UI, webmail, autodiscover/autoconfig, ACME challenges, and any other HTTP service on the host.
  5. Operations: updates, backups, restores, logs, disk capacity, alerts, and the ability to explain what changed.

Traefik mainly belongs to the fourth plane. It may also participate in selected TCP routing, but placing every Mailcow protocol behind the same HTTP mental model is where many “works in the demo” configurations become difficult to operate.

The transport-security choice deserves its own review because MTA-STS and DANE protect the SMTP delivery path, not the Traefik web edge. For the trust-model, DNSSEC, certificate, rollover, and enforcement differences, see MTA-STS vs DANE for self-hosted mail.

BoundaryWhat it ownsWhat to verifyTypical failure signal
DNSNames and mail discoveryA/AAAA, MX, PTR, SPF, DKIM, DMARC, optional TLSAClients cannot discover the service or recipients distrust mail
TraefikSelected HTTP/TCP entry points and certificatesEntrypoint, router rule, service port, Docker network, resolver404, wrong certificate, router not created, connection timeout
MailcowMail services and persistent application stateSupported listeners, generated configuration, volumes, update pathMail flow failure, missing mail, broken UI, inconsistent service state
Host firewallHost-level exposurePublished ports, Docker interaction, SSH policy, IPv6 policyA service is reachable when it should not be, or unreachable when it should
RecoveryReconstruction of data and service stateOff-host copies, restore order, secrets, DNS cutover, acceptance testsA “successful” backup cannot produce a usable server

The deployment becomes easier to debug when every port, certificate, secret, and persistent volume has one named owner.

Step 1: Preflight the host and provider before installing Mailcow

The cheapest production incident is the one you prevent before cloning the repository.

Choose a dedicated shape

Choosing a dedicated server shape
Choosing a dedicated server shape

Mailcow’s resource needs depend on enabled services, message volume, mailbox count, antivirus and anti-spam workload, storage, and operational headroom. Community reports show both multi-year use on a 4 GB VM and concerns about Mailcow being more memory-intensive than lighter alternatives. Neither is a universal sizing rule. Treat these reports as context, not a benchmark.

For a serious deployment, prefer a dedicated VPS or host with SSD-backed storage, a stable public IPv4 address, and enough memory that normal activity does not consume the entire system. Confirm whether the provider supports outbound SMTP on port 25 and whether it will set a meaningful PTR record. An immaculate Docker configuration cannot fix a blocked port or a poor sending reputation.

Verify DNS before containers

Verify DNS before containers
Verify DNS before containers

Create the hostname you will actually use and ensure it resolves correctly before you troubleshoot Mailcow. The Mailcow DNS prerequisites cover the records the project expects. At minimum, verify:

  • The Mailcow hostname resolves to the intended public address.
  • The MX record points to the correct mail hostname.
  • Reverse DNS/PTR is set by the provider and corresponds to the sending identity.
  • IPv6 is either correctly configured end to end or deliberately disabled according to the supported Mailcow procedure.
  • SPF, DKIM, and DMARC are planned before the first production message.
  • Autodiscover/autoconfig names are included if your clients require them.

A practical preflight is to test from outside the server’s network. Check both A and AAAA records, inspect the MX chain, verify PTR, and confirm that port 25 is reachable from a permitted external test point. Do not confuse “the web UI loads” with “the mail system can deliver.”

Establish SSH and host boundaries

Securing Docker hosts and firewalls
Securing Docker hosts and firewalls

Use SSH keys, disable password authentication after confirming key access, and restrict administrative access to the smallest practical source set. Keep the host and Docker packages on a supported update path. Do not paste secrets into shell history, screenshots, public tickets, or Compose labels.

The firewall deserves special care. Docker-published ports and host firewall rules do not always behave like a simple process listening directly on the host. The Docker packet-filtering documentation explains why Docker can affect firewall behavior and why administrators should understand the forwarding path instead of assuming that a familiar UFW rule is the complete policy. Test the externally visible ports after applying your firewall policy.

Preflight gate

Do not proceed to proxy debugging until DNS, PTR, port 25 policy, public reachability, storage capacity, and your SSH recovery path are known. This prevents an edge configuration from receiving blame for a provider or identity problem.

Step 2: Install Mailcow without turning the repository into a local fork

Use the supported Mailcow installation flow and keep local customization small, documented, and reversible. The current Mailcow documentation presents Docker Compose Plugin and standalone Compose syntax; choose the command variant that matches the installed tooling and keep it consistent .

Mailcow installation and configuration
Mailcow installation and configuration

A typical setup sequence is conceptually:

Bash: 

# Illustrative sequence — confirm paths and prerequisites in the current Mailcow docs.
git clone https://github.com/mailcow/mailcow-dockerized /opt/mailcow-dockerized
cd /opt/mailcow-dockerized
./generate_config.sh
# Edit mailcow.conf only after reviewing the generated values.
docker compose pull
docker compose up -d

The sequence is deliberately conservative. Do not copy a third-party docker-compose.override.yml into production without checking which Mailcow services, networks, ports, and generated files it assumes. A configuration that worked with an older Compose schema or Traefik release may fail silently or create the wrong routing behavior today.

After the initial start, validate the Mailcow UI, service health, DNS checks, container logs, and disk use. Then record the exact Mailcow revision, Docker version, Compose implementation, Traefik version, operating system, and public hostname. This small inventory turns a future incident from “what changed?” into a question you can answer.

Do not treat generated configuration as disposable. Mailcow’s persistent data includes more than mailbox files. Configuration, secrets, databases, queues, certificates, and service state all belong in the operational model.

Step 3: Design the Traefik boundary before writing labels

Traefik’s Docker provider discovers containers and configures routers and services from Docker metadata. The Traefik Docker provider reference documents the provider’s configuration and the broader routing model. In a Mailcow deployment, the important decision is not “which label do I paste?” It is “which traffic is this router allowed to own?”

HTTP and mail TCP are different problems

Mailcow ingress routing configuration
Mailcow ingress routing configuration

Webmail, the Mailcow UI, and autodiscover/autoconfig are HTTP workloads. SMTP, submission, IMAP, and POP3 are mail protocols. Traefik has separate HTTP and TCP routing concepts; the Traefik routing documentation should be checked for the exact version and syntax you deploy.

A reverse proxy can make web ingress cleaner, but it does not remove the need to understand mail protocol behavior. Decide whether the mail services remain directly published by Mailcow, are passed through a TCP edge, or are handled by a different supported topology. Do not route them through an HTTP router simply because the web UI is already working.

Choose direct Mailcow ingress when…Choose Traefik at the web edge when…
The host is dedicated to Mailcow, you want the smallest number of moving parts, and Mailcow’s supported web exposure fits your needs.The host already has shared HTTP ingress, you need central certificate management, or you can operate an explicit proxy-to-Mailcow boundary.
You cannot yet document who owns each port and how renewal is tested.You can name the Docker network, backend port, router rules, certificate resolver, and rollback path before deployment.

Use a port-ownership matrix

The matrix below is a design tool, not a universal port prescription. Mailcow’s current configuration and your chosen topology determine the final values.

TrafficProtocol classPossible ownerProduction question
Web UI / webmailHTTP/HTTPSTraefik → Mailcow web serviceIs TLS terminated once, and is the backend port explicitly known?
Autodiscover / autoconfigHTTP/HTTPSTraefik → the correct Mailcow web routeAre host rules and paths tested with a real client?
Inbound SMTPTCPMailcow/Postfix directly or a deliberate TCP edgeCan external senders connect, negotiate TLS, and deliver?
SubmissionTCP with authentication/TLSMailcow/Postfix directly or deliberate TCP edgeDoes a client authenticate without exposing an unintended service?
IMAP/IMAPSTCP with TLS optionsMailcow/Dovecot directly or deliberate TCP edgeAre certificate names, TLS policy, and client settings aligned?

Certificate ownership is a lifecycle, not a label

Mailcow Traefik v3 deployment
Mailcow Traefik v3 deployment

The current Mailcow Traefik v3 guide describes a community-supported approach in which Traefik handles web traffic, domain routing, and certificate management. It also shows disabling Mailcow’s built-in Let’s Encrypt handling, configuring Traefik, restarting services, and testing the web and autodiscover paths . Follow that guide’s current configuration rather than treating an old blog post as a drop-in template.

Before you deploy, answer five questions:

  1. Which component requests the certificate?
  2. Where is the ACME state stored, and who can read it?
  3. Which web entry point answers the ACME challenge?
  4. Which Mailcow services need certificate material, if any, after TLS termination?
  5. How will renewal trigger reloads or certificate distribution, and how will you know it succeeded?

A common failure pattern is a green certificate on one service and an insecure certificate on Mailcow. The root cause can be a missing Docker network, a service port mismatch, a router that never matched, or a certificate that Traefik obtained but Mailcow’s mail services never received. Inspect the proxy logs, router state, container networks, certificate storage, and the externally served certificate separately.

A safe Traefik implementation sequence

  1. Create or confirm the shared Docker network used by Traefik and the Mailcow web service.
  2. Confirm the backend web listener and whether Mailcow exposes it directly or through an internal port.
  3. Add one HTTP router for the primary Mailcow hostname.
  4. Add and test autodiscover/autoconfig routes only after the primary UI route works.
  5. Add TLS resolution and renewal handling.
  6. Restart the affected services using the current Mailcow documentation.
  7. Test from outside the host: browser, curl, a mail client, and a certificate inspection tool.
  8. Only then decide whether selected mail protocols need a TCP router.

This ordering gives each failure a smaller search space. If the primary web route is broken, adding six more labels will make the incident harder to read, not easier to solve.

Step 4: Add the proxy configuration without creating a hidden port conflict

The examples below are illustrative patterns, not a drop-in replacement for the current Mailcow Traefik v3 guide. Keep the generated Mailcow Compose files intact, use docker-compose.override.yml rather than editing docker-compose.yml, and substitute your real hostname, certificate resolver, and external Docker network. The current Mailcow guide uses an internal web-service port of 8080 in its Traefik example .

Mailcow settings: certificate ownership and bindings

Configuring Traefik with Mailcow
Configuring Traefik with Mailcow

If Traefik is the component terminating HTTPS, Mailcow’s current Traefik v3 guidance documents skipping Mailcow’s built-in ACME handling for that topology. The exact binding values depend on where Traefik runs. A containerized Traefik cannot reach a Mailcow service bound only to the host loopback address, so do not copy HTTP_BIND=127.0.0.1 blindly into a container-to-container design.

For a topology in which the Mailcow web service is exposed to the Docker network and Traefik reaches it internally, use the current Mailcow reverse-proxy example as the source of truth and record the chosen internal port. A simplified, version-sensitive settings block may look like this:

# mailcow.conf — illustrative; verify against the current reverse-proxy guide
SKIP_LETS_ENCRYPT=y
AUTODISCOVER_SAN=n

# Use the internal web port expected by your chosen proxy topology.
# Do not bind the service to 127.0.0.1 when Traefik runs in another container.
HTTP_PORT=8080
HTTPS_PORT=8443
HTTP_BIND=
HTTPS_BIND=

The blank bind values above are intentional placeholders for a Docker-network topology, not a universal security recommendation. If you use a host-level proxy instead, a loopback bind may be appropriate, but the host proxy and Mailcow port mappings must then agree. The Mailcow IP bindings documentation explains the binding format; verify the generated Compose mapping before restarting services.

A conservative docker-compose.override.yml pattern

Traefik configuring mailcow network
Traefik configuring mailcow network

The following pattern shows the ownership relationship: Traefik discovers nginx-mailcow on one named external network, routes HTTPS web traffic to the internal web port, and obtains certificates through its configured resolver. It intentionally does not pretend that SMTP, IMAP, or POP3 should use the same HTTP router.

YAML:

# docker-compose.override.yml — illustrative Traefik v3 pattern
# Replace proxy, mail.example.com, and myresolver with your values.
services:
  nginx-mailcow:
    expose:
      - "8080"
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.mailcow.rule=Host(`mail.example.com` )"
      - "traefik.http.routers.mailcow.entrypoints=websecure"
      - "traefik.http.routers.mailcow.tls=true"
      - "traefik.http.routers.mailcow.tls.certresolver=myresolver"
      - "traefik.http.routers.mailcow.service=mailcow-web"
      - "traefik.http.services.mailcow-web.loadbalancer.server.port=8080"

networks:
  proxy:
    external: true

Before applying it, confirm that the network is created and that the Traefik container joins the same network. Then inspect the merged configuration rather than guessing what Compose will do:

Bash: 

docker network inspect proxy
docker compose config > /tmp/mailcow-effective-compose.yml
grep -A30 -n 'nginx-mailcow:' /tmp/mailcow-effective-compose.yml

The current community-supported Mailcow Traefik page also demonstrates explicit routes for autodiscover/autoconfig and certificate distribution to mail services. If clients or SMTP/IMAP listeners need certificates from Traefik, follow that guide’s cert-dumper and downstream-reload pattern instead of assuming the web certificate automatically covers every listener .

Do not copy this blindly

A label can be syntactically valid and still route to the wrong port, network, or certificate owner. Treat the snippet as a map of responsibilities. Validate the generated Compose model, Traefik dashboard or API, TLS handshake, web route, autodiscover path, and mail-client connections after every topology change.

Step 5: Choose an outbound SMTP relay when port 25 is unavailable

A provider may block outbound TCP/25 or restrict new accounts from direct delivery. In that case, the practical alternative is a sender-dependent transport: Mailcow hands selected outbound mail to a third-party relay, also called a smarthost. The current Mailcow relayhost documentation describes using the admin UI’s Configuration and Details → Routing → Add sender-dependent transport, entering the relay host and credentials, testing the relay, and assigning the transport to a domain .

Configuring mail relay in Mailcow
Configuring mail relay in Mailcow

This is not a way to hide poor sender identity. The relay provider will usually require domain verification, authenticated submission, and its own SPF/DKIM/DMARC or alignment steps. Keep the provider’s credentials out of public snippets and note that Mailcow’s documentation warns that relayhost credentials are stored in plain text in the relevant configuration path . Review the provider’s current security model before choosing a service such as Amazon SES, SendGrid, Mailgun, or Postmark.

A safe relay workflow is:

  1. Confirm whether direct outbound port 25 is actually blocked from the server.
  2. Create and verify the sending domain in the relay provider’s console.
  3. Add the relayhost in Mailcow’s Routing UI and test it with a controlled sender.
  4. Assign the sender-dependent transport to the intended domain rather than changing every domain by accident.
  5. Send a test message, inspect the Mailcow/Postfix logs, and verify the provider’s delivery event.
  6. Document the fallback plan if the relay provider is unavailable.

The relay changes the outbound path; it does not remove the need for correct PTR, SPF, DKIM, DMARC, TLS, abuse controls, queue monitoring, and a tested recovery plan.

Step 6: Harden the host, Docker edge, and Mailcow admin surface

Security hardening is most useful when each control has a threat and an observable test.

Host and Docker controls

Securing Docker and SSH access
Securing Docker and SSH access

Keep SSH access key-based and restricted. Patch the operating system and Docker components through a known maintenance path. Avoid exposing the Docker socket to more services than necessary; Traefik’s Docker provider needs access to Docker metadata, but that does not make the socket harmless. Use read-only mounts where they are supported by the chosen architecture, keep secrets out of labels and public repositories, and document every exception.

Review published ports from the outside. A service that is “not linked in Traefik” may still be reachable because of a host-published port. Conversely, a firewall policy may appear correct while Docker forwarding creates a different exposure path. The test is not the rule file; the test is the observed network surface.

Mailcow administration

Securing Mailcow administrator
Securing Mailcow administrator

Use strong, unique administrator credentials and enable the Mailcow account protections that your current release supports, including two-factor authentication where appropriate. Separate administrator access from routine mailbox administration. Keep the admin interface off broad public exposure when your topology allows it, but do not hide it behind an untested proxy rule that breaks emergency access.

Do not describe a deployment as “fully secure.” Security depends on configuration, patching, credentials, exposure, logs, and operator behavior. Mailcow’s documentation includes dedicated guidance for two-factor authentication, WebAuthn/FIDO2, firewall-related tasks, TLS, and service-specific hardening; use the current project pages for exact capabilities rather than relying on a generalized checklist.

Deliverability controls are not the same as host controls

Configuring email authentication
Configuring email authentication

SPF helps receiving systems evaluate authorized senders for a domain. DKIM provides a cryptographic signature that receivers can verify. DMARC connects domain alignment and receiver policy to those signals. Reverse DNS and IP reputation affect how receiving systems interpret a sending host. These controls improve the trust story for mail, but they do not replace patching, access control, or network segmentation.

Use Mailcow’s DNS checks and external validation tools after publishing records. Send test messages to multiple recipient providers and inspect authentication results. A message reaching one inbox does not prove consistent deliverability everywhere.

Control laneProtects or improvesExample verificationDo not confuse it with
Host accessAdministrative entry pointsKey-only SSH, restricted sources, tested recovery keyMail authentication
Docker exposureReachability of containers and published portsExternal port scan and container publish reviewTraefik router visibility
Mailcow adminAccount and control-plane access2FA/WebAuthn policy and admin login reviewSpam filtering
DNS authenticationDomain authentication and alignment signalsSPF/DKIM/DMARC checks in received headersHost patching
ReputationRecipient trust in the sending IP/domainProvider checks and real delivery testsA valid TLS certificate

Step 7: Treat updates as a controlled change

Do not use generic image automation as a substitute for Mailcow’s supported update process. The current Mailcow update documentation documents ./update.sh, a check mode, stable/nightly/legacy variants, hooks, and rollback guidance. It also states that stable updates are intended for productive use while nightly updates are for testing and are not suitable for production.

Updating Mailcow server safely
Updating Mailcow server safely

A disciplined update runbook looks like this:

  1. Record the current revision, configuration changes, disk space, certificate expiry, queue state, and backup location.
  2. Run the supported update check and review changes before applying them.
  3. Confirm that your off-host backup is current and that the restore path is known.
  4. Apply the update during a maintenance window appropriate for your traffic.
  5. Verify container health, web access, SMTP submission, inbound delivery, IMAP, spam processing, and certificate status.
  6. Compare logs and queue behavior with the pre-update baseline.
  7. Record the result and any manual intervention.

Be careful with local changes. The Mailcow update process is repository-aware; a local override or hand-edited generated file can create conflicts or be overwritten. Keep customizations in the supported extension points, track them in version control outside of secrets, and review the diff before a production update.

Step 8: Make backups recoverable

The official Mailcow backup documentation and restore documentation should be your source of truth for the current script and component behavior. The restore page documents backup-path handling, optional multithreading, component selection, and an important prerequisite: on a new system, Mailcow must be initialized and running before restoration.

Mailcow backup and restore
Mailcow backup and restore

That prerequisite changes how you think about disaster recovery. You do not restore into an imaginary empty directory and assume the application will reconstruct itself. You prepare a compatible host, initialize Mailcow, then restore the selected data through the supported mechanism.

The restore documentation lists components such as crypt data, Rspamd data, the mail directory, Redis, Postfix data, and the SQL database. It also warns about architecture differences and the MAILDIR_SUB value for older installations. These details are exactly why a backup should be tested on a separate recovery environment rather than trusted because a scheduled job completed.

A useful recovery drill includes:

  • A copy stored outside the production host.
  • A record of the Mailcow hostname, revision, Docker/Compose versions, DNS provider, and secret-handling process.
  • A clean recovery host or VM with the required architecture and storage.
  • A test initialization before restoration.
  • A restore of the components your recovery objective requires.
  • Verification of mailbox visibility, authentication, inbound/outbound mail, aliases, DKIM, TLS, and web access.
  • A documented DNS or provider cutover plan.

Do not publish a fixed RPO/RTO number unless you have measured it on your own workload. The community evidence supports the importance of backup and restore questions; it does not establish a universal recovery time.

Rollback and failure containment

A production runbook needs a stop condition. If a proxy change breaks web access, restore the last known-good edge configuration and keep mail transport changes separate. If an update produces a service regression, use the rollback procedure documented by Mailcow for the relevant revision; do not improvise a database or volume deletion. If a restore test fails, preserve the backup and logs, record the missing prerequisite, and do not overwrite the only production copy while experimenting.

Production runbook stop conditions
Production runbook stop conditions

For every change, capture the before-state, the exact file or repository revision changed, the expected observable result, and the reversal command or documented procedure. This is especially important when certificate distribution, generated Mailcow configuration, Docker networks, or repository-local changes are involved.

CLI verification commands you can run after each change

Use these commands from a trusted administrative shell and replace every placeholder. They test different boundaries; one successful command does not prove that the whole mail system is healthy.

Inspect DNS and reverse DNS

Bash:

# Forward records for the service hostname and mail discovery
dig +short A mail.example.com
dig +short AAAA mail.example.com
dig +short MX example.com

# Reverse DNS / PTR for the public sending address
dig -x <YOUR_SERVER_IP> +short

The PTR result should be compared with the hostname used in your mail identity and provider configuration. DNS consistency is a prerequisite, not a deliverability guarantee.

Inspect SMTP STARTTLS

Bash:

openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com -crlf

Look for a completed TLS handshake, a certificate whose names match the service you are testing, and an SMTP banner appropriate to the listener. For submission, test the port and TLS mode that your client actually uses; do not infer submission health from port 25.

Send a controlled submission test with swaks

Bash:

swaks \\
  --to controlled-recipient@example.net \\
  --from test@example.com \\
  --server mail.example.com \\
  --port 587 \\
  --tls \\
  --auth LOGIN \\
  --auth-user 'test@example.com' \\
  --auth-password 'USE-A-SECRET-MANAGER-OR-INTERACTIVE-INPUT'

Use a mailbox you control, obtain permission before sending, and avoid putting a real password in shell history. If the command reports success, verify the message in the destination mailbox and inspect the Postfix logs; a 250 response confirms acceptance by the next hop, not inbox placement everywhere.

Inspect queue and service logs

Bash:

cd /opt/mailcow-dockerized
docker compose ps
docker compose logs --tail=200 postfix-mailcow
docker compose exec postfix-mailcow postqueue -p

The exact container name and available commands can differ with the deployed Mailcow revision. Use docker compose ps first, and consult the current Mailcow troubleshooting documentation if a service name or command is absent.

A practical production verification loop

A production setup should have a short, repeatable loop that an operator can run after installation and after every meaningful change.

Verification loop

1. Identity DNS, MX, PTR, SPF, DKIM, DMARC, hostname.
2. Edge Routes, backend port, certificate, renewal state.
3. Mail flow Inbound, outbound, submission, IMAP, client discovery.
4. Operations Logs, queue, disk, alerts, update record.
5. Recovery Backup freshness and restore evidence.

If a check fails, isolate the boundary. A certificate problem is not automatically a Traefik problem; it may be DNS, ACME challenge reachability, a router rule, a Docker network, certificate storage, or a downstream service that still expects the certificate.

Monitoring and alerting: Watchdog plus an independent view

Mailcow includes Watchdog checks for container and service conditions. The current threshold documentation lists checks for services such as Nginx, Unbound, Redis, MySQL, Postfix, Dovecot, Rspamd, ACME, Fail2ban, and the Postfix queue; it also documents MAILQ_THRESHOLD and MAILQ_CRIT as configurable queue thresholds. Watchdog can restart affected containers after a threshold is reached, but that recovery action is not a substitute for incident notification or root-cause analysis.

Mailcow monitoring stack configuration
Mailcow monitoring stack configuration

Configure WATCHDOG_NOTIFY_EMAIL to an external recipient managed by another mail system. Mailcow’s authorization guidance explains that Watchdog notifications may need to work when Postfix, Rspamd, or Redis inside the instance is unavailable, and therefore recommends external recipients plus SPF/DMARC for MAILCOW_HOSTNAME . Test that notification path deliberately.

For a second view, the current Mailcow Prometheus exporter documentation describes enabling its compose override, exposing /metrics with a hostname and read-only API key, and restricting the exporter to localhost or a trusted network rather than binding it broadly . This is useful for metrics such as container state, API response health, and mail-queue observations, but it introduces another secret and endpoint that must be protected.

A practical monitoring stack can therefore have three layers:

LayerWhat it seesWhat to alert onResidual risk
Mailcow WatchdogService checks and selected queue thresholdsRepeated failed checks, container restarts, critical queue growthIt runs with the instance; an instance-wide failure may prevent local visibility
Prometheus exporterRead-only API-backed service and container metricsScrape failure, API failure, queue trend, service-down signalThe API key and metrics endpoint need network controls
External uptime / host monitoringPublic reachability, TLS expiry, disk, CPU, memory, and host livenessHTTP/TLS failure, disk pressure, host down, certificate nearing expiryAn HTTP check cannot prove mail acceptance or inbox placement

Tools such as Netdata or Uptime Kuma can fill the external host and reachability layer, while Prometheus/Grafana can visualize exporter metrics. Treat them as deployment choices, not Mailcow guarantees, and keep at least one notification route independent of the server being monitored.

Common production mistakes—and the better replacement

Common production mistakes and replacement
Common production mistakes and replacement

Mistake 1: Treating Traefik as a universal Mailcow proxy

Why it fails: HTTP routing and mail TCP services have different semantics.

Better replacement: Start with the web edge, document every mail protocol separately, and add TCP routing only when the selected topology requires it.

Mistake 2: Copying a community override without a version check

Why it fails: Community examples are valuable but may depend on an older Mailcow, Compose, or Traefik layout.

Better replacement: Use the current official page for supported behavior, then use community threads for failure modes and test ideas.

Mistake 3: Calling a green padlock “secure”

Why it fails: TLS protects one connection path; it does not harden SSH, Docker, admin accounts, DNS authentication, or recipient trust.

Better replacement: Maintain a control matrix with a threat, owner, and verification method for each control.

Mistake 4: Automating updates like generic stateless containers

Why it fails: Mailcow is a stateful composed platform with repository-aware update behavior and persistent data.

Better replacement: Use the supported update script, review changes, back up first, and verify the mail system afterward.

Mistake 5: Measuring backup success by file creation

Why it fails: A backup can exist while the restore prerequisites, secrets, architecture, or DNS cutover are unknown.

Better replacement: Perform a recovery drill and record the result.

Before and after: from tutorial install to production system

Tutorial stateProduction stateProof
The UI loads over HTTPSCertificate owner and renewal path are documentedRenewal test and expiry monitoring
Containers are runningPersistent state, published ports, and Docker networks are intentionalExternal port review and service health checks
A test email arrivedInbound, outbound, submission, authentication, and client discovery workMulti-provider mail-flow test and received headers
A backup job completedAn off-host backup can produce a usable, tested serviceRecovery drill with acceptance checks
An update command ranThe supported update path was reviewed and the system was revalidatedChange record, logs, queue, and mail-flow comparison

Final checklist

Before calling the deployment production-ready, confirm that you can answer these questions without opening a random forum tab:

  • Which component owns every public port?
  • Which component requests and renews each certificate?
  • Which Docker network connects Traefik to the Mailcow web service?
  • Which records establish mail identity and authentication?
  • What happens if outbound port 25 is blocked or the IP reputation is poor?
  • Which update path is supported, and what local changes must be reviewed?
  • Where is the off-host backup, and when was the last restore drill?
  • How will you detect certificate expiry, queue growth, disk pressure, and failed services?

A successful Mailcow deployment is not the one with the most labels. It is the one whose boundaries are visible, whose state is recoverable, and whose operator can explain what will happen when the happy path ends.

Pre-Flight Verification

Take the Production Audit Checklist with You

Don’t rely on memory during cutover. Download the standalone offline checklist covering all 5 boundaries (DNS, Traefik edge, TLS, storage recovery, and watchdog limits) — 100% free, no tracking, and no email required.

FAQ: Production Mailcow Setup

Do I need Traefik in front of Mailcow?
No universal rule makes Traefik mandatory. It is useful when you deliberately share HTTP ingress, centralize certificate management, or operate several web services. A single-purpose host may use Mailcow’s own supported web edge instead. Choose based on port ownership, threat model, certificate lifecycle, and operational capability—not fashion.
Can Traefik handle SMTP and IMAP the same way it handles the Mailcow web UI?
No. The web UI is HTTP/HTTPS. SMTP, submission, IMAP, and POP3 are mail protocols and require a deliberate TCP or direct-publication design. Confirm the current Traefik TCP routing behavior and the Mailcow reverse-proxy guidance for the exact versions you use before exposing these services.
Should I disable Mailcow’s built-in Let’s Encrypt handling when Traefik manages certificates?
The current Mailcow Traefik v3 guide describes disabling Mailcow’s built-in ACME handling for that topology. Do not apply the setting in isolation: also configure the Traefik resolver, challenge path, backend route, certificate storage, and any downstream certificate distribution required by the chosen design. Verify the current official guide before changing production settings.
How much RAM does a production Mailcow server need?
There is no safe universal number. Workload, enabled services, message volume, storage, anti-spam/antivirus activity, and headroom all matter. Community reports include successful smaller deployments, but those reports are not benchmarks. Measure your own workload and leave room for maintenance and recovery operations.
Is a Mailcow backup enough to recover from a server failure?
Only if it contains what your recovery objective requires and you have tested the restore path. Mailcow’s restore documentation says a new system must be initialized and running before restoration, and it documents component and architecture considerations. Treat restoration as a drill, not an assumption.
Should I use an automatic Docker image updater for Mailcow?
Do not replace Mailcow’s supported update process with generic automation without understanding the project’s repository-aware update path, local changes, backups, and rollback guidance. The current documentation distinguishes stable, legacy, and nightly update paths. Use nightly builds for testing rather than assuming they are production-safe.
Does SPF, DKIM, and DMARC make a Mailcow server secure?
They address domain authentication and alignment signals, not the whole server. You still need host access controls, Docker exposure review, Mailcow admin protection, patching, TLS, monitoring, and recovery. Deliverability controls and host security belong in separate but connected checklists.
📋 Article Timeline & History
Latest Update

Successfully updated on September 10, 2026 with the latest details.

Originally Published

This article was originally published on August 29, 2026.

About The Author

A Gadallh

Ahmed Gadallah is the Founder and Editor of Vertex Frontier, where he publishes research-driven articles on AI, data science, cloud computing, cybersecurity, software engineering, and emerging technologies, with a focus on technical accuracy, clarity, and practical insights.

View all articles by A Gadallh →

Was this article helpful?

3 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

🏠 Home 🔖 Saved 📧 Join Us 📤 Share ⬆️ To Top
Read Next Mailcow DNS Setup, Done Right: The Four Layers Behind Every Working Deployment