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 managed 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

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/setup.php. Generate a setup_password and put the hash in /etc/webapps/postfixadmin/config.inc.php.

Now run the setup. This will install the DB-Schema for Postfix, and setup an admin user.

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

Just install, and edit /etc/conf.d/spamd

SAHOME="/var/lib/spamassassin"
SPAMD_OPTS="--max-children 1 --username spamd --helper-home-dir ${SAHOME} -s ${SAHOME}/spamd.log -x -q --pidfile /var/run/spamd.pid"

8. Create domain and users in postfixAdmin

Login with the admin user created in (4.).

  1. In Domain List -> New Domain create a new domain domain.tld and enable create default aliases checkbox
  2. In Virtual List -> Add Mailbox create a new mailbox

9. Start and Test

Now start postfix, dovecot and spamd, and send some test mail from external account to your newly created mailbox. See postfix and dovecot logs if things arrive properly. Use some mail client (thunderbird, claws-mail etc) and configure your mailbox as IMAP account and the SMTP for sending.

10. Install roundcube

First, install the database schema

psql -U roundcube -d roundcube < /srv/http/roundcube/SQL/postgres.initial.sql

Then prepare the config

cd /srv/http/roundcube/config
cp db.inc.php.dist db.inc.php
cp main.inc.php.dist main.inc.php

In db.inc.php set the DSN like

$rcmail_config['db_dsnw'] = 'pgsql://roundcube:secret@localhost/roundcube';

In main.inc.php set

$rcmail_config['enable_installer'] = true;

Now point your browser to http://localhost/roundcube/installer/ and follow the instructions. Afterwards delete the installer folder.

You should be able to log into your mailbox account.

11. Setup fetchmail in postfixAdmin