Difference between revisions of "Virtual user mail system"

From ArchWiki
Jump to: navigation, search
(rc.conf: Changing for updates to courier-imap)
(Update for systemd)
(44 intermediate revisions by 14 users not shown)
Line 1: Line 1:
{{i18n|Simple Virtual User Mail System}}
+
[[Category:Mail Server]]
[[Category:Web Server (English)]]
+
  
This article describes how to set up a complete virtual user mail system on an Arch Linux system in the simplest manner possible. However, since a mail system consists of many complex components, quite a bit of configuration will still be necessary. Roughly, the components used in this article are Postfix, Cyrus, Courier, PAM, PostfixAdmin and Roundcube.
+
This article describes how to set up a complete virtual user mail system on an Arch Linux system in the simplest manner possible. However, since a mail system consists of many complex components, quite a bit of configuration will still be necessary. Roughly, the components used in this article are Postfix, Dovecot, PostfixAdmin and Roundcube.
  
 
In the end, the provided solution will allow you to use the best currently available security mechanisms, you will be able to send mails using SMTP and SMTPS and receive mails using POP3, POP3S, IMAP and IMAPS. Additionally, configuration will be easy thanks to PostfixAdmin and users will be able to login using Roundcube. What a deal!
 
In the end, the provided solution will allow you to use the best currently available security mechanisms, you will be able to send mails using SMTP and SMTPS and receive mails using POP3, POP3S, IMAP and IMAPS. Additionally, configuration will be easy thanks to PostfixAdmin and users will be able to login using Roundcube. What a deal!
Line 11: Line 10:
  
 
== Installation ==
 
== Installation ==
  # pacman -S postfix courier-imap cyrus-sasl cyrus-sasl-plugins pam_mysql
+
  # pacman -S dovecot postfix
  
 
== Configuration ==
 
== Configuration ==
Line 21: Line 20:
  
 
=== Database ===
 
=== Database ===
{{Expansion}}
+
You will need to create an empty database and corresponding user. We will be using PostfixAdmin's tables to fill the database later on. In this article, ''postfix_user'' will have read/write access to ''postfix_db'' using ''hunter2'' for a password. You are expected to create your database and user yourself as shown in the following code. Make sure to assign proper permissions.
You will need to create an empty database and corresponding user. We will be using PostfixAdmin's tables to fill the database later on. In this article, ''postfix_user'' will have read/write access to ''postfix_db'' using ''hunter2'' for a password. You are expected to create your database and user yourself. Make sure to assign proper permissions.
+
 
 +
{{hc|$> mysql -u root -p|password:}}
 +
{{bc|
 +
CREATE SCHEMA `postfix_db` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
 +
CREATE USER 'postfix_user'@'localhost' IDENTIFIED BY 'hunter2';
 +
GRANT ALL ON `postfix_db`.* TO `postfix_user`@`localhost`;
 +
}}
  
 
=== Postfix ===
 
=== Postfix ===
In {{filename|/etc/postfix/master.cf}} uncomment:
+
There are basically 2 ways for of doing SMTPS.
 +
 
 +
One is using the wrapper mode which enables even old/odd clients like Outlook to use TLS. The wrapper mode uses the system service "smtps" which is a non-standard service and runs on port 465.
 +
 
 +
The other, more proper method is to use a port that simply enforces TLS without any wrapping. The system service for this is "submission" which is standard and uses port 587.
 +
 
 +
For the improper variant uncomment this in {{ic|/etc/postfix/master.cf}}:
 
  smtps    inet  n      -      n      -      -      smtpd
 
  smtps    inet  n      -      n      -      -      smtpd
 
   -o smtpd_tls_wrappermode=yes
 
   -o smtpd_tls_wrappermode=yes
 
   -o smtpd_sasl_auth_enable=yes
 
   -o smtpd_sasl_auth_enable=yes
  
To {{filename|/etc/postfix/main.cf}} append:
+
And verify that these lines are in {{ic|/etc/services}}:
 +
smtps 465/tcp # Secure SMTP
 +
smtps 465/udp # Secure SMTP
 +
 
 +
