Skip to main content

Configuration fundamentals

This page follows first setup. It explains what you can change in Rspamd and which file each change goes in.

Configuration areas​

AreaWhat it controlsWhere you change it
ModulesWhich checks run and how they are set uplocal.d/<module>.conf
ScoresHow much each symbol adds to the message scorelocal.d/groups.conf or local.d/<group>_group.conf, or the web interface (WebUI)
ActionsWhat Rspamd tells the MTA to do at each scorelocal.d/actions.conf
WorkersThe processes that scan mail, serve the WebUI and talk to the MTAlocal.d/worker-<name>.inc
General optionsDNS, timeouts, size limitslocal.d/options.inc
LoggingLog level, destination and formatlocal.d/logging.inc

Paths on this page are relative to /etc/rspamd/. A file in local.d/ holds only the settings you change, and Rspamd merges it with the shipped defaults. Don't wrap its content in the section name: local.d/actions.conf contains reject = 20;, not actions { reject = 20; }. Configuration file structure has the details.

Modules​

Modules run the checks. When a check matches, it adds a symbol to the result, and the symbol's score is added to the message score.

Four modules are compiled into the binary: chartable, dkim, regexp and fuzzy_check. The filters option lists the built-in modules to load, and these four are its default value. The others are Lua plugins, for example rbl, spf, dmarc, multimap and dkim_signing. You configure and disable both kinds the same way.

ModuleWhat it doesDefault state
rblDNS blocklist lookups for IP addresses, domains and URLsEnabled
spfSPF checksEnabled
dkimDKIM signature verificationEnabled
dmarcDMARC policy checksEnabled
fuzzy_checkFuzzy hash lookups, by default against the rspamd.com storageEnabled; free use has limits, see Fuzzy check and the usage policy
multimapRules based on lists (maps)Enabled with shipped freemail, disposable and redirector rules; add your own in local.d/multimap.conf
greylistGreylistingEnabled, but switches itself off until Redis is configured
antivirusPasses messages to a virus scannerInactive until you configure a scanner

Bayesian filtering is not a module. It is the statistical classifier, configured in local.d/classifier-bayes.conf (see statistics). It keeps its data in Redis, so it needs Redis servers, usually set in local.d/redis.conf (see Redis configuration). It adds BAYES_SPAM or BAYES_HAM only after it has learned at least 200 spam and 200 ham messages.

Changing and disabling modules​

Put only the options you want to change in local.d/<module>.conf, without a <module> { } wrapper. To turn a module off, set enabled = false; in that file:

# Replace MODULE with the module name, for example phishing.
# This overwrites any settings already in the file.
echo 'enabled = false;' | sudo tee /etc/rspamd/local.d/MODULE.conf

If the file already has settings, add the line to it instead. An empty file does not disable anything. rspamadm configdump -m lists the enabled modules and the reason each of the others is disabled.

Example: add a DNS blocklist​

# /etc/rspamd/local.d/rbl.conf
rbls {
"CUSTOM_RBL" {
symbol = "CUSTOM_RBL";
rbl = "custom.blocklist.example.com";
checks = ["from"]; # look up the IP address that sent the message
}
}

An RBL rule has no score option. Rspamd disables a rule that contains an unknown option and logs an error. Set the score in the rbl group instead:

# /etc/rspamd/local.d/rbl_group.conf
symbols {
"CUSTOM_RBL" {
weight = 2.0;
}
}

RBL rules skip loopback addresses and the networks in the global local_addrs option (private and link-local ranges by default), so you don't need to exclude your internal networks. To exclude more addresses from RBL checks only, set local_exclude_ip_map in local.d/rbl.conf to a map of addresses.

Fuzzy check and the usage policy​

fuzzy_check sends hashes of message parts to the public rspamd.com fuzzy storage. That feed is free only for non-commercial use below 5,000 queries per day; see the usage policy. Commercial sites, and sites that send more queries than that, must either use the premium feed or turn off the rspamd.com rule:

# /etc/rspamd/local.d/fuzzy_check.conf
rule "rspamd.com" {
enabled = false;
}

You can also run your own fuzzy storage. It holds only the hashes you learn yourself and does not replace the rspamd.com data. The storage worker is disabled by default and keeps its data in Redis, using the servers from local.d/redis.conf. To start it:

