1 (edited by royalfoxy 2026-10-15 06:07:04)

Topic: Migrate from amavis/spamassassin to rspamd

======== Required information ====
- iRedMail version (check /etc/iredmail-release):  iRedMail-1.8.8
- Linux/BSD distribution name and version: Debian 13
- Store mail accounts in which backend (LDAP/MySQL/PGSQL): MySQL
- Web server (Apache or Nginx): Nginx
- Manage mail accounts with iRedAdmin-Pro? No
- Related log if you're reporting an issue: -
====

Hi, since I successfully migrated a production server based on the iRedMail script from amavisd/spamassassin to rspamd, I'd like to share the steps I took and possibly validate whether I skipped any important configuration stages. The migration was done on Debian 13/MySQL/NGINX (not the PRO version), so the paths I give are the correct ones for my setup.

1. Backup

Just in case we dump the versions and secure a basic backup.

cd /root
mkdir -p /root/migrate-rspamd && cd /root/migrate-rspamd
tar czf etc-$(date +%F).tgz /etc/postfix /etc/amavis /etc/mail/spamassassin /etc/spamassassin /etc/dovecot /etc/clamav /var/lib/dkim /var/vmail/sieve
tar czf cron-$(date +%F).tgz /var/spool/cron/crontabs /etc/default/spamassassin
mysqldump --single-transaction amavisd > amavisd.sql

dpkg -l | grep -Ei 'amavis|spamassassin|clamav|rspamd' > pkgs.txt
chmod 600 *.tgz amavisd.sql

2. Installing rspamd + redis:

I couldn't use links in post so replace:
FIRST = rspamd.com/apt-stable/gpg.key
SECOND = rspamd.com/apt-stable/
with https on the begining

sudo apt install curl gnupg ca-certificates lsb-release
curl -fsSL FIRST | gpg --dearmor -o /usr/share/keyrings/rspamd.gpg
echo "deb [signed-by=/usr/share/keyrings/rspamd.gpg] SECOND trixie main" > /etc/apt/sources.list.d/rspamd.list
sudo apt update
sudo apt install rspamd redis-server

verification

systemctl enable --now redis-server && redis-cli ping

3. Configuration

The DKIM keys can be kept or regenerated. I kept them.

In /etc/rspamd/local.d/redis.conf

servers = "127.0.0.1:6379";

/etc/rspamd/local.d/dkim_signing.conf

enabled = true;
selector = "dkim";
path = "/var/lib/dkim/$domain.pem";

sign_authenticated = true;
sign_local = true;
sign_inbound = false;

allow_username_mismatch = true;
allow_hdrfrom_mismatch = true;
check_pubkey = true;

3.1 ClamAV

check the path:

grep LocalSocket /etc/clamav/clamd.conf

usermod -aG clamav _rspamd
systemctl restart rspamd

In /etc/rspamd/local.d/antivirus.conf

clamav {
  servers = "/var/run/clamav/clamd.ctl";   # whatever grep LocalSocket /etc/clamav/clamd.conf returned
  symbol  = "CLAM_VIRUS";
  type    = "clamav";
  action  = "reject";
  scan_mime_parts = true;
}

Verification

sudo -u _rspamd test -w /var/run/clamav/clamd.ctl && echo "socket OK"

3.2 I carry over the headers that were present in Amavisd.

/etc/rspamd/local.d/milter_headers.conf

use = ["spam-header","x-spam-status","x-spam-level","authentication-results","x-virus","add-headers","x-spamd-result","x_spam_score"];
routines {
  spam-header {
    header = "X-Spam-Flag";
    value  = "YES";
    remove = 0;
  }
  x-virus {
    symbols = ["CLAM_VIRUS"];
  }
  add-headers {
    headers {
      "X-Virus-Scanned" = "rspamd";
    }
    remove = 0;
  }
}

custom {
  x_spam_score = <<EOD
return function(task, common_meta)
  local ms = task:get_metric_score()
  if not ms then return nil end
  return nil,
    { ['X-Spam-Score'] = string.format('%.2f', ms[1]) },
    { ['X-Spam-Score'] = 0 },
    {}
end
EOD;
}

3.3 Thresholds