otherwise posfix won't start :
 +
 
 +
''postfix/master[5309]: fatal: 0.0.0.0:smtps: Servname not supported for ai_socktype''
 +
 
 +
For the proper variant uncomment this in {{ic|/etc/postfix/master.cf}}:
 +
smtp    inet  n      -      n      -      -      smtpd
 +
submission    inet  n      -      n      -      -      smtpd
 +
  -o smtpd_tls_security_level=encrypt
 +
  -o smtpd_sasl_auth_enable=yes
 +
 
 +
 
 +
To {{ic|/etc/postfix/main.cf}} append:
 
  relay_domains = *
 
  relay_domains = *
 
  virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf
 
  virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf
Line 46: Line 72:
 
   
 
   
 
  smtpd_sasl_auth_enable = yes
 
  smtpd_sasl_auth_enable = yes
 +
smtpd_sasl_type = dovecot
 +
smtpd_sasl_path = /var/run/dovecot/auth-client
 
  smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
 
  smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
 
  smtpd_sasl_security_options = noanonymous
 
  smtpd_sasl_security_options = noanonymous
 
  smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
 
  smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
 
  smtpd_tls_auth_only = yes
 
  smtpd_tls_auth_only = yes
  smtpd_tls_cert_file = /etc/ssl/certs/server.crt
+
  smtpd_tls_cert_file = /etc/ssl/private/server.crt
 
  smtpd_tls_key_file = /etc/ssl/private/server.key
 
  smtpd_tls_key_file = /etc/ssl/private/server.key
 
  smtpd_sasl_local_domain = $mydomain
 
  smtpd_sasl_local_domain = $mydomain
Line 56: Line 84:
 
  smtpd_tls_loglevel = 1
 
  smtpd_tls_loglevel = 1
  
This references a lot of files that don't even exist yet. Let's create them.
+
This references a lot of files that do not even exist yet. Let's create them.
  
Edit {{filename|/etc/postfix/virtual_alias_maps.cf}} as new and add:
+
Edit {{ic|/etc/postfix/virtual_alias_maps.cf}} as new and add:
 
  user = postfix_user
 
  user = postfix_user
 
  password = hunter2
 
  password = hunter2
Line 65: Line 93:
 
  query = SELECT goto FROM alias WHERE address='%s' AND active = true
 
  query = SELECT goto FROM alias WHERE address='%s' AND active = true
  
Edit {{filename|/etc/postfix/virtual_domains_maps.cf}} as new and add:
+
Edit {{ic|/etc/postfix/virtual_domains_maps.cf}} as new and add:
 
  user = postfix_user
 
  user = postfix_user
 
  password = hunter2
 
  password = hunter2
 
  hosts = localhost
 
  hosts = localhost
 
  dbname = postfix_db
 
  dbname = postfix_db
  query = SELECT domain FROM domain WHERE domain='%s' and backupmx = false and active = true
+
  query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = false AND active = true
  
Edit {{filename|/etc/postfix/virtual_mailbox_limits.cf}} as new and add:
+
Edit {{ic|/etc/postfix/virtual_mailbox_limits.cf}} as new and add:
 
  user = postfix_user
 
  user = postfix_user
 
  password = hunter2
 
  password = hunter2
Line 79: Line 107:
 
  query = SELECT quota FROM mailbox WHERE username='%s'
 
  query = SELECT quota FROM mailbox WHERE username='%s'
  
Edit {{filename|/etc/postfix/virtual_mailbox_maps.cf}} as new and add:
+
Edit {{ic|/etc/postfix/virtual_mailbox_maps.cf}} as new and add:
 
  user = postfix_user
 
  user = postfix_user
 
  password = hunter2
 
  password = hunter2
Line 93: Line 121:
 
  openssl req -new -x509 -newkey rsa:1024 -days 365 -keyout server.key -out server.crt
 
  openssl req -new -x509 -newkey rsa:1024 -days 365 -keyout server.key -out server.crt
 
  openssl rsa -in server.key -out server.key
 
  openssl rsa -in server.key -out server.key
  chown nobody:nobody server.key
