Rspamd image on Debian Trixie with opinionated defaults and env-var wiring
50K+
A production-ready Rspamd container image built on the official
rspamd/rspamd image, with an opinionated default configuration, runtime env-var wiring, and
optional integration with a range of external spam-fighting services.
The container runs as the unprivileged user 11333 (_rspamd).
/data)| Port | Protocol | Purpose |
|---|---|---|
| 11332 | TCP | Milter protocol (Postfix/Dovecot integration) |
| 11333 | TCP | Normal worker — spam scanning endpoint |
| 11334 | TCP | Controller / Web UI |
| 11335 | UDP/TCP | Fuzzy storage |
docker run -d \
--name rspamd \
-p 11332:11332 \
-p 11333:11333 \
-p 11334:11334 \
-e REDIS=redis:6379 \
-e RSPAMD_PASS=changeme \
ricariel/rspamd
The generated web-UI password is printed to stdout on first start (when no
worker-controller.inc exists yet). Open http://<host>:11334 to access the
dashboard.
The following thresholds are baked into the image (conf/local.d/actions.conf):
| Action | Score | Effect |
|---|---|---|
greylist | 4 | Soft-reject; legitimate servers retry |
add_header | 6 | Adds X-Spam header |
rewrite_subject | 7 | Prepends ***SPAM*** to subject |
reject | 15 | Message is rejected outright |
No single signal should reach 15 on its own (except explicit hard-blocks like country blocks or filename blocks). The design goal is 2 to 3 moderate hits combining to cross the threshold.
Default-module RBLs — handled by Rspamd's built-in rbl module, scored via
conf/local.d/rbl_group.conf using the module's own symbol names:
| List | Symbols | Notes |
|---|---|---|
| Spamhaus ZEN (SBL/XBL/PBL) | RCVD_IN_ZEN_BLOCKED_OPENDNS, … | IP reputation |
| Spamhaus DBL | URIBL_SBL_CSS, DBL_SPAM, … | Domain reputation |
| MailSpike | RBL_MAILSPIKE_WORST (+7), RWL_MAILSPIKE_EXCELLENT (−2) | IP reputation + whitelist |
| DNSWL | RCVD_IN_DNSWL_HI (−2), RCVD_IN_DNSWL_MED (−1) | Negative score for good senders |
| SpamEatingMonkey | SEM_FRESH15, SEM_URIBL | Domain freshness + reputation |
Custom RBLs — defined in conf/local.d/rbl.conf, scored in conf/local.d/rbl_group.conf:
| List | Symbol | Score | Notes |
|---|---|---|---|
| InterServer IP | RBL_INTERSERVER | +4 | IP blocklist |
| InterServer SA | RBLSA_INTERSERVER | +2 | Broader SA-level block |
| InterServer Good | RBLGOOD_INTERSERVER | −0.5 | IP whitelist |
| InterServer URI | INTERSERVER_RULE_URIBL_RBLINT | +4 | Domain/URI blocklist |
| URLhaus (active) | URLHAUS_URIBL_ACTIVE | +7 | abuse.ch live malware URLs |
| URLhaus (offline) | URLHAUS_URIBL_OFFLINE | +2 | Recently removed entries |
| MailBaby DQS Email | MAILBABY_DQS_EMAIL | +6 | E-mail address hash RBL |
Optional: mount /data/local.d/custom/dqs-rbl.conf to enable the paid Spamhaus DQS feed.
Beyond RBLs, the image enables and configures several additional Rspamd modules:
| Module | Config file | Purpose |
|---|---|---|
| MX Check | mx_check.conf | Verifies that the sender domain has a working MX record. Domains with no MX are greylisted (greylist_invalid = true). |
| URL Redirector | url_redirector.conf | Follows redirect chains (bit.ly, tracking URLs, etc.) before checking against URI blocklists. redirectors_only = false means any redirect is followed, not just known shorteners. |
| Phishing | phishing.conf | PhishTank (via rspamd.com proxy) + OpenPhish public feed for URL reputation. |
| Known Senders | known_senders.conf | Tracks domains with large legitimate sender populations (e.g. Gmail, Outlook) to reduce false positives. |
| HTTP Headers | http_headers.conf | Scores based on suspicious or missing HTTP-related headers. |
| Replies | replies.conf | Marks replies to outbound mail with action = "no action" — your own replies are never rejected. |
| Greylisting | greylist.conf | Major mail providers (Gmail, Outlook, GMX, Yahoo, Mailchimp, Sendgrid, etc.) are exempt from greylisting via greylist-whitelist-domains.inc since they do not always retry from the same IP. |
Notable composite rules (composites.conf):
| Symbol | Expression | Score | Purpose |
|---|---|---|---|
SUSPICIOUS_DIRECT_DELIVERY | ONCE_RECEIVED_STRICT & MISSING_MID & !WHITELISTED_FWD_HOST | +4.0 | Single-hop delivery with no Message-ID — typical spam MO |
RELAY_DENIED | NON_LOCAL_RCPT & NON_LOCAL_IP | +20.0 | Open relay attempt |
FREEMAIL_POLICY_FAILURE | FREEMAIL_FROM & !DMARC_POLICY_ALLOW | +16.0 | Freemail sender with broken DMARC policy |
All variables are optional unless marked required. The entrypoint re-generates affected config files from scratch on every container start, so every restart is fully idempotent.
| Variable | Default | Description |
|---|---|---|
REDIS | — | Redis connection string, e.g. redis:6379. Enables history, greylist, ratelimit, DMARC stats, neural network, and more. Strongly recommended. |
RSPAMD_PASS | random | Password for the web UI / controller socket. A random password is generated and logged on first start if omitted. Accepts either a plain-text string or a pre-hashed value (starting with $). |
SECURE_IP | 127.0.0.1 | IP that is allowed to call the controller without a password (e.g. a trusted proxy). |
DNS | — | Hostname of a custom DNS resolver. It is resolved and written to local_dns.inc as the primary nameserver, with a public resolver as fallback. The entrypoint then blocks until the resolver answers a test query. |
WAITFOR | — | Space-separated list of tcp://host:port targets to wait for before startup (uses dockerize). E.g. tcp://redis:6379 tcp://clamav:3310. |
CONTROLIP, DNSSEC and NOGREY are printed by the entrypoint at startup but
are not wired to any configuration. Setting them has no effect. Disable
greylisting through a mounted /data/local.d/greylist.conf instead.
Each service runs as a separate sidecar container. Set the variable to the container's hostname (the port is fixed per service).
| Variable | Port | Service | Description |
|---|---|---|---|
CLAMAV | 3310 | ClamAV | Virus scanning with custom pattern matching. Configured with patterns for common malware families, phishing, PUA, and macro-based threats. |
VIRUSTOTAL | — | VirusTotal | Set to your API key. Submits attachments to VirusTotal. Triggers when ≥ 3 engines flag a file, rejects when ≥ 7. |
OLEFY | 10050 | Olefy | Python sidecar running oletools. Scans Office documents for macros, IOCs, obfuscated VBA, and malware. |
DCCIFD | 10045 | DCC | Distributed Checksum Clearinghouse — bulk-mail detection via hash comparison. |
RAZORFY | 11342 | Razorfy | Sidecar exposing Razor2, a collaborative spam-digest network. |
PYZOR | 24441 | Pyzor | Sidecar running Pyzor, another collaborative spam-digest service (complements Razor). |
GOOGLE_API_KEY | — | Google Safe Browsing | Set to your API key to enable URL reputation checks against Google Safe Browsing. |
BAZAAR | — | abuse.ch MalwareBazaar | Set to any non-empty value. Downloads the full MD5 hash list from MalwareBazaar every 12 h and uses it for fuzzy attachment matching. |
All feeds are handled by a single background process, update_daemon.sh, started
by the entrypoint when at least one feed is enabled. It runs every enabled feed
once at startup and then every 12 hours.
Each feed compares the remote ETag against the one stored from the last
successful download and skips the transfer when nothing changed, so the interval
costs a HEAD request per feed rather than a full download.
| Variable | Description |
|---|---|
HEINLEIN | Enables Heinlein Support SA rules — a curated SpamAssassin rule set loaded into Rspamd's SA compatibility layer. Also starts an auto-update daemon (every 12 h). |
KAM | Enables KAM.cf — Kevin A. McGrail's community SpamAssassin rules. Updated every 12 h. |
SCHAAL | Enables schaal-it SA rules — German-language rule set. Updated every 12 h. |
BAZAAR | See External Services above — also activates SpamAssassin base rules when combined with HEINLEIN. |
Note:
HEINLEINandBAZAARboth require the SpamAssassin base rule set, which is downloaded once from the Apache mirrors at container start. This adds ~30 s to the initial startup time.
When DMARC_DOMAIN is set, Rspamd collects DMARC statistics (requires REDIS)
and sends daily aggregate reports to domain owners whose mail you process.
| Variable | Default | Description |
|---|---|---|
DMARC_DOMAIN | — | Required to enable reporting. The domain that appears as the report sender (your mail domain). |
DMARC_ORG | $DMARC_DOMAIN | Organization name that appears in the report XML. |
DMARC_REPORT_EMAIL | dmarc-report@$DMARC_DOMAIN | Envelope-from / sender address of the report emails. |
DMARC_SMTP | 127.0.0.1 | SMTP relay to use for sending reports. Typically points to your local Postfix. |
DMARC_SMTP_PORT | 25 | SMTP port of the relay. |
Reports are sent once per day (send_interval = 1d) with up to 1000 entries
per report. The dmarc.conf is regenerated from scratch on every container
start, so changing these variables takes effect on the next restart.
/data)Mount a directory to /data to inject or override any configuration file
without rebuilding the image. The entrypoint symlinks files into the correct
Rspamd config directories at startup.
/data/
├── local.d/ → /etc/rspamd/local.d/ (merged with built-in config)
│ ├── arc.conf # override ARC signing key/selector
│ ├── dkim/ # DKIM private keys (see DKIM Signing)
│ └── maps.d/ # writable map files (greylist, bayes, etc.)
├── override.d/ → /etc/rspamd/override.d/ (replaces built-in config)
└── plugins.d/ → /etc/rspamd/plugins.d/
Files in /data/local.d/ that already exist in the built-in config are
replaced (the original is removed and a symlink is created). A warning is
printed to stdout for each replaced file.
Special handling:
/data/local.d/rspamd.conf.local → linked as /etc/rspamd/rspamd.conf.local/data/local.d/dkim/ → linked as /etc/rspamd/local.d/dkim//data/local.d/maps.d/ → replaces the built-in maps.d/ directoryPlace your private key(s) in /data/local.d/dkim/ and create a
/data/local.d/dkim_signing.conf:
# /data/local.d/dkim_signing.conf
domain {
example.com {
path = "/etc/rspamd/local.d/dkim/example.com.key";
selector = "2024010101";
}
}
The key file must be readable by the _rspamd user inside the container.
Verification is enabled in the base image by default — Rspamd validates incoming ARC chains and can trust forwarded mail (e.g. from mailing lists) even when SPF/DKIM fail for the forwarded copy.
| Symbol | Score | Meaning |
|---|---|---|
ARC_ALLOW | −1.0 | Valid, trusted ARC chain |
ARC_INVALID | +0.5 | Chain present but broken |
ARC_REJECT | +1.5 | Chain explicitly rejected by a prior hop |
ARC_NA | 0.0 | No ARC headers (most direct mail) |
Signing is disabled in the base image (no keys present). To enable it,
mount an arc.conf via /data/local.d/arc.conf:
# /data/local.d/arc.conf
enabled = true;
sign_inbound = true;
allow_envfrom_empty = true;
allow_hdrfrom_mismatch = true;
allow_username_mismatch = true;
path = "/etc/rspamd/local.d/$selector.key";
selector = "20250101001";
try_fallback = true;
use_redis = false;
The key file referenced by path must also be mounted into the container.
The fuzzy storage combines two sources:
fuzzy.rspamd.com:11335) — Rspamd's community hash database127.0.0.1:11335) — your own private fuzzy storageThree local flags are pre-configured:
| Flag | Symbol | Max Score | Purpose |
|---|---|---|---|
| 11 | LOCAL_FUZZY_DENIED | 20.0 | Confirmed spam/malware — learned via spamtrap |
| 12 | LOCAL_FUZZY_PROB | 10.0 | Probable spam |
| 13 | LOCAL_FUZZY_WHITE | 2.0 | Whitelisted hashes |
The spamtrap (spamtrap.conf) automatically learns incoming mail to addresses
listed in /var/lib/rspamd/spamtrap.map into flag 11.
The image ships a large set of multimap rules covering German- and English-language spam categories. Rules are split by language and topic:
| Category | Files |
|---|---|
| Body content | multimap.body.{de,en}.{conf,...} |
| Sender address | multimap.sender.{de,en}.{conf,...} |
| Subject line | multimap.subject.{de,en}.{conf,...} |
| Headers | multimap.header.conf |
| Whitelists | multimap.whitelist.*.conf |
| Phishing URLs | multimap.base.body.href.phishingdb.conf |
Maps are stored under conf/local.d/maps.d/. To add your own entries, mount a
writable maps.d/ directory via /data/local.d/maps.d/.
The rule set in the image comes from
martinschaible/rspamd-rules,
downloaded during the build. Do not edit the _multimap_*.conf files in this
repository to add your own rules — a rebuild replaces them. Put local additions
into mm_fabrice.conf, which multimap.conf includes and the build leaves
alone.
services:
rspamd:
image: ricariel/rspamd:latest
restart: unless-stopped
ports:
- "11332:11332" # milter
- "11333:11333" # scanner
- "11334:11334" # web UI
environment:
REDIS: redis:6379
RSPAMD_PASS: "changeme"
CLAMAV: clamav
OLEFY: olefy
RAZORFY: razorfy
PYZOR: pyzor
BAZAAR: "1"
HEINLEIN: "1"
KAM: "1"
DMARC_DOMAIN: "example.com"
DMARC_SMTP: postfix
WAITFOR: "tcp://redis:6379 tcp://clamav:3310"
volumes:
- /data/rspamd:/data # custom config + DKIM keys
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis-data:/data
clamav:
image: clamav/clamav:stable
restart: unless-stopped
olefy:
image: ghcr.io/heinleincloud/olefy:latest
restart: unless-stopped
razorfy:
image: ghcr.io/heinleincloud/razorfy:latest
restart: unless-stopped
pyzor:
image: ghcr.io/heinleincloud/pyzor:latest # community image
restart: unless-stopped
volumes:
redis-data:
services:
rspamd:
image: ricariel/rspamd:latest
restart: unless-stopped
ports:
- "11333:11333"
- "11334:11334"
environment:
REDIS: redis:6379
volumes:
- /data/rspamd:/data
redis:
image: redis:7-alpine
restart: unless-stopped
git clone https://git.zyria.de/pyrox/rspamd-docker
cd rspamd-docker
docker build -t rspamd-local .
| Component | Source |
|---|---|
| Base image | Official docker.io/rspamd/rspamd, pinned to an exact version |
| Extra packages | razor, ldnsutils, bind9-dnsutils, redis-tools, wget, unzip, procps |
| Multimap rules | Fetched at build time from martinschaible/rspamd-rules |
The Rspamd version is pinned in the FROM line and raised by Renovate, so a
rebuild does not silently change the Rspamd version.
The build overlays the upstream multimap rules on top of the bundled snapshot.
If the download fails — an air-gapped build, or --network=none — the build
still succeeds and the bundled snapshot is used. The log line says which of the
two happened.
docker pull ricariel/rspamd
Content type
Image
Digest
sha256:df7f6959c…
Size
129.1 MB
Last updated
about 8 hours ago
docker pull ricariel/rspamd