Setup Email Server From Scratch Debian #2 - 12 Amavis Clam AntiVirus

11 SpamAssassin <- Intro -> 13 Reducing Server Load With Postscreen

We believe in data independence, and support others who want data independence.
Debian Email From Scratch version 2 finished 2025-07-30.

We are still adding to it but it all works!

#######################################################
# Installing Antivirus Amavis and ClamAV on Debian 12 #
#######################################################

# Install amavisd

apt install amavisd-new
apt install arj bzip2 cabextract cpio rpm2cpio file gzip lhasa nomarch pax
apt install rar unrar p7zip-full unzip zip lrzip lzip liblz4-tool lzop unrar-free

# Get the amavis user and group id

root@okdeb.com:~# grep amavis /etc/passwd /etc/group
/etc/passwd:amavis:x:994:994:AMaViS system user:/var/lib/amavis:/bin/sh
/etc/group:amavis:x:994:

# Create a 1G memory mapped tmp filesystem for amavis

mkdir -p /var/lib/amavis/tmp

nano /etc/fstab
# ---
tmpfs /var/lib/amavis/tmp tmpfs defaults,noexec,nodev,nosuid,size=1024m,mode=750,uid=994,gid=994 0 0
# ---

systemctl daemon-reload
mount /var/lib/amavis/tmp

# Check the amavis user and group for the amavis tmp directory

ls -ld /var/lib/amavis/tmp
drwxr-x--- 2 amavis amavis 40 Jul 30 10:30 /var/lib/amavis/tmp

systemctl enable amavis
systemctl start amavis
systemctl status amavis

root@okdeb.com:~# netstat -lnpt | grep amavis
tcp        0      0 127.0.0.1:10024     0.0.0.0:*    LISTEN      28996/amavisd (mast 
tcp6       0      0 ::1:10024           :::*         LISTEN      28996/amavisd (mast 


root@okdeb.com:~# amavisd -V
amavis-2.13.0 (20230106)

nano /etc/amavis/conf.d/05-node_id
# ---
$myhostname = "mx.okdeb.com";
# ---

systemctl restart amavis

# Add Amavis to Postfix main.cf

nano /etc/postfix/main.cf
# --- add to bottom of file
# amavisd
smtpd_proxy_options = speed_adjust
content_filter = smtp-amavis:[127.0.0.1]:10024
# ---

# In teh smtp-amavis adjust max_servers in 50-user value, cores on server, 4 in this
# example.

lscpu | grep CPU\(s\): | grep -v NUMA

-------------------------------------v
smtp-amavis   unix   -   -   n   -   4   smtp

nano /etc/postfix/master.cf
# --- add to end of file, -- cores - v ------
smtp-amavis   unix   -   -   n   -   4   smtp
    -o syslog_name=postfix/amavis
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20
    -o smtp_tls_security_level=none

127.0.0.1:10025   inet   n    -     n     -     -    smtpd
    -o syslog_name=postfix/10025
    -o content_filter=
    -o mynetworks_style=host
    -o mynetworks=127.0.0.0/8
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o strict_rfc821_envelopes=yes
    -o smtp_tls_security_level=none
    -o smtpd_tls_security_level=none
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_end_of_data_restrictions=
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings
# ---

systemctl restart postfix

# Install clamav and clamav-daemon

apt install clamav clamav-daemon

systemctl enable clamav-freshclam
systemctl start clamav-freshclam
systemctl status clamav-freshclam

# ClamAV Daemon need to download the virus definitions file and be restarted.

systemctl enable clamav-daemon
systemctl start clamav-daemon
systemctl status clamav-daemon
Condition: start condition failed at Wed 2025-07-30 10:53:12 PDT; 2min 3s ago

# Try to restart clamav-daemon

systemctl restart clamav-daemon
systemctl status clamav-daemon
     Active: active (running) since Wed 2025-07-30 10:55:57 PDT; 12ms ago

# SpamAssassin headers can get removed by amavis if run separately so I enable 
# spamassassin in amavis and disable it it postfix. This will retain the X-Spam-Score
# and have X-Virus-Scanned, otherwise if run SpamAssassin from postfix amavis will
# remove the X-Virus-Scanned headers.

nano /etc/amavis/conf.d/15-content_filter_mode
# --- enable these two sections by removing the # hash marks ---
@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
# ---

adduser clamav amavis
systemctl restart amavis clamav-daemon

systemctl status amavis
Jul 30 11:00:10 okdeb.com amavis[30944]: Using primary internal av scanner code for ClamAV-clamd
Jul 30 11:00:10 okdeb.com amavis[30944]: Found secondary av scanner ClamAV-clamscan at /usr/bin/clamscan

# Use a dedicated port for submissions, max_servers should be the number of cores on 
# the server, I have 4 virtual cores.

nano /etc/amvais/conf.d/50-user.conf
# ---
$max_servers = 4;
$enable_dkim_verification = 0;
$sa_tag_level_deflt = -999;
$X_HEADER_LINE = "by mx.$mydomain";
$TEMPBASE = "/var/lib/amavis/tmp";

$inet_socket_port = [10024, 10026];
$interface_policy{'10026'} = 'ORIGINATING';

$policy_bank{'ORIGINATING'} = {  # mail supposedly originating from our users
  originating => 1,  # declare that mail was submitted by our smtp client
  allow_disclaimers => 1,  # enables disclaimer insertion if available

 # notify administrator of locally originating malware
  virus_admin_maps => ["postmaster\@okdeb.com"],
  spam_admin_maps  => ["postmaster\@okdeb.com"],
  warnbadhsender   => 1,

  # force MTA conversion to 7-bit (e.g. before DKIM signing)
  smtpd_discard_ehlo_keywords => ['8BITMIME'],
  bypass_banned_checks_maps => [1],  # allow sending any file names and types
  terminate_dsn_on_notify_success => 0,  # don't remove NOTIFY=SUCCESS option
};
# ---

# Fix amavis to scan other virtual domains

nano /etc/amavis/conf.d/05-domain_id
# ---
@local_domains_acl = ( ".$mydomain",".coragarden.com",".domain3.org" );
# ---

# Add the following 2 line to /etc/postfix/master.cf submission and smtps sections
# Add the no_milters or else outgoing gets DKIM signed twice!

  -o content_filter=smtp-amavis:[127.0.0.1]:10026
  -o receive_override_options=no_milters

nano /etc/postfix/master.cf
# --- add the content_filter line in 2 places like this
submission     inet     n    -    y    -    -    smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=no
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o content_filter=smtp-amavis:[127.0.0.1]:10026
  -o receive_override_options=no_milters
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o content_filter=smtp-amavis:[127.0.0.1]:10026
  -o receive_override_options=no_milters
# ---

systemctl restart postfix

# Well use Spamassassin in amavis not in postfix
apt install libnet-dns-perl libmail-spf-perl pyzor razor

# Remove SpamAssasin socket in smtpd_milters, it is running in amavis

nano /etc/postfix/main.cf
# ---
smtpd_milters = unix:opendkim/opendkim.sock,unix:opendmarc/opendmarc.sock
# ---

systemctl restart amavis

# Next Up Reducing Server Load With Postscreen

11 SpamAssassin <- Intro -> 13 Reducing Server Load With Postscreen