Setup your own mail hosting with Linux, Postfix, Dovecot and MySQL


I’ve written a new post on this topic, with an easier setup using an installer that installs and set’s up everything.

See set up your own mail server >>

If you want to set up your own mail hosting, just follow this guide.
I will use Debian Squeeze as the OS.

You are assumed to have your own server or VPS with root access.

Step 1

Install the required packages.

apt-get install postfix postfix-mysql postfix-doc mysql-client mysql-server dovecot-common dovecot-imapd dovecot-pop3d libsasl2-2 libsasl2-modules libsasl2-modules-sql sasl2-bin libpam-mysql openssl telnet mailutils

When the GUI for MySQL password pops up, pick a secure password and dont loose it!
Then it’s time for Postfix.
In the first step of the Postfix installation, choose “Internet Site”. On the next screen, choose a domain name for your mail server. This has nothing to do with your future email addresses.

Step 2

Set up MySQL for domains, users and email addresses.
Type

mysql -u root -p

and enter your password you chose in Step 1.
Now you should be in the mysql shell.
Type these commands, one at a time. Choose your own password

CREATE DATABASE mail;
USE mail;
GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost' IDENTIFIED BY 'mail_admin_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost.localdomain' IDENTIFIED BY 'mail_admin_password';
FLUSH PRIVILEGES;
CREATE TABLE domains (domain varchar(50) NOT NULL, PRIMARY KEY (domain) );
CREATE TABLE forwardings (source varchar(80) NOT NULL, destination TEXT NOT NULL, PRIMARY KEY (source) );
CREATE TABLE users (email varchar(80) NOT NULL, password varchar(20) NOT NULL, PRIMARY KEY (email) );
CREATE TABLE transport ( domain varchar(128) NOT NULL default '', transport varchar(128) NOT NULL default '', UNIQUE KEY domain (domain) );
quit

Restart MySQL

/etc/inid.d/mysql restart

Step 3

Now it’s time to configure Postfix to use MySQL to check for mailboxes.
Lets create some files and configs.

nano /etc/postfix/mysql-virtual_domains.cf

Add this to the file you just created. Be sure you use the same password as earlier:

user = mail_admin
password = mail_admin_password
dbname = mail
query = SELECT domain AS virtual FROM domains WHERE domain='%s'
hosts = 127.0.0.1

Another file, for mail forwarding.

nano /etc/postfix/mysql-virtual_forwardings.cf

And add this

user = mail_admin
password = mail_admin_password
dbname = mail
query = SELECT destination FROM forwardings WHERE source='%s'
hosts = 127.0.0.1

And another one, for the mail boxes.

nano /etc/postfix/mysql-virtual_mailboxes.cf

And add this

user = mail_admin
password = mail_admin_password
dbname = mail
query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s'
hosts = 127.0.0.1

And the last one for matching users to addresses.

nano /etc/postfix/mysql-virtual_email2email.cf

And add this

user = mail_admin
password = mail_admin_password
dbname = mail
query = SELECT email FROM users WHERE email='%s'
hosts = 127.0.0.1

Time to make the files readable for Postfix user.

chmod o= /etc/postfix/mysql-virtual_*.cf
chgrp postfix /etc/postfix/mysql-virtual_*.cf

Step 4

Make mailboxes for users under a new linux users home directory.

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /home/vmail -m

Step 5

Time to configure Postfix and Dovecot some more. Change server.example.com to your domain you added in Step 1.

postconf -e 'myhostname = server.example.com'
postconf -e 'mydestination = server.example.com, localhost, localhost.localdomain'
postconf -e 'mynetworks = 127.0.0.0/8'
postconf -e 'message_size_limit = 30720000'
postconf -e 'virtual_alias_domains ='
postconf -e 'virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf'
postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf'
postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf'
postconf -e 'virtual_mailbox_base = /home/vmail'
postconf -e 'virtual_uid_maps = static:5000'
postconf -e 'virtual_gid_maps = static:5000'
postconf -e 'smtpd_sasl_auth_enable = yes'
postconf -e 'broken_sasl_auth_clients = yes'
postconf -e 'smtpd_sasl_authenticated_header = yes'
postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination'
postconf -e 'smtpd_use_tls = yes'
postconf -e 'smtpd_tls_cert_file = /etc/postfix/smtpd.cert'
postconf -e 'smtpd_tls_key_file = /etc/postfix/smtpd.key'
postconf -e 'virtual_create_maildirsize = yes'
postconf -e 'virtual_maildir_extended = yes'
postconf -e 'proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps'
postconf -e virtual_transport=dovecot
postconf -e dovecot_destination_recipient_limit=1

Step 6

Create a SSL cert for encrypted traffic to the server.

cd /etc/postfix
openssl req -new -outform PEM -out smtpd.cert -newkey rsa:2048 -nodes -keyout smtpd.key -keyform PEM -days 365 -x509