# /etc/rspamd/local.d/worker-fuzzy.inc
count = 1;

It listens on localhost:11335 and accepts learning only from the addresses in allow_update (localhost by default). If the scanners reach it over the network, as in the rule below, also set bind_socket in this file (for example bind_socket = "*:11335";) and list the hosts that learn in allow_update. A list set in local.d/ is added to the default localhost. The fuzzy storage tutorial covers access control and encryption.

To query your storage, add a rule for it:

# /etc/rspamd/local.d/fuzzy_check.conf
rule "local" {
algorithm = "mumhash";
servers = "fuzzy.internal.example.com:11335";
symbol = "LOCAL_FUZZY_UNKNOWN";
mime_types = ["*"];
read_only = false; # allow learning to this storage
skip_unknown = true; # ignore flags that are not in fuzzy_map
fuzzy_map = {
LOCAL_FUZZY_DENIED {
hits_limit = 20.0;
flag = 11;
}
}
}

Symbols from fuzzy_map have no score by default, so a match adds 0 to the message score (Rspamd also logs symbol ... has no score registered at startup). Give them one:

# /etc/rspamd/local.d/fuzzy_group.conf
symbols {
"LOCAL_FUZZY_DENIED" {
weight = 12.0;
}
}

Scores​

A symbol's weight, also called its score, is the amount it adds to the message score. The message score is the sum of the weights of all symbols that matched. Some symbols scale their weight by the confidence of the check: BAYES_SPAM, for example, adds up to 5.1 depending on the Bayes probability.

Some default weights:

SymbolDefault weightMeaning
FUZZY_DENIED12.0Matches a hash in the rspamd.com fuzzy blocklist
SPOOF_DISPLAY_NAME8.0Display name is used to spoof the recipient
BAYES_SPAMup to 5.1Bayes classifier says spam
MISSING_MID2.5No Message-ID header
R_SPF_FAIL1.0SPF verification failed
MISSING_DATE1.0No Date header
FORGED_SENDER0.3From header and SMTP MAIL FROM differ
R_DKIM_NA0.0No DKIM signature
R_DKIM_ALLOW-0.1DKIM signature verified
R_SPF_ALLOW-0.2SPF allows the sender
DMARC_POLICY_ALLOW-0.5DMARC check passed
BAYES_HAMdown to -3.0Bayes classifier says ham

rspamadm configdump -g prints every symbol with the score set in the configuration files. It does not include scores saved from the WebUI (see below); the WebUI Symbols tab shows the scores the running Rspamd uses.

Changing a score​

Set weights in local.d/groups.conf:

# /etc/rspamd/local.d/groups.conf
symbols {
"FORGED_SENDER" {
weight = 1.0;
}
"R_SPF_FAIL" {
weight = 0.5;
}
}

The same symbols { } block also works in the file of the symbol's group, for example local.d/headers_group.conf for FORGED_SENDER or local.d/policies_group.conf for R_SPF_FAIL. The group line in rspamadm configdump -d output tells you which group a symbol belongs to.

Scores you change in the WebUI are saved to /var/lib/rspamd/rspamd_dynamic and take precedence over local.d/. If a local.d/ change has no effect, check whether rspamd_dynamic holds a value for the same symbol.

Older guides set scores in local.d/metrics.conf. That file has been deprecated since Rspamd 1.7; use the group files.

Tuning scores​

Adjust the action thresholds first (see Setting thresholds). Change individual weights when specific symbols cause wrong results.

  1. Check the counters:
    rspamc stat | grep -E 'Messages (scanned|with action|treated)'
  2. In the WebUI History tab, open misclassified messages and note which symbols matched.
  3. Change one weight at a time, run sudo rspamadm configtest, then restart Rspamd with sudo systemctl restart rspamd.
  4. Watch the History tab and rspamc stat before you make the next change.

Actions​

The action is Rspamd's verdict for the MTA. Rspamd compares the message score with the action thresholds and picks the action with the highest threshold that the score has reached (score >= threshold).

