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.