One container providing SMTP/IMAP/POP3/JMAP plus CalDAV/CardDAV, an admin UI and spam filtering — chosen over mailcow (owns its own installer, which is what killed the earlier attempt now sitting in scripts/unused/) and over Mailu (~7 containers) because a single image with a single data dir is the only shape that fits the existing conventions cleanly: one anchor service the updater can version, one path the backup engine can snapshot. Mail-specific departures from the usual app template, each deliberate: * Ports are FIXED, not random. Other mail servers connect to :25 by number and clients expect 465/587/993 — a randomised external port would silently make the server unreachable. Only the admin UI takes a random port, since that one really is just a browser behind Traefik. 143/995/4190/443 ship disabled; the port processor comments them out. * UPDATE_TYPE=manual and the image pinned to v0.16, not :latest. Stalwart is pre-1.0 and has said the storage schema is still being finalised, so an unattended minor bump could carry a data migration on the message store. This is the one app where the auto default is wrong. * BACKUP_STRATEGY=stop-snapshot-start. The message store is written continuously; a live copy can land mid-transaction. Seconds of queued delivery (senders retry) buys a consistent snapshot. * The install hook checks outbound port 25 and reverse DNS, then prints the MX/SPF/DMARC records with real values. A mail server whose container started is not a working mail server, and every remaining requirement lives at the registrar or the VPS provider. Admin credentials are seeded via STALWART_RECOVERY_ADMIN from the app config rather than left to Stalwart's first-run random password, which would otherwise exist only in the container log. Icon is a drawn placeholder, not the upstream trademark. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
91 lines
5.6 KiB
Plaintext
91 lines
5.6 KiB
Plaintext
#
|
|
# =============================================================================
|
|
# GENERAL CONFIGURATION
|
|
# =============================================================================
|
|
# APP_NAME = name of application for use in scripts
|
|
# COMPOSE_FILE = default for no app_name in docker-compose file name, app if there is
|
|
# BACKUP = if true, include this application in backup operations
|
|
# UPDATE_TYPE = auto: new image builds are applied automatically (a recovery snapshot is taken first), manual: only when you press Update
|
|
# HEALTHCHECK = if true, default docker health checks for that container will be enabled
|
|
# AUTHELIA = if true, use Authelia authentication, if false turned off.
|
|
# HEADSCALE = options : false, local, remote (see general config). e.g false or local,remote
|
|
#
|
|
CFG_STALWART_APP_NAME=stalwart
|
|
CFG_STALWART_BACKUP=true
|
|
# Mail is the one app where a "live" snapshot is a real risk: the message store
|
|
# is being written continuously, so a copy taken mid-write can land mid-transaction.
|
|
# stop-snapshot-start costs seconds of queued delivery (senders retry — that is
|
|
# what SMTP does) and buys a consistent store.
|
|
CFG_STALWART_BACKUP_STRATEGY=stop-snapshot-start
|
|
CFG_STALWART_UPDATE_TYPE=manual
|
|
CFG_STALWART_COMPOSE_FILE=default
|
|
CFG_STALWART_HEALTHCHECK=true
|
|
CFG_STALWART_AUTHELIA=false
|
|
CFG_STALWART_HEADSCALE=false
|
|
#
|
|
# =============================================================================
|
|
# METADATA
|
|
# =============================================================================
|
|
# CATEGORY = application category for grouping
|
|
# TITLE = display name for the application
|
|
# DESCRIPTION = short description of the application
|
|
# LONG_DESCRIPTION = detailed description of the application
|
|
# URL = source repository or documentation URL
|
|
# ACTIONS = available actions for this application
|
|
#
|
|
CFG_STALWART_CATEGORY="communication"
|
|
CFG_STALWART_TITLE="Stalwart"
|
|
CFG_STALWART_DESCRIPTION="Mail Server"
|
|
CFG_STALWART_LONG_DESCRIPTION="Stalwart is an all-in-one mail and collaboration server — SMTP, IMAP, POP3 and JMAP plus calendars and contacts, in a single container with a built-in admin interface and spam filtering."
|
|
CFG_STALWART_URL="https://github.com/stalwartlabs/stalwart"
|
|
CFG_STALWART_ACTIONS="configure|install|restart|shutdown|uninstall"
|
|
#
|
|
# =============================================================================
|
|
# NETWORK CONFIGURATION
|
|
# =============================================================================
|
|
# DOMAIN = number of domain from the general config, useful when using multiple domains
|
|
# WHITELIST = if true only allow whitelisted ips (see general config), if false allow all
|
|
#
|
|
CFG_STALWART_DOMAIN=1
|
|
CFG_STALWART_WHITELIST=false
|
|
CFG_STALWART_NETWORK=default
|
|
#
|
|
# =============================================================================
|
|
# PORT CONFIGURATION
|
|
# =============================================================================
|
|
# PORT_ = port configuration: app|name|external:internal|access|protocol|login|traefik|webui|description|paths|subdomain
|
|
# - app: application name
|
|
# - name: service identifier (webui, dns, ssh, etc.)
|
|
# - external:internal: port mapping (external can be 'random' for auto-allocation)
|
|
# - access: 'public' (internet accessible), 'private' (local network only), 'disabled' (not running)
|
|
# - protocol: 'tcp' or 'udp'
|
|
# - login: if true, this port requires basic-auth via Traefik (only meaningful when traefik=true)
|
|
# - traefik: if true, Traefik handles this port (reverse proxy)
|
|
# - webui: if true, this port serves the main web interface
|
|
# - description: human-readable description of the service
|
|
#
|
|
# MAIL PORTS ARE FIXED, NOT RANDOM. Every other app can take a random external
|
|
# port because only a browser (via Traefik) reaches it. Mail is different: other
|
|
# mail servers on the internet connect to port 25 by number, and mail clients
|
|
# expect 465/587/993 — a randomised external port silently makes the server
|
|
# unreachable. Only the admin UI gets a random port, because that one IS just a
|
|
# browser behind Traefik.
|
|
CFG_STALWART_PORT_1="stalwart-service|webui|random:8080|public|tcp|false|true|true|Admin Interface||mail"
|
|
CFG_STALWART_PORT_2="stalwart-service|smtp|25:25|public|tcp|false|false|false|SMTP (server-to-server mail delivery)|"
|
|
CFG_STALWART_PORT_3="stalwart-service|submissions|465:465|public|tcp|false|false|false|Mail submission (implicit TLS)|"
|
|
CFG_STALWART_PORT_4="stalwart-service|submission|587:587|public|tcp|false|false|false|Mail submission (STARTTLS)|"
|
|
CFG_STALWART_PORT_5="stalwart-service|imaps|993:993|public|tcp|false|false|false|IMAP (implicit TLS)|"
|
|
CFG_STALWART_PORT_6="stalwart-service|imap|143:143|disabled|tcp|false|false|false|IMAP (STARTTLS) — enable only if a client needs it|"
|
|
CFG_STALWART_PORT_7="stalwart-service|pop3s|995:995|disabled|tcp|false|false|false|POP3 (implicit TLS) — off by default, IMAP is preferred|"
|
|
CFG_STALWART_PORT_8="stalwart-service|sieve|4190:4190|disabled|tcp|false|false|false|ManageSieve (client-managed mail filters)|"
|
|
CFG_STALWART_PORT_9="stalwart-service|jmap|443:443|disabled|tcp|false|false|false|HTTPS/JMAP direct — leave disabled when Traefik fronts the UI|"
|
|
|
|
# AUTH_PROFILE = capability tier for the WebUI auth tools (single_password | user_password | multi_user)
|
|
# The password reaches the container through a compose environment variable, so
|
|
# if you replace the generated one by hand keep it alphanumeric: docker compose
|
|
# interpolates `$` and YAML treats ` #` as a comment, either of which would
|
|
# silently mangle the value. The generator only emits letters and digits.
|
|
CFG_STALWART_AUTH_PROFILE=user_password
|
|
CFG_STALWART_ADMIN_USER=admin
|
|
CFG_STALWART_ADMIN_PASSWORD=RANDOMIZEDPASSWORD1
|