Skip to content
Logo
Table of contents
VeryCloud
DocumentationVPS Linux

Rspamd: modern anti-spam for mail servers

Rspamd: modern anti-spam for mail servers

Rspamd is the modern successor to SpamAssassin: faster, more accurate, based on rules + bayesian + reputation. The anti-spam filter used by Mailcow, ProtonMail, and many large providers.

Category
VPS Linux
Level
Advanced
Reading time
5 min
Published
May 18, 2026

Introduction

Rspamd:

  • C/Lua daemon, 30x faster than SpamAssassin
  • Filters: SPF, DKIM, DMARC, ARC, DNSBL, regex, Lua rules
  • Bayesian learning (per-user or global)
  • Integrated greylisting
  • Web UI for debug and stats
  • REST API
  • Plug-and-play with Postfix, Exim, Sendmail

Note: if you use Mailcow, Rspamd is already installed and configured. This tutorial is for standalone install (Postfix + Dovecot + manual Rspamd).

Prerequisites

  • Linux VPS with Postfix already installed (see tutorial 38)
  • Root access
  • Redis (for stats and bayesian)

Step 1: Installation

curl https://rspamd.com/apt-stable/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/rspamd.gpg
echo "deb [signed-by=/usr/share/keyrings/rspamd.gpg] https://rspamd.com/apt-stable/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/rspamd.list

sudo apt update
sudo apt install -y rspamd redis-server

rspamadm --version

Step 2: First start

sudo systemctl enable --now rspamd redis-server
sudo systemctl status rspamd

Rspamd listens by default on:

  • 11332: milter (Postfix interface)
  • 11333: normal worker
  • 11334: web UI

Step 3: Password for UI

Generate hash:

rspamadm pw

Type password, hash appears.

/etc/rspamd/local.d/worker-controller.inc:

password = "$2$abc123hashpassword...";
bind_socket = "0.0.0.0:11334";
sudo systemctl restart rspamd

Visit http://IP:11334. Login: leave empty, password = chosen one.

Step 4: Postfix integration

/etc/postfix/main.cf:

smtpd_milters = inet:localhost:11332
non_smtpd_milters = inet:localhost:11332
milter_default_action = accept
milter_protocol = 6
sudo systemctl restart postfix

All incoming mails now go through Rspamd.

Step 5: Test

Send a test (GTUBE = recognized test pattern):

echo "Subject: Test spam
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X

Test message body" | sendmail -t [email protected]

Mail should be marked as spam. In Rspamd UI > History, see the scoring.

Step 6: Bayesian (learning)

Configure for training:

sudo nano /etc/rspamd/local.d/classifier-bayes.conf
servers = "127.0.0.1";
backend = "redis";
new_schema = true;
expire = 8640000;
autolearn = true;

users_enabled = false;    # global bayesian (true for per-user)
sudo systemctl restart rspamd

Manual learning:

rspamc learn_spam /path/to/spam.eml
rspamc learn_ham /path/to/ham.eml

After ~200 spam + 200 ham, bayesian becomes effective.

For re-learning from Dovecot when user moves a mail to Junk folder (Sieve script): see step 11.

Step 7: Greylisting

Temporarily blocks emails from unknown senders, accepts on 2nd try (spammers rarely retry).

/etc/rspamd/local.d/greylist.conf:

servers = "127.0.0.1:6379";
expire = 1d;
timeout = 5m;
ipv4_mask = 19;
ipv6_mask = 64;

Active by default. To disable:

enabled = false;

Step 8: Score tuning

/etc/rspamd/local.d/actions.conf:

reject = 15.0;
add_header = 6.0;    # adds "X-Spam: Yes" if score >= 6
greylist = 4.0;

To adjust specific rule scoring:

/etc/rspamd/local.d/metric.conf:

symbol "SPF_FAIL" {
    weight = 4.0;
}

symbol "DKIM_INVALID" {
    weight = 3.0;
}

symbol "MISSING_TO" {
    weight = 2.0;
}

Step 9: Custom DNSBL

/etc/rspamd/local.d/rbl.conf:

rbls {
    spamhaus {
        symbol = "RBL_SPAMHAUS";
        rbl = "zen.spamhaus.org";
        ipv6 = true;
    }
    
    barracuda {
        symbol = "RBL_BARRACUDA";
        rbl = "b.barracudacentral.org";
    }
}

Step 10: Whitelist / Blacklist

/etc/rspamd/local.d/maps.d/local_bl.map:

[email protected]
*@spammer-domain.com

/etc/rspamd/local.d/maps.d/local_wl.map:

[email protected]
@example.com        # my whole domain

/etc/rspamd/local.d/multimap.conf:

LOCAL_BL_FROM {
    type = "from";
    map = "/etc/rspamd/local.d/maps.d/local_bl.map";
    score = 15.0;
    symbol = "LOCAL_BL_FROM";
}

LOCAL_WL_FROM {
    type = "from";
    map = "/etc/rspamd/local.d/maps.d/local_wl.map";
    score = -10.0;
    symbol = "LOCAL_WL_FROM";
}

Step 11: Auto-learning via Sieve

For users to train Rspamd by moving mails to "Junk", configure Dovecot Sieve:

sudo apt install -y dovecot-sieve dovecot-managesieved

Script /etc/dovecot/sieve/learn-spam.sieve:

require ["vnd.dovecot.pipe", "copy", "imapsieve"];

pipe :copy "learn-spam.sh" ["${mailbox}"];

And /etc/dovecot/sieve/learn-spam.sh:

#!/bin/sh
exec /usr/bin/rspamc -h 127.0.0.1:11334 learn_spam

Configure Dovecot event:

sudo nano /etc/dovecot/conf.d/90-sieve.conf
plugin {
  sieve_plugins = sieve_imapsieve

  imapsieve_mailbox1_name = Junk
  imapsieve_mailbox1_causes = COPY APPEND
  imapsieve_mailbox1_before = file:/etc/dovecot/sieve/learn-spam.sieve
  
  imapsieve_mailbox2_name = *
  imapsieve_mailbox2_from = Junk
  imapsieve_mailbox2_causes = COPY
  imapsieve_mailbox2_before = file:/etc/dovecot/sieve/learn-ham.sieve
}

User moves mail to Junk -> Rspamd learns as spam. Out of Junk -> learned as ham.

Step 12: Rspamd cluster (HA)

For scaling or HA:

# /etc/rspamd/local.d/redis.conf
servers = "10.0.0.1:6379,10.0.0.2:6379";

Stats and bayesian shared between nodes. Multiple workers behind load balancer.

Troubleshooting

No mails filtered

Check Postfix integration:

sudo postconf -n | grep milter

Must point to inet:localhost:11332. Check logs:

sudo tail -f /var/log/rspamd/rspamd.log
sudo tail -f /var/log/mail.log

"Cannot connect to Redis"

sudo systemctl status redis-server
redis-cli ping
# PONG expected

Check Redis port in worker-controller.inc.

Web UI inaccessible

Check bind_socket and port 11334 open. To expose publicly, put behind Nginx reverse proxy with basic auth.

Too many false positives

Reduce scores of triggering rules. UI > Symbols > frequency:

rspamc stat

Whitelist trusted domains.

Bayesian not training

rspamc stat | grep learned

Need at least 200 spam + 200 ham for stable results.

Useful commands

sudo systemctl status rspamd
sudo systemctl restart rspamd

sudo tail -f /var/log/rspamd/rspamd.log

rspamc stat
rspamc symbols
rspamc counters

rspamc learn_spam /path/to/file.eml
rspamc learn_ham /path/to/file.eml
rspamc -h localhost:11334 learn_spam < message.eml

rspamc < message.eml

sudo systemctl reload rspamd

sudo rspamadm configtest

rspamc statreset

Conclusion

Rspamd is state-of-the-art anti-spam:

  • Performant (up to 30k msg/s)
  • Modular (Lua scripting)
  • Full UI for debug
  • Effective bayesian learning

Going further:

  • Combine with ClamAV for virus filtering
  • Integrate OpenDMARC for strict DMARC validation
  • For Mailcow, Rspamd is already there and accessible via /rspamd/ in UI

Resources

Join our Discord community server

For any questions, suggestions, or just to chat with the community, join us on Discord!

900+Members