+
  chown nobody:nobody server.key server.crt
  chmod 600 server.key
+
  chmod 400 server.key
 +
chmod 444 server.crt
 
  mv server.key /etc/ssl/private/
 
  mv server.key /etc/ssl/private/
 +
mv server.crt /etc/ssl/private/
  
=== Courier ===
+
=== Dovecot ===
In {{filename|/etc/authlib/authdaemonrc}} make sure that ''authmodulelist'' only contains ''authmysql'':
+
Start by getting a fresh config file from the pre-existing sample config:
authmodulelist="authmysql"
+
cp /etc/dovecot/dovecot.conf.sample /etc/dovecot/dovecot.conf
  
Next, we need to configure the field names used by PostfixAdmin in {{filename|/etc/authlib/authmysqlrc}}. Search and replace values provided here. Uncomment commented entries if necessary:
+
In {{ic|/etc/dovecot/dovecot.conf}} we'll need to do quite some configuration:
  MYSQL_HOST          localhost
+
  protocols = imap pop3
  MYSQL_PORT          3306
+
  auth_mechanisms = plain
  MYSQL_USERNAME     postfix_user
+
  passdb {
MYSQL_PASSWORD     hunter2
+
     driver = sql
  MYSQL_DATABASE     postfix_db
+
     args = /etc/dovecot/dovecot-sql.conf
  MYSQL_USER_TABLE    mailbox
+
  }
  MYSQL_CRYPT_PWFIELD password
+
userdb sql {
  MYSQL_UID_FIELD    5000
+
     driver = sql
  MYSQL_GID_FIELD    5000
+
    args = /etc/dovecot/dovecot-sql.conf
  MYSQL_LOGIN_FIELD  username
+
  }
  MYSQL_HOME_FIELD    "/home/vmail"
+
   
  MYSQL_NAME_FIELD    name
+
  service auth {
  MYSQL_MAILDIR_FIELD maildir
+
    unix_listener auth-client {
  MYSQL_QUOTA_FIELD  quota
+
        group = postfix
 +
        mode = 0660
 +
        user = postfix
 +
    }
 +
    user = root
 +
  }
 +
   
 +
  mail_home = /home/vmail/%d/%u
 +
  mail_location = maildir:~
 +
   
 +
  ssl_cert = </etc/ssl/private/server.crt
 +
ssl_key = </etc/ssl/private/server.key
  
Edit the ''[ reg_dn ]'' part in {{filename|/etc/imapd.cnf}} and {{filename|/etc/pop3d.cnf}} to correctly state your mail server's location. E.g.:
+
See http://wiki2.dovecot.org/Variables for the docevot variables %d and %u.
[ req_dn ]
+
C=DE
+
ST=Hamburg
+
L=Hamburg
+
O=Courier Mail Server
+
OU=Automatically-generated IMAP SSL key
+
CN=localhost
+
emailAddress=god@world.com
+
  
Next, generate the certificates and move them into position:
+
Now obviously we also need the {{ic|/etc/dovecot/dovecot-sql.conf}} we just referenced in the config above. Go ahead and create a {{ic|/etc/dovecot/dovecot-sql.conf}} with these contents:
  mkimapdcert
+
  driver = mysql
  mv /usr/share/imapd.pem /etc/courier-imap/
+
  connect = host=localhost dbname=postfix_db user=postfix_user password=hunter2
  mkpop3dcert
+
# The new name for MD5 is MD5-CRYPT so you might need to change this depending on version
  mv /usr/share/pop3d.pem /etc/courier-imap/
+
default_pass_scheme = MD5-CRYPT
 +
# Get the mailbox
 +
user_query = SELECT '/home/vmail/%d/%u' as home, 'maildir:/home/vmail/%d/%u' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
 +
  # Get the password
 +
  password_query = SELECT username as user, password, '/home/vmail/%d/%u' as userdb_home, 'maildir:/home/vmail/%d/%u' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
 +
# If using client certificates for authentication, comment the above and uncomment the following
 +
