--- # nocheck: seaweedfs-required — object storage not implemented for this role sso: bond: 1 enabled: "{{ 'web-app-keycloak' in group_names }}" shared: "{{ 'web-app-keycloak' in group_names }}" flavor: oidc oidc: email_by_username: true enable_user_creation: true logout: bond: 1 enabled: "{{ 'web-svc-logout' in group_names }}" shared: "{{ 'web-svc-logout' in group_names }}" dashboard: bond: 1 enabled: "{{ 'web-app-dashboard' in group_names }}" shared: "{{ 'web-app-dashboard' in group_names }}" matomo: bond: 1 enabled: "{{ 'web-app-matomo' in group_names }}" shared: "{{ 'web-app-matomo' in group_names }}" # nocheck: dynamic-flag email: bond: 1 enabled: "{{ MAIL_PROVIDER in group_names }}" shared: "{{ MAIL_PROVIDER in group_names }}" # nocheck: playwright-service-flag — self-provider mailu: modes: compose: enabled: true swarm: enabled: true bond: 1 # nocheck: default-placement-manager mail edge at a known IP: MX A-record, PTR and SPF bind inbound/outbound SMTP to the stack host IP (a floating task's egress IP breaks deliverability); postfix /queue and dovecot mail+index state are NFS-hostile and ARE the app (no central-service equivalent); cert renewals land in a node-local bind via a manager-side systemd timer placement: manager enabled: true # nocheck: dynamic-flag shared: true covers: - email # nocheck: unwatched-version Reason: Mailu ships its images under the release-series tag while its git tags are patch level (2024.06.58), so the series is the pin and moves only on a deliberate migration version: "2024.06" name: mailu backup: project_hard_restart: true min_storage: 20GB domain: "{{ lookup('email').domain }}" dmarc: rua_user: administrator ports: local: http: 8007 public: smtp: 25 smtps: 465 submission: 587 pop3: 110 pop3s: 995 imap: 143 imaps: 993 sieve: 4190 internal: http: 80 smtp: 25 smtps: 465 submission: 587 pop3: 110 pop3s: 995 imap: 143 imaps: 993 sieve: 4190 onion: smtp: true submission: true imap: true pop3: true # nocheck: onion-flag ManageSieve edits server-side filters, which is administration rather than the sending and receiving the onion transport is for sieve: false proxy: service_key: front run_after: - web-app-matomo - web-app-stalwart lifecycle: eol cpus: "1.0" mem_reservation: 512m mem_limit: 2g pids_limit: 1024 # nocheck: shared # nocheck: dynamic-flag # nocheck: playwright-service-flag — DB engine, covered by role-local integration tests redis: bond: 1 name: mailu-redis backup: disabled: true enabled: true # nocheck: dynamic-flag # Exception: central redis overlay adds VIP pressure on manager-pinned mailu; embedded redis avoids it. shared: "{{ ('svc-db-redis' in group_names) and (DEPLOYMENT_MODE == 'compose') }}" cpus: "0.2" mem_reservation: 256m mem_limit: 512m pids_limit: 256 # nocheck: playwright-service-flag - central DNS resolver, infrastructural (no Playwright surface) # nocheck: dynamic-flag enabled+shared (not the `in group_names` form) marks svc-dns-unbound `required` so the loader deploys it every compose round; reverting reintroduces the admin DNS hang. unbound: bond: 1 enabled: "{{ DEPLOYMENT_MODE == 'compose' }}" shared: true # nocheck: playwright-service-flag — DB engine, covered by role-local integration tests mariadb: bond: 1 enabled: true # nocheck: dynamic-flag shared: "{{ 'svc-db-mariadb' in group_names }}" cpus: "0.8" mem_reservation: 1g mem_limit: 2g pids_limit: 512 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component admin: name: mailu-admin enabled: true # nocheck: dynamic-flag shared: false cpus: "0.3" mem_reservation: 256m mem_limit: 2g pids_limit: 512 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component imap: name: mailu-imap enabled: true # nocheck: dynamic-flag shared: false cpus: "0.5" mem_reservation: 512m mem_limit: 1.5g pids_limit: 512 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component smtp: name: mailu-smtp enabled: true # nocheck: dynamic-flag shared: false cpus: "0.5" mem_reservation: 512m mem_limit: 1.5g pids_limit: 512 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component antispam: name: mailu-antispam enabled: true # nocheck: dynamic-flag shared: false cpus: "0.6" mem_reservation: 512m mem_limit: 1.5g pids_limit: 512 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component antivirus: name: mailu-antivirus enabled: true # nocheck: dynamic-flag shared: false image: clamav/clamav-debian version: 1.5.4 cpus: "0.6" mem_reservation: 2g mem_limit: 3g pids_limit: 512 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component oletools: name: mailu-oletools enabled: true # nocheck: dynamic-flag shared: false cpus: "0.2" mem_reservation: 256m mem_limit: 512m pids_limit: 256 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component webdav: name: mailu-webdav enabled: true # nocheck: dynamic-flag shared: false cpus: "0.2" mem_reservation: 256m mem_limit: 512m pids_limit: 256 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component fetchmail: name: mailu-fetchmail enabled: true # nocheck: dynamic-flag shared: false cpus: "0.2" mem_reservation: 256m mem_limit: 512m pids_limit: 256 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component webmail: name: mailu-webmail enabled: true # nocheck: dynamic-flag shared: false cpus: "0.3" mem_reservation: 256m mem_limit: 1g pids_limit: 512 # nocheck: dynamic-flag # nocheck: playwright-service-flag — internal sub-component front: name: mailu-front enabled: true # nocheck: dynamic-flag shared: false cpus: "0.3" mem_reservation: 256m mem_limit: 1g pids_limit: 512 # nocheck: playwright-service-flag — verified by web-svc-css provider spec css: bond: 1 enabled: "{{ 'web-svc-css' in group_names }}" shared: "{{ 'web-svc-css' in group_names }}" prometheus: bond: 1 enabled: "{{ 'web-app-prometheus' in group_names }}" shared: "{{ 'web-app-prometheus' in group_names }}" # nocheck: playwright-service-flag # nocheck: variants-coverage — sso-variant-tor requires the onion on in every variant, so the false polarity has no variant left to live in tor: bond: 0.5 enabled: "{{ 'svc-net-tor' in group_names }}" shared: true # nocheck: dynamic-flag # nocheck: dynamic-flag # nocheck: playwright-service-flag, dynamic-flag infrastructure backup consumer container_backup: # nocheck: bond-baseline backup host joins outside the variant topology bond: 1 enabled: "{{ 'svc-bkp-volume-2-local' in group_names }}" shared: true