SOHO Mailserver with Postfix+Postgresql+Dovecot+SpamAssassin+Roundcube

This HowTo describes my Home-Mailserver Setup. Basically this is a sum-it-all-up article from various resources on the net. 

Used Software:

  • Arch Linux OS
  • Postfix MTA
  • PostgreSQL database backend
  • Dovecot IMAP Server
  • Roundcube Webmail + Apache Webserver
  • Spamassassin junk filter
  • Server-side filtering with Sieve
  • fetchmail (for pulling all spread accounts in this one place)

Preconditions:

  • Server behind Firewall/NAT
  • Dynamic IP (No-IP Plus manages DynDNS service with MX Record etc)
  • StartSSL certificate for both Web- and Mail-Server domain
  • ISP doesn't allow running an outgoing mail server
  • Apache + PHP + Postgresql already running and working

[toc]

 

1. Prepare the host interfaces

As the server runs with LAN IP it's required to set hostnames in /etc/hosts. Here both Apache and the Mail-$foo will listen on one interface.

192.168.1.2   domain.net   mail.domain.net

 

2. Install required packages

This host runs Arch-Linux with community, extra and AUR enabled.

# yaourt -S postfix postfixadmin dovecot pigeonhole roundcubemail spamassassin \
razor fetchtmail perl-dbd-pg perl-lockfile-simple

 

3. Setup Postgresql DB

We will need two DBs: one for postfix/postfixadmin/dovecot, one for roundcubemail

$ createuser postfixadmin -P     # no superuser, no createdb, no createuser
$ createuser mailreader -P        # dito
$ createuser roundcube -p         # dito
$ createdb postfix --owner postfixadmin
$ createdb roundcube --owner roundcube

 

4. Setup PostfixAdmin

I installed postfixAdmin into a vhost which is only accessible on localhost, using following config (mind: AUR package of postfixadmin)

Alias /postfixAdmin "/usr/share/webapps/postfixAdmin"
<Directory "/usr/share/webapps/postfixAdmin">
      AllowOverride All
      Options FollowSymlinks
      Order allow,deny
      Allow from all
</Directory>

.. and included that in the local-only vhost.

Then edit /etc/webapps/postfixadmin/config.inc.php

$CONF['configured'] = true;
...
$CONF['database_type'] = 'pgsql';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfixadmin';
$CONF['database_password'] = 'secret';
...
$CONF['admin_email'] = 'postmaster@domain.net';
...
$CONF['smtp_server'] = 'mail.domain.net';
$CONF['smtp_port'] = '25';
...
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';

Now head to http://admin.localhost/postfixAdmin and run the setup. This will install the DB-Schema for Postfix.

5. Prepare Dovecot

The next step is to prepare Dovecot. I will use Dovecot LDA as delivery agent, and enable Sieve/ManageSieve for server-side filtering. Edit following file in /etc/dovecot (only changed lines are shown).

edit dovecot.conf

protocols = imap sieve
listen = *, ::

create dovecot-sql.conf.ext

driver = pgsql
connect = host=localhost dbname=postfix user=postfix password=secret
default_pass_scheme = MD5
user_query = \
    SELECT '/var/mail/vmail/'||maildir AS home, '*:bytes='||quota AS quota_rule \
    FROM mailbox WHERE username = '%u' AND active = TRUE
password_query = \
    SELECT '/var/mail/vmail/'||maildir AS userdb_home, \
        username AS user, password, '*:bytes='||quota AS userdb_quota_rule \
    FROM mailbox WHERE username = '%u' AND active = TRUE

conf.d/10-mail.conf

mail_location = maildir:/var/mail/vmail/%d/%n/
mail_uid = 8
mail_gid = 12
first_valid_uid = 8
last_valid_uid = 8
first_valid_gid = 12
last_valid_gid = 12
mail_plugins = quota

conf.d/20-imap.conf

mail_plugins = $mail_plugins imap_quota

conf.d/10-master.conf

service auth {
  unix_listener auth-userdb {
    mode = 0600
    user = mail
    group = mail
  }
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
}

service auth-worker {
  user = $default_internal_user
}

conf.d/10-auth.conf (I enabled plain-text auth for testing. Take care!)

disable_plaintext_auth = no  #DANGEROUS
#!include auth-system.conf.ext
!include auth-sql.conf.ext

conf.d/15-lda.conf

postmaster_address = postmaster@domain.net
protocol lda {
  mail_plugins = $mail_plugins sieve
}

conf.d/90-plugin.conf

Note: /var/lib/dovecot/sieve/ has to be created and owned by mail:mail

plugin {
   sieve = ~/.dovecot.sieve
   sieve_global_path = /var/lib/dovecot/sieve/default.sieve
   sieve_dir = ~/sieve
   sieve_global_dir = /var/lib/dovecot/sieve/global/
}

conf.d/10-ssl.conf

Note: for StartSSL combine the server and the intermediate cert in one .pem (with cat .. > ..), and specify the root ca

ssl = yes
ssl_cert = </etc/ssl/certs/mail.domain.net.pem
ssl_key = </etc/ssl/private/mail.domain.net.key
ssl_ca = </etc/ssl/certs/startssl-ca-bundle.crt

 

6. Prepare Postfix

main.cf

myhostname = mail.domain.net
mydomain = domain.net
mydestination = $myhostname, localhost
mynetworks = 192.168.1.0/24, 127.0.0.0/8
myorigin = $mydomain
relay_domains = proxy:pgsql:/etc/postfix/pgsql/relay_domains.cf
# this is needed if your ISP doesn't allow to run a outgoing mailserver. Use their mail relay.
relayhost = mail.mnet-online.de
# enable auth via Dovecot
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = private/auth
smtpd_sasl_type = dovecot
# vmail stuff
virtual_mailbox_base = /var/mail/vmail
virtual_mailbox_limit = 512000000
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/pgsql/virtual_domains_maps.cf
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/pgsql/virtual_mailbox_maps.cf
virtual_alias_maps = proxy:pgsql:/etc/postfix/pgsql/virtual_alias_maps.cf
virtual_uid_maps = static:8
virtual_gid_maps = static:12
virtual_minimum_uid = 8
dovecot_destination_recipient_limit = 1
virtual_transport = dovecot-spamassassin
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps

/etc/postfix/pgsql/relay_domains.cf

user = mailreader
password = secret
hosts = localhost
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = true

/etc/postfix/pgsql/virtual_alias_maps.cf

user = mailreader
password = secret
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = true

/etc/postfix/pgsql/virtual_domains_maps.cf

user = mailreader
password = secret
hosts = localhost
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = false and active = true

/etc/postfix/pgsql/virtual_mailbox_limits.cf

# Used for QUOTA!
user = mailreader
password = secret
hosts = localhost
dbname = postfix
query = SELECT quota FROM mailbox WHERE username='%s'

/etc/postfix/pgsql/virtual_mailbox_maps.cf

user = mailreader
password = secret
hosts = localhost
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = true

/etc/postfix/master.cf

We pipe through spamassassin forwards to Dovecot DLA

dovecot-spamassassin   unix  -       n       n       -       -       pipe
  flags=DRhu user=mail:mail argv=/usr/bin/vendor_perl/spamc -f -e /usr/lib/dovecot/deliver
  -f ${sender} -d ${recipient}

 

7. Prepare Spamassassin

8. Create domain and users in postfixAdmin

9. Start and Test

10. Install roundcube

11. Setup fetchmail in postfixAdmin