#password_query = SELECT null AS password, ‘%u’ AS user
  
=== Cyrus ===
+
=== PostfixAdmin ===
Firstly, edit {{filename|/etc/services}} and add
+
To install PostfixAdmin, we need to manually get its upstream package and extract it to our web root (or other desired directory). You should use the most recent version available at the time. This article will use the most recent version at the time of writing.
  smtps          465/tcp  # Secure Simple Mail Transfer
+
  cd /srv/http/
  smtps          465/udp  # Secure Simple Mail Transfer
+
  wget http://sourceforge.net/projects/postfixadmin/files/postfixadmin/postfixadmin-2.3.5/postfixadmin-2.3.5.tar.gz/download
to it.
+
tar xzf postfixadmin-2.3.5.tar.gz
 +
cd postfixadmin-2.3.5
  
Contents of {{filename|/etc/pam.d/smtp}} should be:
+
Next, PostfixAdmin needs to be configured. First edit the config.inc.php file :
  auth required /lib/security/pam_mysql.so user=postfix_user passwd=hunter2 host=localhost db=postfix_db table=mailbox usercolumn=username passwdcolumn=password crypt=1
+
  $CONF['configured'] = true;
  account sufficient /lib/security/pam_mysql.so user=postfix_user passwd=hunter2 host=localhost db=postfix_db table=mailbox usercolumn=username passwdcolumn=password crypt=1
+
  // correspond to dovecot maildir path /home/vmail/%d/%u
 +
$CONF['domain_path'] = 'YES';
 +
$CONF['domain_in_mailbox'] = 'YES';
  
Modify {{filename|/etc/conf.d/saslauthd}} to say:
+
$CONF['database_type'] = 'mysql';
  SASLAUTHD_OPTS="-m /var/run/saslauthd -r -a pam"
+
$CONF['database_host'] = 'localhost';
 +
$CONF['database_user'] = 'postfix_user';
 +
$CONF['database_password'] = 'hunter2';
 +
  $CONF['database_name'] = 'postfix_db';
  
Finally, {{filename|/usr/lib/sasl2/smtpd.conf}} should have:
+
   
  pwcheck_method: saslauthd
+
Then assuming localhost is the hostname of the machine you are installing this on, navigate to ''http://localhost/postfixadmin-2.3.5/setup.php''. The setup will guide you through the remaining steps to set up PostfixAdmin.
mech_list: plain login
+
saslauthd_path: /var/run/saslauthd/mux
+
log_level: 7
+
  
=== PostfixAdmin ===
 
To install PostfixAdmin, we need to manually get its upstream package and extract it to our web root (or other desired directory). You should use the most recent version available at the time. This article will use the most recent version at the time of writing.
 
cd /srv/http/
 
wget http://sourceforge.net/projects/postfixadmin/files/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz/download
 
tar xzf postfixadmin-2.3.2.tar.gz
 
