Host Your Own Private Home Email Server

Background

The availability and prevalence of high-quality gratis email providers has made people take for granted the true cost of using these services. These companies are hoping they can collect enough valuable information from reading your emails that they can make up the difference of providing you the service at no cost. A necessary step to regain control over your email and maintain your privacy is to host your own private email server using free (as in freedom) software.

There are several components involved in a email server and you have choices to make between alternative free software projects. At a high level, the the primary components are the MTA, MDA, and MUA.

Mail Transfer Agent (MTA)

A Mail Transer Agent (MTA) uses SMTP to send/receive emails. I recommend Postfix unless special circumstances require the features of the alternative MTAs.

  • Sendmail – perhaps the most well known MTA but notoriously hard to configure and a poor history of security breaches
  • qmail – ideal for size constrained environment but doesn’t support modern email standards
  • exim – very flexible, powerful, and general purpose, but not as fast as or secure as Postfix
  • Postfix – modern, secure, and efficient, but has a restricted feature set by design
Mail Delivery Agent (MDA)

A Mail Delivery Agent (MDA) receives messages from a MTA and delivers the mail to a local mailbox typically using either Post Office Protocol (POP) or Internet Message Access Protocol (IMAP). I recommend Dovecot over the alternatives.

  • Cyrus – difficult to configure and non-standard format
  • Courier – consumes more server resources, slower, and less secure than dovecot
  • Dovecot – modern, fast, and secure
Mail User Agent (MUA)

A Mail User Agent (MUA) is a program used by the end user to read and process mail. A MUA can be a local email client such as Thunderbird or it can be a remote webmail server that provides access to clients via a web browser. If you want to host a webmail server, I recommend Roundcube unless you desire the additional features offered by Horde such as mobile email access.

  • Squirrelmail – very simple but doesn’t have spell check or support HTML composition
  • Horde – has more complete features such as mobile email access, advanced productivity features including event reminders, news feed, notes, and a calendar
  • Roundcube – very user friendly, modern, and pretty

Setup PHP and MySQL

Prerequisites

On Debian 9 GNU/Linux, install the following PHP and MySQL packages:

sudo apt-get install -y php5-fpm php5-imap php5-mysql php5-mcrypt php5-intl mysql-server mysql-client
Configuration

Set the timezone in the PHP configuration file:

sudo sed -i -e 's/^;date\.timezone =$/date.timezone = America\/Chicago/' /etc/php5/fpm/php.ini

Create a new user and group:

sudo groupadd -g 1001 g1001
sudo useradd --no-create-home -g 1001 -u 1001 u1001

Create PHP fpm socket directory:

sudo mkdir -p /etc/php5/fpm/socks

Remove the default FastCGI Process Manager (FPM) pool:

sudo rm -f /etc/php5/fpm/pool.d/www.conf

Create a new fpm pool configuration file /etc/php5/fpm/pool.d/ssl_example.com.conf and copy into it the following content.

[ssl_example.com]
listen = /etc/php5/fpm/socks/ssl_example.com.sock
user = u1001
group = g1001
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
pm = dynamic
pm.max_children = 50
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 5
pm.max_requests = 0
php_admin_value[open_basedir]=/
php_admin_value[session.save_path]=/home/clients_ssl/example.com/tmp
php_admin_value[upload_tmp_dir]=/home/clients_ssl/example.com/tmp
php_admin_value[disable_functions]=dl

Ensure that the file has the proper permissions:

sudo chmod 644 /etc/php5/fpm/pool.d/ssl_example.com.conf

Start the PHP FPM service:

sudo systemctl start php5-fpm.service

Setup Postfix

Prerequisites

On Debian 9 GNU/Linux, install the following Postfix packages:

sudo apt-get install -y posftfixadmin libsasl2-modules libsasl2-modules-sql postfix postfix-mysql
Configuration

Create the postfix database.

sudo mysql -u root -p dbpassword1 -e "CREATE DATABASE postfix; GRANT ALL PRIVILEGES ON postfix.* TO 'postfix_admin'@'%' IDENTIFIED BY 'dbpassword1'; GRANT SELECT ON postfix.* TO 'postfix'@'%' IDENTIFIED BY 'dbpassword2'; FLUSH PRIVILEGES;"

Create /etc/postfix/main.cf with the following contents:

myorigin = /etc/mailname
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
readme_directory = no
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = myhost.example.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = localhost
relayhost = [smtp.myisp.net]:587
mynetworks = 127.0.0.0/8 192.168.253.0/24 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
virtual_uid_maps = static:3000
virtual_gid_maps = static:3000
virtual_mailbox_base = /home/vmail
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_mailbox_domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
relay_domains = mysql:/etc/postfix/mysql_relay_domains.cf
virtual_transport = lmtp:unix:private/dovecot-lmtp
smtpd_recipient_restrictions =
 permit_mynetworks,
 permit_sasl_authenticated,
 reject_non_fqdn_hostname,
 reject_non_fqdn_sender,
 reject_non_fqdn_recipient,
 reject_unauth_destination,
 check_policy_service unix:private/policyd-spf,
 reject_unauth_pipelining,
 reject_invalid_hostname
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options =
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth

Create /etc/postfix/mysql_virtual_mailbox_domains.cf with the following contents:

hosts = 127.0.0.1
user = postfix
password = dbpassword
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = 0 and active = 1

Create /etc/postfix/mysql_virtual_mailbox_maps.cf with the following contents:

hosts = 127.0.0.1
user = postfix
password = dbpassword
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = 1

Create /etc/postfix/mysql_virtual_alias_maps.cf with the following contents:

hosts = 127.0.0.1
user = postfix
password = dbpassword
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = 1

Create /etc/postfix/mysql_relay_domains.cf with the following contents:

hosts = 127.0.0.1
user = postfix
password = dbpassword
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = 1

Create /etc/postfix/master.cf with the following contents:

smtp inet n - y - - smtpd -v
submission inet n - y - - smtpd
 -o syslog_name=postfix/submission
 -o smtpd_tls_security_level=encrypt
 -o smtpd_sasl_auth_enable=yes
 -o smtpd_client_restrictions=permit_sasl_authenticated,reject
 -o milter_macro_daemon_name=ORIGINATING
smtps inet n - y - - smtpd
 -o syslog_name=postfix/smtps
 -o smtpd_tls_wrappermode=yes
 -o smtpd_sasl_auth_enable=yes
 -o smtpd_client_restrictions=permit_sasl_authenticated,reject
 -o milter_macro_daemon_name=ORIGINATING
pickup unix n - y 60 1 pickup
cleanup unix n - y - 0 cleanup
qmgr unix n - n 300 1 qmgr
tlsmgr unix - - y 1000? 1 tlsmgr
rewrite unix - - y - - trivial-rewrite
bounce unix - - y - 0 bounce
defer unix - - y - 0 bounce
trace unix - - y - 0 bounce
verify unix - - y - 1 verify
flush unix n - y 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - y - - smtp
relay unix - - y - - smtp
showq unix n - y - - showq
error unix - - y - - error
retry unix - - y - - error
discard unix - - y - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - y - - lmtp
anvil unix - - y - 1 anvil
scache unix - - y - 1 scache
maildrop unix - n n - - pipe
 flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
uucp unix - n n - - pipe
 flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
ifmail unix - n n - - pipe
 flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp unix - n n - - pipe
 flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix - n n - 2 pipe
 flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman unix - n n - - pipe
 flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
 ${nexthop} ${user}
policyd-spf unix - n n - 0 spawn
 user=policyd-spf argv=/usr/bin/policyd-spf

Create vmail user and group:

sudo groupadd -g 3000 vmail
sudo useradd -d /home/vmail -m -u 3000 -g 3000 vmail
sudo adduser postfix sasl

Start the postfix service:

sudo systemctl start postfix.service

Setup Dovecot

Prerequisites

On Debian 9 GNU/Linux, install the following Dovecot packages:

sudo apt-get install -y dovecot-core dovecot-mysql
Configuration

Configure /etc/dovecot/dovecot-sql.conf.ext:

driver = mysql
connect = host=127.0.0.1 dbname=postfix user=root password=dbpassword
default_pass_scheme = MD5
user_query = \
 SELECT '/home/vmail/%d/%n' as home, 3000 AS uid, 3000 AS gid \
 FROM mailbox WHERE username = '%u'
password_query = \
 SELECT password \
 FROM mailbox WHERE username = '%u'

Configure /etc/dovecot/conf.d/10-auth.conf:

auth_mechanisms = plain login
!include auth-sql.conf.ext

Configure /etc/dovecot/conf.d/10-mail.conf:

mail_location = maildir:/home/vmail/%d/%n:INDEX=/home/vmail/%d/%n/indexes
namespace inbox {
 inbox = yes
}

Configure /etc/dovecot/conf.d/10-ssl.conf:

ssl = no
ssl_cert = </etc/dovecot/dovecot.pem
ssl_key = </etc/dovecot/private/dovecot.pem

Configure /etc/dovecot/conf.d/20-imap.conf:

protocol imap {
 mail_max_userip_connections = 10
}

Configure /etc/dovecot/conf.d/auth-sql.conf.ext:

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

Configure /etc/dovecot/conf.d/10-master.conf:

service imap-login {
 inet_listener imap {
 }
 inet_listener imaps {
 }
}
service pop3-login {
 inet_listener pop3 {
 }
 inet_listener pop3s {
 }
}
service lmtp {
 unix_listener /var/spool/postfix/private/dovecot-lmtp {
 mode = 0600
 user = postfix
 group = postfix
 }
}
service imap {
}
service pop3 {
}
service auth {
 unix_listener auth-userdb {
 }
 unix_listener /var/spool/postfix/private/auth {
 mode = 0666
 }
}
service auth-worker {
}
service dict {
 unix_listener dict {
 }
}

Start the dovecot service:

sudo systemctl start dovecot.service

Setup Roundcube

Prerequisites

On Debian 9 GNU/Linux, install the following Roundcube packages:

sudo apt-get install -y roundcube roundcube-mysql
Configuration

Create and populate roundcube database:

sudo mysql -u root -p dbpassword1 -e "CREATE DATABASE roundcube; GRANT ALL PRIVILEGES ON roundcube.* TO roundcube@localhost IDENTIFIED BY 'rcpassword'; FLUSH PRIVILEGES;"
sudo mysql -u roundcube -p rcpassword < /usr/share/roundcube/SQL/mysql.initial.sql

Enable roundcube and reload apache2 service:

sudo a2enconf roundcube
sudo systemctl reload apache2

Proxy MTA

One challenge you may face if hosting the server at your home is your residential ISP may block incoming connections to TCP port 25 which is required for receiving incoming email on your MTA. One way around this problem is to set your MX record to point at a virtual server that is running a proxy MTA. Then setup a VPN tunnel between your remote virtual server and your local MTA and have the proxy MTA forward all messages to your local MTA.

Conclusion

Hosting your own email server is only the first step to regaining your email privacy. A major challenge is that very few people have the skills, time, or motivation to host their own email servers. As a result, most people you send emails to will be using email providers that spy on their users. Thus, your communication with those people will still be subject to surveillance. Lastly, there is always the issue of plaintext emails being intercepted by a third party. To properly defend against this, you need to share GPG encryption keys and encrypt the contents of the email.