# Optional anti-spam sidecar for inbound relay (docs/plans/inbound-relay.md). # # SelfPost does not ship or start an anti-spam engine. This fragment brings up # rspamd next to SelfPost and points the inbound smtpd milter at it. Merge it # only when you want filtering on port 25: # # docker compose -f docker-compose.yml -f antispam/docker-compose.antispam.yml up -d # # Requires INBOUND_RELAY_ENABLE=true in .env. The milter sees the real client # IP, HELO and PTR — unlike the upstream, which only sees SelfPost's address. # # The rspamd image is pinned to one build, 4.2.2-0 - "4.2", "4" and "latest" # are rebuilt every night - and it is the build the comments in # antispam/rspamd/ were read against (rspamd 4.2.2, rspamd-docker v4.2.2+0; # 3.11.1-3 until 2.14.4, security audit 2026-10-17, S4); bump it # deliberately, and read them again. Default milter action is fail-open (accept) so a down sidecar # does not block backup-MX. Set INBOUND_ANTISPAM_MILTER_ACTION=tempfail to # defer instead. services: selfpost: environment: INBOUND_RELAY_ENABLE: "${INBOUND_RELAY_ENABLE:-true}" INBOUND_ANTISPAM_MILTER: "${INBOUND_ANTISPAM_MILTER:-inet:antispam:11332}" INBOUND_ANTISPAM_MILTER_ACTION: "${INBOUND_ANTISPAM_MILTER_ACTION:-accept}" depends_on: - antispam antispam: # The milter: rspamd 4.2.2, conf/worker-proxy.inc, "milter = yes" for the # rspamd_proxy worker, bound to *:11332 by antispam/rspamd/worker-proxy.inc # while every other worker stays on loopback (RSPAMD_LOCAL_ADDR below); # it runs as uid 11333 (rspamd-docker v4.2.2+0, Dockerfile, USER # 11333:11333) and needs no capability: it starts unprivileged, binds # ports above 1024 and runs nothing setuid (src/rspamd.c, detect_priv()). image: rspamd/rspamd:4.2.2-0 restart: unless-stopped environment: # Workers on loopback; the proxy alone is put back on every address. RSPAMD_LOCAL_ADDR: localhost security_opt: - no-new-privileges:true cap_drop: - ALL # A ceiling on processes and threads (security audit 2026-10-17, I3). pids_limit: 256 # No host ports: only SelfPost talks to the milter on the compose network. volumes: # The verdict headers SelfPost's inbound journal reads. - ./antispam/rspamd/milter_headers.conf:/etc/rspamd/local.d/milter_headers.conf:ro # The allow and deny lists kept in the panel: the rules, and the files # SelfPost writes them to. - ./antispam/rspamd/multimap.conf:/etc/rspamd/local.d/multimap.conf:ro # The proxy (the milter) on the compose network, nothing else. - ./antispam/rspamd/worker-proxy.inc:/etc/rspamd/local.d/worker-proxy.inc:ro - ./data/antispam:/etc/rspamd/selfpost:ro