Files
computer-playbook/roles/web-app-mailu/templates/env.j2
kevinveenbirkenbachandClaude Opus 5.5 c4d0283300 feat(mail): publish a DMARC aggregate report address (rua)
Both mail providers published "v=DMARC1; p=reject; ruf=...; adkim=s;
aspf=s" without a rua tag, so the domain owner received no aggregate
reports and could not see who sends in the domain's name or whether
legitimate mail fails alignment.

services.<entity>.dmarc.rua_user in web-app-stalwart and web-app-mailu
now names the users-catalogue key whose mailbox receives the aggregate
reports. It is set to administrator, the one user every deployment
provisions with a mailbox (user-administrator), and an inventory may
name another key. The address is built as <username>@<mail domain>,
which is the exact account or alias the provider creates, so the record
never points at an address the server does not serve. An assert in the
DNS task fails the deploy before any record is written when the user
carries no mailbox account (Stalwart), or neither a mailbox account nor
a forward alias (Mailu), so reports cannot bounce. Mailu's DMARC_RUA
env, which only feeds the record its admin UI suggests, now carries the
same local part instead of the unprovisioned "admin".

production_facts.py takes a required --dmarc-rua. check_dmarc parses
the record's tags and fails unless rua names that mailbox (size
suffixes and several URIs are accepted). The policy check now reads the
p tag instead of matching the substring "p=", which "sp=" also matched.

Closes #1125

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:56:40 +01:00

65 lines
2.7 KiB
Django/Jinja

{% include 'roles/sys-svc-container/templates/env.j2' %}
LD_PRELOAD=
SECRET_KEY={{ MAILU_SECRET_KEY }}
SUBNET={{ MAILU_SUBNET }}
DOMAIN={{ MAILU_DOMAIN }}
HOSTNAMES={{ MAILU_CANONICAL_HOST }}
POSTMASTER=admin
TLS_FLAVOR={{ MAILU_TLS_FLAVOR }}
PORTS={{ MAILU_PORTS.values() | map('int') | unique | sort | join(',') }}
AUTH_RATELIMIT=10/minute;1000/hour
MESSAGE_RATELIMIT_EXEMPTION={{ lookup('users', 'no-reply').email | lower }}
DISABLE_STATISTICS=True
ADMIN=true
WEBMAIL=roundcube
WEBDAV=radicale
ANTIVIRUS=clamav
MESSAGE_SIZE_LIMIT=50000000
RELAYNETS=
RELAYHOST=
FETCHMAIL_DELAY=600
RECIPIENT_DELIMITER=+
DMARC_RUA={{ MAILU_DMARC_RUA_LOCALPART }}
DMARC_RUF=admin
WELCOME=false
WELCOME_SUBJECT=Welcome to your new email account
WELCOME_BODY=Welcome to your new email account, if you can read this, then it is configured properly!
COMPRESSION=
COMPRESSION_LEVEL=
WEBROOT_REDIRECT=/webmail
WEB_ADMIN=/admin
WEB_WEBMAIL=/webmail
SITENAME=Mailservices
WEBSITE={{ MAILU_WEBSITE }}
LOG_DRIVER=syslog
COMPOSE_PROJECT_NAME=mailu
PASSWORD_SCHEME=BLF-CRYPT
REAL_IP_HEADER=
REAL_IP_FROM=
REJECT_UNLISTED_RECIPIENT=
LOG_LEVEL={{ 'DEBUG' if MODE_DEBUG | bool else 'WARNING' }}
SQLALCHEMY_DATABASE_URI_ROUNDCUBE=mysql://{{ lookup('database', application_id, 'username') }}:{{ lookup('database', application_id, 'password') }}@{{ lookup('database', application_id, 'host') }}/{{ lookup('database', application_id, 'name') }}?collation=utf8mb4_unicode_ci
SQLALCHEMY_DATABASE_URI=mysql+mysqlconnector://{{ lookup('database', application_id, 'username') }}:{{ lookup('database', application_id, 'password') }}@{{ lookup('database', application_id, 'host') }}/{{ lookup('database', application_id, 'name') }}?collation=utf8mb4_unicode_ci
{% set _mailu_redis = lookup('engine', 'redis', application_id) %}
REDIS_ADDRESS={% if _mailu_redis.shared %}{{ _mailu_redis.username }}:{{ _mailu_redis.password }}@{% endif %}{{ _mailu_redis.host }}:{{ _mailu_redis.port }}
API=true
WEB_API=/api
API_TOKEN={{ MAILU_API_TOKEN}}
AUTH_REQUIRE_TOKENS=True
{% if MAILU_OIDC_ENABLED | bool %}
OIDC_ENABLED={{ MAILU_OIDC_ENABLED | string | capitalize }}
OIDC_PROVIDER_INFO_URL={{ OIDC.CLIENT.ISSUER_URL }}
OIDC_CLIENT_ID={{ OIDC.CLIENT.ID }}
OIDC_CLIENT_SECRET={{ OIDC.CLIENT.SECRET }}
OIDC_BUTTON_NAME={{ OIDC.BUTTON_TEXT }}
OIDC_VERIFY_SSL={{ 'False' if (lookup('tls', application_id, 'mode') == 'self_signed') else (lookup('tls', application_id, 'enabled') | ternary('True','False')) }}
OIDC_CHANGE_PASSWORD_REDIRECT_ENABLED=True
OIDC_CHANGE_PASSWORD_REDIRECT_URL={{ OIDC.CLIENT.CHANGE_CREDENTIALS | dotenv_quote }}
{% if MAILU_OIDC_EMAIL_BY_USERNAME_ENABLED | bool %}
OIDC_USERNAME_CLAIM={{ OIDC.ATTRIBUTES.USERNAME }}
OIDC_USER_DOMAIN={{ MAILU_DOMAIN }}
{% endif %}
OIDC_ENABLE_USER_CREATION={{ MAILU_OIDC_ENABLE_USER_CREATION }}
{% endif %}