APP_PORT=3025 APP_BASE_URL=https://mailhub.example.com ADMIN_USER=admin ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=change-this-admin-password SESSION_SECRET=change-this-long-random-session-secret # Require administrator approval after a newly registered user verifies their email. REGISTRATION_REQUIRES_APPROVAL=false # Legacy admin send token. New users should generate their own token in the web UI. API_TOKEN=change-this-legacy-api-token SUBMISSION_ENABLED=true SUBMISSION_HOST=smtp.mailhub.example.com SUBMISSION_BIND=0.0.0.0 SUBMISSION_PORTS=25:smtp,587:smtp,465:smtps,2525:smtp SUBMISSION_ALT_PORT=2525 SUBMISSION_ALLOW_INSECURE_AUTH=false SUBMISSION_TLS_CERT=/certs/mailhub.example.com.crt SUBMISSION_TLS_KEY=/certs/mailhub.example.com.key # Optional host directory containing fullchain.pem and privkey.pem. Deploy and scheduled jobs sync it into ./certs. # The sync detects the running app container group, writes cert=0644/key=0640, and verifies container ports 465 and 993. MAILHUB_CERT_SOURCE_DIR= SUBMISSION_USERNAME=change-this-smtp-user SUBMISSION_PASSWORD=change-this-smtp-password # Legacy Node protocol backend only. Docker Compose always exposes Dovecot on # 143/993 and 110/995; use IMAP_BIND/POP3_BIND or a Compose override/firewall # when either public protocol must be restricted. IMAP_ENABLED=true IMAP_BIND=0.0.0.0 IMAP_PORTS=143:imap,993:imaps POP3_ENABLED=true POP3_BIND=0.0.0.0 POP3_PORTS=110:pop3,995:pop3s MAIL_ACCESS_ALLOW_INSECURE_AUTH=false # Docker deployments delegate IMAP/POP3 to Dovecot. The authentication bridge # is available only on the private Compose network and uses a generated secret. MAIL_ACCESS_BACKEND=dovecot DOVECOT_AUTH_ENABLED=true DOVECOT_AUTH_HOST=0.0.0.0 DOVECOT_AUTH_PORT=3001 DOVECOT_AUTH_SECRET_FILE=/run/secrets/dovecot_auth_secret # Low-resource hosts should keep CPU-bound password verification concurrency modest. UV_THREADPOOL_SIZE=2 # Relative path for host-side migration commands. Compose overrides this with /data/maildir. MAILDIR_ROOT=./data/maildir MAILDIR_SYNC_INTERVAL_MS=300000 # Optional Roundcube one-click login. The browser receives only a single-use # POST ticket; Roundcube exchanges it over the private network for an expiring # mhw_ credential. Generate a separate hexadecimal secret at # ./data/secrets/webmail_sso_secret and expose it read-only to Roundcube. WEBMAIL_SSO_URL= WEBMAIL_SSO_SECRET_FILE=./data/secrets/webmail_sso_secret # Host-side reader gid for a same-host Roundcube PHP worker. Debian/Apache # images commonly use www-data gid 33. Leave 1000 when no external reader exists. WEBMAIL_SSO_READER_GID=1000 WEBMAIL_SSO_TICKET_TTL_SECONDS=60 WEBMAIL_SSO_CREDENTIAL_TTL_SECONDS=43200 # Outbound hostname is authorized through the SPF a: mechanism and used for HELO/Postfix. # The sending IP drives the managed A record and PTR health check, not a direct SPF ip4 entry. MAIL_HOSTNAME=smtp.mailhub.example.com SENDING_IP=203.0.113.10 # Extra SPF mechanisms to preserve coexistence with third-party senders. # Examples: include:spf.mailjet.com include:_netblocks.m.feishu.cn DEFAULT_SPF_MECHANISMS= DNS_RESOLVERS=1.1.1.1,8.8.8.8 DNS_AUTO_CHECK_ENABLED=true DNS_AUTO_CHECK_INTERVAL_MS=60000 DNS_AUTO_CHECK_LIMIT=25 # SMTP service used by the web API. In docker-compose this is the internal Postfix service. SMTP_HOST=postfix SMTP_PORT=25 SMTP_HELO=smtp.mailhub.example.com SEND_REQUIRES_VERIFIED=false DELIVERY_TRACKING_ENABLED=true POSTFIX_LOG_POLL_INTERVAL_MS=5000 # Engagement tracking uses opaque public links and a stable encryption key. TRACKING_SECRET=change-this-separate-long-random-tracking-secret ENGAGEMENT_TRACKING_ENABLED=false TRACKING_RETENTION_DAYS=180 TRUST_PROXY=true # Optional deliverability headers. One-click should only be enabled when the URL accepts compliant unsubscribe POSTs. LIST_UNSUBSCRIBE_MAILTO= LIST_UNSUBSCRIBE_URL= LIST_UNSUBSCRIBE_POST_ENABLED=false FEEDBACK_ID_ENABLED=true REPORT_ABUSE_TO= CSA_COMPLAINTS_TO= # Optional bounce envelope sender. Keep disabled until this mailbox/domain receives and processes bounces. BOUNCE_ADDRESS= BOUNCE_ENVELOPE_ENABLED=false # DMARC defaults. DMARC_POLICY=none DMARC_RUA=