Sign inSign up

euca01/postfix-distroless

By euca01

•Updated about 2 months ago

Enterprise-grade Postfix on a distroless base: DB/LDAP maps, TLS 1.2-1.3, DANE, SASL, hardened

Image
0

1.5K

euca01/postfix-distroless repository overview

⁠postfix-distroless — deployment kit

Everything needed to deploy and operate euca01/postfix-distroless⁠ — enterprise-grade Postfix on a distroless base (no shell, no package manager, amd64/arm64, hardened by default, built and fully tested automatically for every upstream release).

This repository contains deployment material only: compose files, examples and operating documentation. The container images are prebuilt and published on Docker Hub.

⁠Deploy in 3 commands

git clone <this-repo> postfix && cd postfix
cp .env.example .env && $EDITOR .env      # image tag + hostname
docker compose up -d

That's it:

  • the hardened production compose (read-only rootfs, dropped capabilities, persistent queue volume) starts a ready-to-use MTA;
  • on first start, ./config/ is seeded with the commented, hardened configuration of your exact image version — edit the real Postfix files there and apply live with docker kill -s HUP postfix;
  • prefer reviewing before the first start? Extract the template first:
docker run --rm euca01/postfix-distroless:3.11.6-r2 config-template | tar -x -C ./config

⁠What you get

PathPurpose
docker-compose.ymlProduction-hardened single-MTA deployment (env-driven)
.env.exampleThe two settings you must choose: image tag, hostname
config/Your Postfix configuration (seeded on first start, then yours)
examples/relay.compose.ymlMinimal outbound relay (smarthost)
examples/mx-dovecot-sasl.compose.ymlMX + Dovecot SASL for authenticated submission (587)
examples/rspamd-milter.compose.ymlMX + Rspamd spam filtering (fail-closed milter)
docs/CONFIGURATION.mdFull configuration reference: layers, templates, TLS, SASL, lookup tables
docs/OPERATIONS.mdRunbook: go-live checklist, runtime security spec, -debug variants, maintenance contract, upgrades/rollback, troubleshooting
SECURITY.mdVulnerability reporting, CVE handling policy, rebuild SLA
CHANGELOG.mdRelease notes per image revision

⁠Image tags

TagMeaningUse
3.11.6-r2Immutable build, never overwrittenProduction
3.11.6Latest rebuild of that patch (moves on dependency updates)Patch-pinned
3.11Latest patch of the lineLine tracking
stable, latestCurrent stable lineEvaluation
3.11.6-r2-debug, 3.11-debug, debugSame rootfs + busybox shell (distroless :debug base)Incident diagnosis only

Published lines: 3.11 (stable), 3.10, 3.9, 3.8 (legacy). Every upstream release and every dependency update (OpenSSL, …) is rebuilt, passed through the full test pyramid (unit + 43 integration + 18 E2E/chaos assertions on both architectures), scanned (Trivy, blocking on fixable CRITICAL/HIGH) and published automatically.

Base image: gcr.io/distroless/cc-debian12 (Google distroless, digest-pinned in the build). The C runtime (glibc, libssl carried by the image) comes from Debian 12 packages, rebuilt into a new -rN revision as soon as Debian ships a security update — patching is owned by this pipeline, not by waiting for a base-image refresh.

⁠Operations cheat sheet

ActionCommand
Queue status / flushdocker exec postfix /usr/sbin/postqueue -p · -f
Effective configurationdocker exec postfix /usr/sbin/postconf -n
Test a lookup tabledocker exec postfix /usr/sbin/postmap -q KEY type:/etc/postfix/file
Reload configurationdocker kill -s HUP postfix
Graceful stopdocker stop --timeout 30 postfix (exit 0)
Logsdocker logs postfix

There is no shell in the image: docker exec works with absolute binary paths only.

Full references: docs/CONFIGURATION.md⁠ · docs/OPERATIONS.md⁠ · SECURITY.md⁠ · CHANGELOG.md⁠

Tag summary

Content type

Image

Digest

sha256:2d48cff26…

Size

22.1 MB

Last updated

about 2 months ago

docker pull euca01/postfix-distroless