Be sure to write your domain name added in Step 1 under “Common Name” when it comes up.
And then set the permissions for the cert.

chmod o= /etc/postfix/smtpd.key

Step 7

Add saslauthd for authing your users. One row at a time.

mkdir -p /var/spool/postfix/var/run/saslauthd
cp -a /etc/default/saslauthd /etc/default/saslauthd.bak

Edit the file /etc/default/saslauthd.
Add this:

START=yes
DESC="SASL Authentication Daemon"
NAME="saslauthd"
MECHANISMS="pam"
MECH_OPTIONS=""
THREADS=5
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -r"

Add a new file named /etc/pam.d/smtp.
Add this to it (be sure to use your own mysql user and password):

auth    required   pam_mysql.so user=mail_admin passwd=mail_admin_password host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1
account sufficient pam_mysql.so user=mail_admin passwd=mail_admin_password host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1

Now, create a new file named /etc/postfix/sasl/smtpd.conf and add this to it.

pwcheck_method: saslauthd
mech_list: plain login
allow_plaintext: true
auxprop_plugin: mysql
sql_hostnames: 127.0.0.1
sql_user: mail_admin
sql_passwd: mail_admin_password
sql_database: mail
sql_select: select password from users where email = '%u'

Set the right permissions and restart. One row at a time.

chmod o= /etc/pam.d/smtp
chmod o= /etc/postfix/sasl/smtpd.conf
adduser postfix sasl
/etc/init.d/postfix restart
/etc/init.d/saslauthd restart

Step 8

Now it’s almost the last step. Configure Dovecot to use MySQL to serve you with email via IMAP/POP3.
First, tell Postfix to use Dovecot.

dovecot   unix  -       n       n       -       -       pipe
    flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}

Then, add this to the file /etc/dovecot/dovecot.conf

protocols = imap imaps pop3 pop3s
log_timestamp = "%Y-%m-%d %H:%M:%S "
mail_location = maildir:/home/vmail/%d/%n/Maildir

ssl_cert_file = /etc/ssl/certs/dovecot.pem
ssl_key_file = /etc/ssl/private/dovecot.pem

namespace private {
    separator = .
    prefix = INBOX.
    inbox = yes
}

protocol lda {
    log_path = /home/vmail/dovecot-deliver.log
    auth_socket_path = /var/run/dovecot/auth-master
    postmaster_address = postmaster@example.com
    mail_plugins = sieve
    global_script_path = /home/vmail/globalsieverc
}

protocol pop3 {
    pop3_uidl_format = %08Xu%08Xv
}

auth default {
    user = root

    passdb sql {
        args = /etc/dovecot/dovecot-sql.conf
    }

    userdb static {
        args = uid=5000 gid=5000 home=/home/vmail/%d/%n allow_all_users=yes
    }

    socket listen {
        master {
            path = /var/run/dovecot/auth-master
            mode = 0600
            user = vmail
        }

        client {
            path = /var/spool/postfix/private/auth
            mode = 0660
            user = postfix
            group = postfix
        }
    }
}

Dovecot will use MySQL for auth, so replace the contents of /etc/dovecot/dovecot-sql.conf with the following. As always, replace with your mysql user and password.

driver = mysql
connect = host=127.0.0.1 dbname=mail user=mail_admin password=mail_admin_password
default_pass_scheme = CRYPT
password_query = SELECT email as user, password FROM users WHERE email='%u';

Then, restart Dovecot and set permissions.

/etc/init.d/dovecot restart
chgrp vmail /etc/dovecot/dovecot.conf
chmod g+r /etc/dovecot/dovecot.conf

Step 9

Add users and domains!

mysql -u root -p
USE mail;
INSERT INTO domains (domain) VALUES ('example.com');
INSERT INTO users (email, password) VALUES ('mynewmail@example.com', ENCRYPT('password'));
quit

You have to send an email before the user can access the account. Install mailx of you dont have it.

mailx mynewmail@example.xom

Ctrl+D sends the mail.

Check the logs to see if everything is ok.

tail /var/log/mail.log
tail /home/vmail/dovecot-deliver.log

Step 10

To actually receive mail for your own domain, you have to set the MX-record on the domain name.
server.example.com should be the one you chose in Step 1.
Add this to your DNS for the domain added in Step 9.

@ IN 3600 MX 1 server.example.com.
@ IN 3600 TXT "v=spf1 a mx ~all"

Step 11

In your mail client, add a new account with IMAP and SMTP with host server.example.com and the user and password you added in Step 9. Answer yes if you get asked if you want to trust the connection. It’s there because you made your own SSL-cert and it’s perfectly safe.

A side note, Apple Mail needs to be restarted to start fetching mail.

This guide will be followed up with a guide how to set up a GUI for adding more domains and mailboxes. And probably another guide how to set up a redundant mail server so you wont loose any emails if this server goes down.


I’ve written a new post on this topic, with an easier setup using an installer that installs and set’s up everything.

See set up your own mail server >>