The thresholds in rspamd are different; below are the ones I added in /etc/rspamd/local.d/actions.conf

reject = 15;            # final rejection
rewrite_subject = 7;    # prefix [SPAM] in the subject
add_header = 6;         # tag (X-Spam-Flag) -> Junk
greylist = 4;           # greylisting

# subject for the 'rewrite subject' action (%s = original subject)
subject = "[SPAM] %s";

3.4 Web UI panel

If anyone wants such a panel, per the rspamd documentation

rspamadm pw

/etc/rspamd/local.d/worker-controller.inc
bind_socket = "127.0.0.1:11334";
password = "$2$...";

rspamadm configtest && systemctl restart rspamd

3.5 Finish

We apply the configuration:

rspamadm configtest
systemctl enable --now rspamd
systemctl restart rspamd
systemctl status rspamd --no-pager
ss -tlnp | grep -E '11332|11333|11334'

4. Postfix

In /etc/postfix/main.cf you should comment out

content_filter = smtp-amavis:[127.0.0.1]:10024

as well as

smtp-amavis_destination_recipient_limit = 1

In /etc/postfix/master.cf

You should comment out all occurrences of

-o content_filter=smtp-amavis...

We run

postconf -X pickup/unix/content_filter

4.1 DKIM keys (if you keep the already generated ones)

chown -R _rspamd:_rspamd /var/lib/dkim
chmod 0400 /var/lib/dkim/*.pem
find /var/lib/dkim -type d -exec chmod 0700 {} \;
sudo -u _rspamd head -c1 /var/lib/dkim/dts-frankfurt.de.pem >/dev/null && echo "keys OK"

4.2 Reload postfix:

postconf -e 'smtpd_milters = inet:127.0.0.1:11332'
postconf -e 'non_smtpd_milters = inet:127.0.0.1:11332'
postconf -e 'milter_protocol = 6'
postconf -e 'milter_default_action = accept'
postfix check && systemctl reload postfix

5. Disabling amavisd and spamassassin

systemctl disable --now amavisd spamassassin

Comment out the crons

1   2   *   *   *   python3 /opt/www/iredadmin/tools/cleanup_amavisd_db.py >/dev/null

Verification:

You can verify correctness in the logs:

tail -f /var/log/mail.log

Check the signing with the tool:

rspamc -u postmaster@your_domain.com <<'EOF' | grep DKIM_SIGNED  //change this
From: postmaster@your_domain.com  //change this
To: someone@someone.com  //change this
Subject: DKIM test

Test message
EOF

Spam test:

printf 'Subject: test gtube\n\nXJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X\n' \
  | sendmail postmaster@your-domain.com  //change this

======

I hope I didn't miss anything. iRedAPD reads the tables from the database so I left it as is; I assume the lists will still work. Unfortunately Bayes has to be trained from scratch. You can do it on the emails you have.

If anyone had the Bayes auto-learning scripts from the iRedMail documentation configured, they need to be changed:

# before: output="$(${SA_LEARN} --spam ${SPOOL_LEARN_SPAM_DIR})"
output="$(/usr/bin/rspamc learn_spam ${SPOOL_LEARN_SPAM_DIR})"
...
# before: output="$(${SA_LEARN} --ham ${SPOOL_LEARN_HAM_DIR})"
output="$(/usr/bin/rspamc learn_ham ${SPOOL_LEARN_HAM_DIR})"

If any messages get stuck in the Postfix queue, they need to be requeued:

postsuper -r ALL
postqueue -f
postqueue -p

There are differences in behavior:
Amavis did DISCARD, rspamd does REJECT for messages considered infected.

iRedAPD — wblist works but the per-user thresholds from amavis.policy are no longer used.

By default rspamd does not use the system resolver. It has to be changed in the settings.

If you have experience with this kind of migration or notice anything I might have missed, please let me know. I assume everyone will need to adjust the Rspamd configuration to their own needs starting from the defaults. I hope I didn't miss anything big_smile

----

Spider Email Archiver: On-Premises, lightweight email archiving software developed by iRedMail team. Supports Amazon S3 compatible storage and custom branding.

2

Re: Migrate from amavis/spamassassin to rspamd

Thanks for sharing. smile