cd postfixadmin-2.3.2
 
  
Next, PostfixAdmin needs to be configured. Assuming localhost is the hostname of the machine you are installing this on, navigate to ''http://localhost/postfixadmin-2.3.2/setup.php''. The setup will guide you through the remaining steps to set up PostfixAdmin.
+
{{Note|For a detailed section on setting up domains and mailboxes in PostfixAdmin see the related [[http://en.gentoo-wiki.com/wiki/Mail_server_using_Postfix_and_Dovecot#Setting_up_Mailboxes| Gentoo wiki article]] }}
  
 
=== Roundcube ===
 
=== Roundcube ===
 
As with PostfixAdmin, this article will use the most recent version as of the time of writing. You should always use the most recent version available.
 
As with PostfixAdmin, this article will use the most recent version as of the time of writing. You should always use the most recent version available.
 
  cd /srv/http/
 
  cd /srv/http/
  wget http://sourceforge.net/projects/roundcubemail/files/roundcubemail/0.4/roundcubemail-0.4.tar.gz/download
+
  wget http://sourceforge.net/projects/roundcubemail/files/roundcubemail/0.7.2/roundcubemail-0.7.2.tar.gz/download
  tar xzf roundcubemail-0.4.tar.gz
+
  tar xzf roundcubemail-0.7.2.tar.gz
  cd roundcubemail-0.4
+
  cd roundcubemail-0.7.2
  
 
Make some directories writable by the webserver:
 
Make some directories writable by the webserver:
 
  chown -R http:http temp logs
 
  chown -R http:http temp logs
  
Assuming that localhost is your current host, navigate a browser to ''http://localhost/roundcubemail-0.4/installer/'' and follow the instructions. You could use the same database for Roundcube that you already used for PostfixAdmin though you shouldn't. For a proper setup, create a second database "roundcube_db" and a "roundcube_user" for use with Roundcube.  
+
Assuming that localhost is your current host, navigate a browser to ''http://localhost/roundcubemail-0.7.2/installer/'' and follow the instructions. You could use the same database for Roundcube that you already used for PostfixAdmin though you shouldn't. For a proper setup, create a second database "roundcube_db" and a "roundcube_user" for use with Roundcube.  
  
While running the installer, make sure to address the IMAP host with '''tls://localhost/''' instead of just '''localhost'''. Use port 993. Likewise with SMTP, make sure to provide '''ssl://localhost/''' on port 465.
+
While running the installer, make sure to address the IMAP host with '''ssl://localhost/''' instead of just '''localhost'''. Use port 993. Likewise with SMTP, make sure to provide '''ssl://localhost/''' on port 465 if you used the wrapper mode and '''tls://localhost/''' on port 587 if you used the proper TLS mode. See [[#Postfix|here]] for an explanation on that.
  
=== rc.conf ===
+
=== systemd ===
The services should be restarted in the correct order on system restart. Make sure your DAEMONS array in {{filename|/etc/rc.conf}} contains:
+
Make sure your daemons start on boot:
  DAEMONS=( ... fam saslauthd postfix authdaemond imapd imapd-ssl pop3d pop3d-ssl ... )
+
  systemctl enable dovecot postfix
Make sure to keep this order.
+
  
 
== Fire it up ==
 
== Fire it up ==
Since now hopefully everything is set up correctly, all necessary daemon should be started for a test run:
+
Since now hopefully everything is set up correctly, all necessary daemons should be started for a test run:
  for daemon in fam saslauthd postfix authdaemond courier-imap; do /etc/rc.d/$daemon start; done
+
  systemctl start postfix dovecot
The order in which the daemons are started up is actually important here.
+
 
+
As a final bit of configuration, Postfix needs to be able to write to saslauth. Thus:
+
chown postfix:postfix /var/run/saslauthd
+
  
 
Now for testing purposes, create a domain and mail account in PostfixAdmin. Try to login to this account using Roundcube. Now send yourself a mail.
 
Now for testing purposes, create a domain and mail account in PostfixAdmin. Try to login to this account using Roundcube. Now send yourself a mail.
 +
 +
== Troubleshooting ==
 +
If you get errors like your imap/pop3 client failing to receive mails, take a look into your /var/log/mail.log file.
 +
It turned out that the maildir /home/vmail/mail@domain.tld is just being created if there is at least one email waiting. Otherwise there wouldn't be any need for the directory.
  
 
==See also==
 
==See also==

Revision as of 12:34, 1 March 2013


This article describes how to set up a complete virtual user mail system on an Arch Linux system in the simplest manner possible. However, since a mail system consists of many complex components, quite a bit of configuration will still be necessary. Roughly, the components used in this article are Postfix, Dovecot, PostfixAdmin and Roundcube.

In the end, the provided solution will allow you to use the best currently available security mechanisms, you will be able to send mails using SMTP and SMTPS and receive mails using POP3, POP3S, IMAP and IMAPS. Additionally, configuration will be easy thanks to PostfixAdmin and users will be able to login using Roundcube. What a deal!

This article assumes that you have a working LAMP setup as we will need a working Apache2 as well as MYSQL database. Of course, with a few changes to these instructions you could easily use another httpd and database. For the purposes of this tutorial, however, the choice made above will be used. Additionally, the article assumes all-default settings for every package installed below. No changes except for those mentioned will be required.

Should any unforeseen problems occur, feel free to use the discussion page to voice your problems and I will try to answer.

Installation

# pacman -S dovecot postfix

Configuration

User

For security reasons, a new user should be created to store the mails:

groupadd -g 5000 vmail
useradd -u 5000 -g vmail -s /sbin/nologin -d /home/vmail -m vmail

A gid and uid of 5000 is used in both cases so that we do not run into conflicts with regular users. All your mail will then be stored in /home/vmail. You could change the home dir to something like /var/mail/vmail but careful to change this in any configuration below as well.

Database

You will need to create an empty database and corresponding user. We will be using PostfixAdmin's tables to fill the database later on. In this article, postfix_user will have read/write access to postfix_db using hunter2 for a password. You are expected to create your database and user yourself as shown in the following code. Make sure to assign proper permissions.

$> mysql -u root -p
password:
CREATE SCHEMA `postfix_db` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
CREATE USER 'postfix_user'@'localhost' IDENTIFIED BY 'hunter2';
GRANT ALL ON `postfix_db`.* TO `postfix_user`@`localhost`;

Postfix

There are basically 2 ways for of doing SMTPS.

One is using the wrapper mode which enables even old/odd clients like Outlook to use TLS. The wrapper mode uses the system service "smtps" which is a non-standard service and runs on port 465.

The other, more proper method is to use a port that simply enforces TLS without any wrapping. The system service for this is "submission" which is standard and uses port 587.

For the improper variant uncomment this in /etc/postfix/master.cf:

smtps     inet  n       -       n       -       -       smtpd
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes

And verify that these lines are in /etc/services:

smtps 465/tcp # Secure SMTP
smtps 465/udp # Secure SMTP

otherwise posfix won't start :

postfix/master[5309]: fatal: 0.0.0.0:smtps: Servname not supported for ai_socktype

For the proper variant uncomment this in /etc/postfix/master.cf:

smtp     inet  n       -       n       -       -       smtpd
submission     inet  n       -       n       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes


To /etc/postfix/main.cf append:

relay_domains = *
virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/virtual_domains_maps.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/virtual_mailbox_maps.cf
virtual_mailbox_base = /home/vmail
virtual_mailbox_limit = 512000000
virtual_minimum_uid = 5000
virtual_transport = virtual
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps
transport_maps = hash:/etc/postfix/transport

smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = /var/run/dovecot/auth-client
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_security_options = noanonymous
smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/ssl/private/server.crt
smtpd_tls_key_file = /etc/ssl/private/server.key
smtpd_sasl_local_domain = $mydomain
broken_sasl_auth_clients = yes
smtpd_tls_loglevel = 1

This references a lot of files that do not even exist yet. Let's create them.

Edit /etc/postfix/virtual_alias_maps.cf as new and add:

user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
query = SELECT goto FROM alias WHERE address='%s' AND active = true

Edit /etc/postfix/virtual_domains_maps.cf as new and add:

user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = false AND active = true

Edit /etc/postfix/virtual_mailbox_limits.cf as new and add:

user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
query = SELECT quota FROM mailbox WHERE username='%s'

Edit /etc/postfix/virtual_mailbox_maps.cf as new and add:

user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = true

Run postmap on transport to generate its db:

postmap /etc/postfix/transport

We still need the SSL cert and private key:

cd /etc/ssl/certs
openssl req -new -x509 -newkey rsa:1024 -days 365 -keyout server.key -out server.crt
openssl rsa -in server.key -out server.key
chown nobody:nobody server.key server.crt
chmod 400 server.key
chmod 444 server.crt
mv server.key /etc/ssl/private/
mv server.crt /etc/ssl/private/

Dovecot

Start by getting a fresh config file from the pre-existing sample config:

cp /etc/dovecot/dovecot.conf.sample /etc/dovecot/dovecot.conf

In /etc/dovecot/dovecot.conf we'll need to do quite some configuration:

protocols = imap pop3
auth_mechanisms = plain
passdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf
}
userdb sql {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf
}

service auth {
    unix_listener auth-client {
        group = postfix
        mode = 0660
        user = postfix
    }
    user = root
}

mail_home = /home/vmail/%d/%u
mail_location = maildir:~

ssl_cert = </etc/ssl/private/server.crt
ssl_key = </etc/ssl/private/server.key

See http://wiki2.dovecot.org/Variables for the docevot variables %d and %u.

Now obviously we also need the /etc/dovecot/dovecot-sql.conf we just referenced in the config above. Go ahead and create a /etc/dovecot/dovecot-sql.conf with these contents:

driver = mysql
connect = host=localhost dbname=postfix_db user=postfix_user password=hunter2
# The new name for MD5 is MD5-CRYPT so you might need to change this depending on version
default_pass_scheme = MD5-CRYPT
# Get the mailbox
user_query = SELECT '/home/vmail/%d/%u' as home, 'maildir:/home/vmail/%d/%u' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
# Get the password
password_query = SELECT username as user, password, '/home/vmail/%d/%u' as userdb_home, 'maildir:/home/vmail/%d/%u' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
# If using client certificates for authentication, comment the above and uncomment the following
#password_query = SELECT null AS password, ‘%u’ AS user

PostfixAdmin

To install PostfixAdmin, we need to manually get its upstream package and extract it to our web root (or other desired directory). You should use the most recent version available at the time. This article will use the most recent version at the time of writing.

cd /srv/http/
wget http://sourceforge.net/projects/postfixadmin/files/postfixadmin/postfixadmin-2.3.5/postfixadmin-2.3.5.tar.gz/download
tar xzf postfixadmin-2.3.5.tar.gz
cd postfixadmin-2.3.5

Next, PostfixAdmin needs to be configured. First edit the config.inc.php file :

$CONF['configured'] = true;
// correspond to dovecot maildir path /home/vmail/%d/%u 
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'YES';
$CONF['database_type'] = 'mysql';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix_user';
$CONF['database_password'] = 'hunter2';
$CONF['database_name'] = 'postfix_db';


Then assuming localhost is the hostname of the machine you are installing this on, navigate to http://localhost/postfixadmin-2.3.5/setup.php. The setup will guide you through the remaining steps to set up PostfixAdmin.


Note: For a detailed section on setting up domains and mailboxes in PostfixAdmin see the related [Gentoo wiki article]

Roundcube

As with PostfixAdmin, this article will use the most recent version as of the time of writing. You should always use the most recent version available.

cd /srv/http/
wget http://sourceforge.net/projects/roundcubemail/files/roundcubemail/0.7.2/roundcubemail-0.7.2.tar.gz/download
tar xzf roundcubemail-0.7.2.tar.gz
cd roundcubemail-0.7.2

Make some directories writable by the webserver:

chown -R http:http temp logs

Assuming that localhost is your current host, navigate a browser to http://localhost/roundcubemail-0.7.2/installer/ and follow the instructions. You could use the same database for Roundcube that you already used for PostfixAdmin though you shouldn't. For a proper setup, create a second database "roundcube_db" and a "roundcube_user" for use with Roundcube.

While running the installer, make sure to address the IMAP host with ssl://localhost/ instead of just localhost. Use port 993. Likewise with SMTP, make sure to provide ssl://localhost/ on port 465 if you used the wrapper mode and tls://localhost/ on port 587 if you used the proper TLS mode. See here for an explanation on that.

systemd

Make sure your daemons start on boot:

systemctl enable dovecot postfix

Fire it up

Since now hopefully everything is set up correctly, all necessary daemons should be started for a test run:

systemctl start postfix dovecot

Now for testing purposes, create a domain and mail account in PostfixAdmin. Try to login to this account using Roundcube. Now send yourself a mail.

Troubleshooting

If you get errors like your imap/pop3 client failing to receive mails, take a look into your /var/log/mail.log file. It turned out that the maildir /home/vmail/mail@domain.tld is just being created if there is at least one email waiting. Otherwise there wouldn't be any need for the directory.

See also