Three apps were instanceable and the rest were silent, so the feature looked far narrower than it is. Every app has now been checked against the two rules instance_create.sh enforces, and the answer recorded in its config rather than left unset. 32 apps are instance-safe and now say so. Six are not, and each says why in its own words instead of being indistinguishable from an app nobody had reviewed: pihole a DNS server must own port 53 unbound a resolver must own its fixed 5335 stalwart a mail server must own 25/465/587/993 traefik must own 443, and one Traefik routes every other app prometheus node-exporter and cadvisor carry no "prometheus" prefix stoat pins 7881, and database/redis/rabbit/minio carry no prefix The first four are genuinely one-per-host: the port is not arbitrary, it is the protocol. The last two are compose-identity problems and could be fixed by prefixing those service names, which is a change to make deliberately rather than in passing. Recorded as an explicit false with a reason, not left unset, so the next person reads a decision instead of an absence. The audit was verified not to pass anything vacuously: every app resolves at least one service name, so no app reached "eligible" merely because nothing was found to check. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
176 lines
10 KiB
Plaintext
176 lines
10 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
|
|
# VERSION = the Stalwart release line this install tracks; drives the image tag.
|
|
# The two settings do different jobs and are safe together:
|
|
# UPDATE_TYPE=auto picks up REBUILDS of the version below (security/bug
|
|
# patches) — snapshot, pull, recreate. Your data volume is untouched;
|
|
# nothing is reinstalled.
|
|
# Changing VERSION is how you move BETWEEN releases (v0.16 -> v0.17).
|
|
# So patches land on their own, while a version jump stays a decision you
|
|
# make — which matters while Stalwart is pre-1.0 and still settling its
|
|
# storage schema.
|
|
# 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
|
|
# MULTI_INSTANCE = if true, this app can run as multiple isolated instances
|
|
# (own data/DB/subdomain/backups) via `libreportal instance create`. Only set on
|
|
# apps whose compose identity (container_name, Traefik routers, backup labels)
|
|
# is instance-safe — see scripts/instance/instance_create.sh.
|
|
# Not instance-safe. A mail server must own the SMTP/IMAP ports (25, 465, 587, 993); a second copy could not bind them.
|
|
CFG_STALWART_MULTI_INSTANCE=false
|
|
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=auto
|
|
CFG_STALWART_VERSION=v0.16
|
|
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="An all-in-one mail and collaboration server — SMTP, IMAP, POP3 and JMAP plus calendars and contacts, in a single container"
|
|
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
|
|
#
|
|
# MODE = who this mail server is for. This is the single most consequential
|
|
# setting on the app, so it is worth reading before changing.
|
|
#
|
|
# private — mail stays on your own network. Stalwart still gives you
|
|
# mailboxes, IMAP, calendars and contacts, and mail between local
|
|
# accounts works normally. It just does not exchange mail with the
|
|
# internet, so there is no MX, no reverse DNS, no port 25 and no
|
|
# deliverability to worry about. Port 25 is not published at all;
|
|
# the client ports stay bound to the host but are never opened
|
|
# through the firewall.
|
|
#
|
|
# public — a real internet mail server. Needs outbound AND inbound port 25,
|
|
# a matching reverse DNS record set by your VPS provider, and the
|
|
# DNS records the installer prints. Be aware that deliverability is
|
|
# a reputation game as much as a configuration one: a brand-new IP
|
|
# is distrusted by large providers for weeks regardless of how
|
|
# correct your setup is. That part no installer can fix for you.
|
|
#
|
|
# auto — decide at install time: public if Traefik is installed (which in
|
|
# practice means you have a domain pointed here), private if not.
|
|
# The resolved value is written back here, so this reads as a real
|
|
# answer afterwards rather than staying 'auto'.
|
|
#
|
|
# Changing this later is supported — see the "Mail exposure" tool in the WebUI,
|
|
# which flips the setting and reconfigures the server both ways.
|
|
CFG_STALWART_MODE=auto
|
|
#
|
|
# =============================================================================
|
|
# 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|"
|
|
|
|
# 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_ADMIN_USER=admin
|
|
CFG_STALWART_ADMIN_PASSWORD_1=RANDOMIZEDPASSWORD1
|
|
#
|
|
# =============================================================================
|
|
# AUTOMATIC SETUP
|
|
# =============================================================================
|
|
# Out of the box Stalwart opens a five-screen setup wizard on first sign-in and
|
|
# waits for a human. LibrePortal already knows the answers that matter — the
|
|
# hostname and the domain — so the installer fills the wizard in instead, and
|
|
# the user's first sight of Stalwart is a configured mail server.
|
|
#
|
|
# CLI_VERSION = the version of the Stalwart CLI used to apply that setup.
|
|
# Pinned, not ':latest', for the same reason the server image is: this writes
|
|
# configuration, so an unattended jump to a new CLI is not something to
|
|
# discover during an install. The CLI is a separate upstream project from the
|
|
# server and is NOT included in the server image, which is why it is a
|
|
# container of its own rather than something bundled.
|
|
CFG_STALWART_CLI_VERSION=1.0.12
|
|
#
|
|
# FIRST_MAILBOX = local part of one real mailbox created during setup.
|
|
# Setup leaves you with admin@<domain>, which is an administrator account
|
|
# rather than somewhere to read mail. 'postmaster' is the default for a
|
|
# concrete reason: the generated zone file points DMARC and TLS-RPT reports at
|
|
# postmaster@<domain>, and if nothing creates it those reports bounce.
|
|
# Set empty to skip creating it.
|
|
CFG_STALWART_FIRST_MAILBOX=postmaster
|
|
CFG_STALWART_FIRST_MAILBOX_PASSWORD_1=RANDOMIZEDPASSWORD2
|
|
#
|
|
# DNS_PROVIDER = 'manual', or a provider name to let Stalwart publish DNS itself.
|
|
# On 'manual' the installer prints the full record set — including the real
|
|
# DKIM public keys — for you to paste at your registrar.
|
|
# Given a provider, Stalwart writes MX, SPF, DKIM, DMARC, MTA-STS, TLS-RPT,
|
|
# SRV and CAA into the zone through the provider's API and keeps them in sync.
|
|
# That also makes DKIM key rotation safe to leave switched on, since the server
|
|
# republishes the records itself — hand-managed DKIM keys are, in practice,
|
|
# keys nobody ever rotates.
|
|
#
|
|
# Wired up here: Cloudflare, DigitalOcean, DeSEC (token-only providers).
|
|
# Route 53 and Google Cloud DNS need more than a token — set those up in the
|
|
# admin console instead.
|
|
#
|
|
# The trade: the token is stored in the mail server's database and can write to
|
|
# your zone, so compromising this box means compromising your DNS. Scope the
|
|
# token to this one zone if your provider allows it.
|
|
CFG_STALWART_DNS_PROVIDER=manual
|
|
CFG_STALWART_DNS_API_TOKEN=
|