ActionDefault thresholdResult
no actionbelow 4The message is accepted.
greylist4If the greylist module is active (it needs Redis), first-time senders get a temporary failure (soft reject) and must retry. Messages that score high enough for add header or rewrite subject are greylisted too; rejected messages are not. Without Redis the message is accepted.
add header6The message is delivered with a spam header (X-Spam: Yes when the MTA uses the milter proxy). Mail filters or the mail client usually move it to a spam folder.
rewrite subjectnoneThe subject line is rewritten. Applies only if you set a threshold.
soft rejectnoneTemporary failure. Modules such as greylist and ratelimit set it.
reject15The MTA refuses the message during the SMTP session (554 5.7.1 Spam message rejected with the milter proxy). The sending server reports the failure to its user; your server sends no bounce.

With the default thresholds, a message that scores 8.5 gets add header (if greylisting is active, a first-time sender gets a soft reject first):

Setting thresholds​

local.d/actions.conf is merged with the defaults, so list only the thresholds you change. In this file, action names are written with underscores (add_header, rewrite_subject):

# /etc/rspamd/local.d/actions.conf
reject = 20; # default 15
add_header = 8; # default 6

Which way to move each threshold:

ThresholdRaise it whenLower it when
rejectlegitimate mail gets rejectedobvious spam is only marked, not rejected
add_headerlegitimate mail lands in spam foldersspam reaches inboxes unmarked
greylistlegitimate senders complain about delaysspam that scores just below the threshold is delivered without greylisting

Workers​

Each worker type has its own file in local.d/. Put only the options you change in it, without a worker { } wrapper.

Worker typeRoleLocal fileDefault socket
normalScans messageslocal.d/worker-normal.inclocalhost:11333
controllerWebUI, HTTP API, learning, statisticslocal.d/worker-controller.inclocalhost:11334
rspamd_proxyMilter interface for the MTA; passes messages to scanners or scans them itselflocal.d/worker-proxy.inclocalhost:11332
fuzzyLocal fuzzy hash storage (Redis backend)local.d/worker-fuzzy.inclocalhost:11335, disabled by default

Controller​

Set a password for the WebUI and API. rspamadm pw asks for a password and prints its hash:

# /etc/rspamd/local.d/worker-controller.inc
password = "$2$..."; # hash printed by rspamadm pw

secure_ip lists the addresses that may use the controller without a password (127.0.0.1 and ::1 by default). It does not restrict who can connect: use bind_socket (default localhost:11334) and a firewall for that. A secure_ip value in local.d/ replaces the default list instead of adding to it.

Proxy​

The proxy is enabled by default. It speaks the milter protocol on port 11332 and passes messages to the normal worker on localhost. On a single server it can scan messages itself (self-scan mode):

# /etc/rspamd/local.d/worker-proxy.inc
upstream "local" {
self_scan = yes;
}

The normal worker keeps running after this change. If nothing else uses it, disable it:

# /etc/rspamd/local.d/worker-normal.inc
enabled = false;

rspamc then has to use the controller port (11334). It does so by default when it connects to localhost; for a remote host, pass -h host:11334. See self-scan mode for details.

Normal worker​

To scan more messages in parallel, run more scanner processes with count:

# /etc/rspamd/local.d/worker-normal.inc
count = 8;

The default count is the number of CPU cores minus two, at least 1 and at most 4. max_tasks (default 0, unlimited) caps how many messages one process handles at the same time, so set it only to limit load, not to increase throughput.

General options​

Global options go in local.d/options.inc. The ones you are most likely to change:

OptionDefaultMeaning
dns.nameserverservers from /etc/resolv.confDNS servers Rspamd queries
dns.timeout1sTime to wait for each DNS attempt
dns.retransmits5Attempts before a lookup fails
dns.sockets16Sockets per DNS server
dns_max_requests64DNS requests allowed per message
task_timeout8sMaximum processing time for one message
max_message50 MiBLargest message Rspamd scans
max_urls10240Maximum number of URLs processed per message
max_recipients1024Maximum number of recipients processed per message
local_addrsprivate and link-local rangesAddresses treated as local, for example skipped by RBL checks

DNS​

Use a local recursive resolver; DNS resolver explains why.

# /etc/rspamd/local.d/options.inc
dns {
nameserver = ["127.0.0.1"]; # local recursive resolver
}

Without nameserver, Rspamd uses the servers listed in /etc/resolv.conf. Set 127.0.0.1 only if a resolver listens there.

On a slow network, raise the DNS timeout and keep task_timeout above the longest DNS wait. Each attempt waits a full timeout, so one lookup can take up to timeout × retransmits:

# /etc/rspamd/local.d/options.inc
dns {
timeout = 3s; # 5 attempts (default): up to 15s per lookup
}
task_timeout = 20s;

Message size limit​

Rspamd does not scan messages larger than max_message, so keep it at or above the message size limit of your MTA:

# /etc/rspamd/local.d/options.inc
max_message = 100mb;

Write sizes with mb. In UCL, mb means 1024 × 1024 bytes and M means 1,000,000 bytes, so max_message = 50M; sets a limit slightly below the 50 MiB default.

Logging​

Logging has its own section and file, local.d/logging.inc. Logging settings placed in options.inc are ignored. By default Rspamd logs at info level to /var/log/rspamd/rspamd.log. To get debug output from one module without switching the whole log to debug:

# /etc/rspamd/local.d/logging.inc
debug_modules = ["dkim"];

See logging for all options.

Configuration file structure​

/etc/rspamd/
├── rspamd.conf # main file (shipped, do not edit)
├── actions.conf # shipped defaults, one file per section
├── groups.conf
├── options.inc
├── worker-*.inc
├── modules.d/ # shipped module defaults (do not edit)
├── scores.d/ # shipped symbol scores (do not edit)
├── local.d/ # your changes, merged with the defaults
│ ├── actions.conf
│ ├── groups.conf
│ ├── options.inc
│ └── worker-normal.inc
└── override.d/ # your changes, replacing defaults key by key

A comment at the top of most shipped files names the local.d/ and override.d/ files that extend them. Don't edit the shipped files: upgrades bring new versions of them, and an edited file is either replaced (FreeBSD) or left for you to merge by hand (.rpmnew files, dpkg prompts). See Key paths.

Precedence​

From lowest to highest:

  1. Shipped defaults: rspamd.conf and the files next to it, modules.d/, scores.d/.
  2. local.d/ (priority 1): merged into the defaults. Settings you don't mention keep their default values.
  3. Scores and action thresholds saved from the WebUI (/var/lib/rspamd/rspamd_dynamic). They take precedence over local.d/ but not over override.d/.
  4. override.d/ (priority 10): every key or block you define replaces the default as a whole, without merging. Keys you don't define keep their defaults.

For example, override.d/actions.conf containing only reject = 20; keeps the default add_header and greylist thresholds. But override.d/options.inc containing dns { timeout = 3s; } replaces the whole dns block: the sockets and retransmits lines from the shipped options.inc no longer apply, and Rspamd uses its built-in values for them.

Use local.d/ unless you need to replace a whole block. Top-level sections that have no file in local.d/ go into rspamd.conf.local, or rspamd.conf.override to override at priority 10.

Testing changes​

sudo rspamadm configtest # prints "syntax OK" or the errors
sudo rspamadm configtest -s # also fails if any module logged an error

Plain configtest can print syntax OK while a module has rejected part of its configuration. An RBL rule with an unknown option, for example, is disabled with an error message. With -s, any logged error makes the test fail with syntax BAD.

Check the configuration as Rspamd loads it:

rspamadm configdump actions # one section
rspamadm configdump -g # symbol groups with scores from the config files
rspamadm configdump -d | grep -A10 'MISSING_DATE {' # details of one symbol
rspamadm configdump -m # enabled and disabled modules

Plain rspamadm configdump shows only the configuration files, so symbols registered by Lua rules, such as MISSING_DATE, do not appear in it. Use -g or -d to see scores, including those of Lua rules. Neither includes scores saved from the WebUI.

Scan a message and follow the log:

rspamc /path/to/message.eml
rspamc /path/to/message.eml | grep SYMBOL_NAME
tail -f /var/log/rspamd/rspamd.log

Common setups​

SetupWhat you changeFiles
MinimalRedis, the controller password and MTA integration; modules, scores and thresholds stay at their defaultslocal.d/redis.conf, local.d/worker-controller.inc; local.d/worker-proxy.inc only if the MTA runs on another host
TunedAlso action thresholds, symbol scores, extra blocklists, your own map rules, Bayesadds local.d/actions.conf, local.d/groups.conf (or <group>_group.conf), local.d/rbl.conf, local.d/multimap.conf, local.d/classifier-bayes.conf
High volumeNumber of scanner processes, DNS and timeouts, separate scanner hosts behind the proxylocal.d/worker-normal.inc, local.d/options.inc, local.d/worker-proxy.inc

Next steps​