Files
computer-playbook/roles/web-app-mailu/vars/main.yml
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

62 lines
4.5 KiB
YAML

---
application_id: "web-app-mailu"
http_port: "{{ lookup('config', application_id, 'services.mailu.ports.local.http') }}"
database_password: "{{ lookup('config', application_id, 'secrets.credentials.database_password') }}"
MAILU_VOLUMES_DIR: "{{ lookup('container', application_id, 'directories.volumes') }}"
MAILU_INSTANCE_DIR: "{{ lookup('container', application_id, 'directories.instance') }}"
MAILU_OVERRIDES_DIR: "{{ [ MAILU_VOLUMES_DIR, 'overrides' ] | path_join }}"
MAILU_CERTS_HOST_DIR: "{{ [ MAILU_VOLUMES_DIR, 'certs' ] | path_join }}"
MAILU_WEBSITE: "{{ lookup('tls', application_id, 'url.base') }}"
MAILU_API_SERVICE_BASE_URL: "http://localhost:8080/api/v1"
MAILU_DOMAIN: "{{ lookup('config', application_id, 'services.mailu.domain') }}"
MAILU_DOMAIN_DNS_ZONE: "{{ MAILU_DOMAIN | to_zone }}"
MAILU_EMAIL: "{{ lookup('email', application_id) }}"
MAILU_HOSTNAME: "{{ MAILU_EMAIL.host }}"
MAILU_CANONICAL_HOST: "{{ lookup('domain', application_id) }}"
MAILU_ACTIVE_PROVIDER: "{{ lookup('mail_provider') == application_id }}"
MAILU_TLS_FLAVOR: "{{ (MAILU_EMAIL.tls and MAILU_ACTIVE_PROVIDER | bool) | ternary('mail', 'notls') }}"
MAILU_HOSTNAME_DNS_ZONE: "{{ MAILU_HOSTNAME | to_zone }}"
MAILU_VERSION: "{{ lookup('config', application_id, 'services.mailu.version') }}"
MAILU_PORTS: "{{ lookup('config', application_id, 'services.mailu.ports.internal') }}"
MAILU_FRONT_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'front') }}"
MAILU_ADMIN_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'admin') }}"
MAILU_IMAP_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'imap') }}"
MAILU_SMTP_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'smtp') }}"
MAILU_OLETOOLS_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'oletools') }}"
MAILU_ANTISPAM_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'antispam') }}"
MAILU_ANTIVIRUS_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'antivirus') }}"
MAILU_WEBDAV_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'webdav') }}"
MAILU_FETCHMAIL_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'fetchmail') }}"
MAILU_WEBMAIL_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'webmail') }}"
MAILU_REDIS_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, 'redis') }}"
MAILU_FRONT_SERVICE: "front"
MAILU_DNS_RESOLVER: "{{ lookup('config', 'svc-dns-unbound', 'networks.local.dns_resolver') }}"
MAILU_SWARM_DB_HOST: "{{ lookup('database', application_id, 'host') }}"
MAILU_SWARM_DB_ENGINE: "{{ lookup('database', application_id, 'type') }}"
MAILU_SWARM_REDIS_HOST: "{{ lookup('engine', 'redis', application_id, 'host') }}"
MAILU_IP4_PUBLIC: "{{ DOCKER_PUBLIC_BIND_HOST }}"
MAILU_SUBNET: "{{ lookup('config', 'web-app-mailu', 'networks.local.subnet') }}"
MAILU_SECRET_KEY: "{{ lookup('config', application_id, 'secrets.credentials.secret_key') }}"
MAILU_API_TOKEN: "{{ lookup('config', application_id, 'secrets.credentials.api_token') }}"
MAILU_OIDC_HOST: "{{ lookup('tls', 'web-app-keycloak', 'domain') }}"
MAILU_OIDC_ONION_ISSUER: "{{ MAILU_OIDC_HOST.endswith('.onion') }}"
MAILU_OIDC_SOCKS_PROXY: "{{ lookup('tor_socks_proxy') if MAILU_OIDC_ONION_ISSUER | bool else '' }}"
MAILU_OIDC_ENABLED: "{{ lookup('config', application_id, 'services.sso.enabled') }}"
MAILU_OIDC_EMAIL_BY_USERNAME_ENABLED: "{{ lookup('config', application_id, 'services.sso.oidc.email_by_username') }}"
MAILU_OIDC_ENABLE_USER_CREATION: "{{ lookup('config', application_id, 'services.sso.oidc.enable_user_creation') | string | capitalize }}"
MAILU_EXTRA_HOSTS: "{{ query('mailu_extra_hosts') }}"
MAILU_USERS: "{{ lookup('mailu_users') }}"
MAILU_DOCKER_FLAVOR: "{{ 'ghcr.io/heviat' if MAILU_OIDC_ENABLED | bool else 'ghcr.io/mailu' }}"
MAILU_DMARC_RUF: "{{ lookup('config', application_id, 'users.administrator.email') }}"
MAILU_DMARC_RUA_USER: "{{ lookup('config', application_id, 'services.mailu.dmarc.rua_user') }}"
MAILU_DMARC_RUA_LOCALPART: "{{ lookup('users', MAILU_DMARC_RUA_USER).username }}"
MAILU_DMARC_RUA: "{{ MAILU_DMARC_RUA_LOCALPART }}@{{ MAILU_DOMAIN }}"
MAILU_DKIM_KEY_FILE: "{{ MAILU_DOMAIN }}.dkim.key"
MAILU_DKIM_KEY_PATH: "/dkim/{{ MAILU_DKIM_KEY_FILE }}"
MAILU_NGINX_HOST_DIR: "{{ [ MAILU_OVERRIDES_DIR, 'nginx' ] | path_join }}"
MAILU_RSPAMD_HOST_DIR: "{{ [ MAILU_OVERRIDES_DIR, 'rspamd' ] | path_join }}"
MAILU_RSPAMD_HOST_FILE: "{{ [ MAILU_RSPAMD_HOST_DIR,'ratelimit.conf' ] | path_join }}"
MAILU_RSPAMD_LIMITS_DEFAULTS:
RATE: "30 / 1min"
BURST: 50