Slackware Mail Server with MySQL, Postfix, and Dovecot25 Apr 2015
This post contains some suggestions for a mildly secure mail server running on a Slackware Linux host. The guide assumes a default, fresh installation of Slackware64 14.1 that includes at least the
N/ package series. By the end of the tutorial, you will have:
- Postfix for encrypted connections over SMTP and removing identifying information from the email headers
- Dovecot for local mail directories and encrypted connections over POP and IMAP
- MariaDB a drop-in replacement for MySQL to store mailbox information
- Postgrey which will require unknown senders to resend their mail, eliminating most spam
- SpamAssassin for e-mail spam filtering based on content-matching rules
- ClamAV to detect trojans, viruses, malware and other malicious threats in your email
- amavisd-new to manage ClamAV and SpamAssasin
- OpenDKIM a DomainKeys Identified Mail (DKIM) milter to sign and/or verify mail
- nginx as a webserver (optional)
- Postfix Admin to manage mailboxes and domains using a TLS secured web user interface (optional)
- Roundcube as a TLS secured webmail client (optional)
There are a number of reasons you may want to host your own email. The Internet of today is not the Internet of yesterday. There is a movement to decentralize the internet and regain control of one’s data. You and others may want to distance yourself from “the stacks”: the internet companies that control a large portion of it. Think of the chaos that ensues whenever CloudFlare’s hardware fucks up and how much of the internet relies on providers like them and Akamai. Think of the companies that have presence in every aspect of your digital life. Today, you can be woken up by the alarm on your Google Nexus phone, running Google’s version of Android. You’ll check your email on Gmail and plan your day using Google Calendar on your Google Chromebook running Chrome OS, through your Google Fiber internet connection. They may even be your domain registrar. Watch your Google TV while you eat breakfast. You can put on Google Glass and get a quick bike route to work on Google Maps. Listen to Google Music while you drive. Go over your presentation and spreadsheets on Google Docs and save them on Google Drive. What if Google disappeared tomorrow? The infrastructure of the internet is just as fragile and people want to keep control of their data.
We also have hackers breaking into crypto currency exchanges and vendors bundling spyware with their PCs. Single points of failure are common, with the organizations in charge not even being able to trust each other:
Both the US commerce department and the Department of Homeland Security take a close interest, to differing degrees, in ICANN’s operations. In the wake of the ongoing revelations of NSA spying, and of undermined internet security, this does not sit well with many of ICANN’s overseas partners. Some, including Russia and Brazil – whose president has made such demands very public – are calling for a complete overhaul of how the internet is run, suggesting it should be put under UN auspices.
A note about hosting providers
There are a number of hosting providers that offer Slackware images, mostly based in the U.K. Linode offers some cheap VPS plans and is based in the US. I got the folks at CloudSigma to build a Slackware image which I’m sure they’ll happily provide if you ask. The guys at LQ also offer some suggestions. In general, you want to keep these things in mind:
- Where is the company based? If it’s a publicly traded company, who is involved?
- Does the company own their data centers or are they colocated?
- Where are the data centers located? Does the country have strong privacy laws?
You’ll also want to pay attention to any modifications they may make to the images they provide. Linode, for example, provide their own custom kernel and have the
-current branch of Slackware selected in
/etc/slackpkg/mirrors. They also have a very minimal system with only the absolute necessary packages necessary to run the OS installed. You’ll want to skip installing
glibc-zoneinfo. It turns out if you set the date on the server and then proceed to install that package, your
/etc/localtime file will become corrupted. I notified Linode about this issue but they didn’t seem to care too much. On the CloudSigma platform watch out for a script they add to
/etc/rc.d/rc.local that creates a shell user for them and checks your host keys. There may be other caveats on other providers. Make sure you check the OS thoroughly. You’ll also have to make some changes if you roll your own image. Most of the time, you will have to
chroot and create an
initrd right after installation, before rebooting:
You’ll need to edit
/etc/lilo.conf and add some parameters to your
partition sections. These were taken from a CloudSigma image. They should work on other KVM based cloud platforms that allow you to upload your own ISO, such as Vultr:
root device accordingly or contact your provider for assistance. Don’t forget to run
lilo -C /mnt/etc/lilo.conf before rebooting.
Another option you have is setting this up in a physical server in your home. Former secretary of state Hillary Clinton certainly thought it was a good idea:
[She] used a private email account rather than her official State.gov email address while serving in the State Department. And this was no Gmail or Yahoo! Mail account: On Wednesday the AP reported that Clinton actually ran a private mail server in her home during her entire tenure leading the State Department, hosting her email at the domain Clintonemail.com.
The article questions her use of a private domain registrar and a self-signed certificate. These are real concerns and unfortunate tradeoffs that have to be made for those of us who are unable to register a .gov domain or purchase a certificate from a “trusted” authority. Some argue a self-signed certificate is more secure than one purchased from a certificate authority (only trust yourself), but if you want to get rid of those pesky browser warnings you’ll need to had over some money to a certificate authority.
This setup will most likely involve some port forwarding being done on your modem or router. Preferably, you should also have a static IP. Most ISPs don’t allow residential customers to host mail servers using their service. Contact them if you have any doubts.
Now we’re ready to get started.
Set up an FQDN as your hostname. We’ll use mail.example.org:
PHP + nginx
I recently switched my site to nginx so I’ll be sticking with that for Postfix Admin and Roundcube. You’ll need to compile nginx with support for FastCGI and memcached to better support Roundcube so you’re probably better off using the build from SlackBuilds than the configure options I gave in the linked post. Create your webserver user:
If you choose to install from source, there is a handy modification you can make to the code before compiling. As of this writing, the most recent stable release of nginx is 1.8.0. Extract the source archive and change into the new directory:
Next, we’ll edit two files to remove some identifying information. The first of these is the
src/http/ngx_http_header_filter_module.c file in the extracted source. We are going to remove the
Server: string of the host. You don’t really need to advertise this especially if you’ll be the only user on the server (or just a few friends). The
Server: string is found in lines 49-50. You will also need to change lines 281-282:
The next edit will remove it from the auto generated error pages as well. This is done in the
src/http/ngx_http_special_response.c file in lines 21 and 28. In this same file you can also change the HTML for each of the server error pages such as 301, 404, etc:
Once you’ve made these changes, go ahead and compile. You can still use the SlackBuild if you
tar up the sources, otherwise, just
./configure && make && make install. You’ll want to add the
--with-http_spdy_module to add support for SPDY, the starting point for HTTP 2.0. If you use the SlackBuild don’t forget to change the
GROUP variables in the script.
Unfortunately there is no
init script included with the source, but you can use rc.nginx from the SlackBuild. If you want to enable syntax highlighlting for the
nginx.conf file in
vim, copy the
contrib/vim directory from the extracted source to
This is a tough one. The SHA-1 hash algorithm has been “sunsetting” since back in 2014 thanks to Google so stay away from that, not just because Google says so but because they have good reason to. You’ll hear everyone urging to move from RSA to ECDSA but then it turns out NIST curves are suspicious.. You can feel free to browse a list of Safe Curves but you’ll be hard pressed to find any Certificate Authority that offers any certificate using non-NIST curves. Browser vendors also tend to only support these as well. To that end, you can then refer to things like Mozilla’s Modern Compatibility ciphersuite selection for your nginx SSL configuration. The linked example will require modern browsers and mobile devices like Android 4.4+ in order to work properly. Let’s say you go with a relatively strong NIST curve like
secp384r1 for compatibility (or the stronger
secp521r1 if not). You’ll need to find a Certificate Authority that provides ECC SSL certificates such as Comodo or DigiCert. The suggested configuration below will include support for HSTS and PFS to completely get rid of plain HTTP access to the server. It will also provide support for SPDY.
Let’s set up some Server Blocks (VirtualHosts if you’re coming from Apache) to serve content. Your
nginx.conf file will need an
events section which can be left blank to activate the defaults or modified depending on the load you’re expecting on the server.
You will notice I am only allowing TLS and disabling SSL. I used
/var/www/html/mail.example.org as the site’s
root for easier management, but you can use whatever you feel comfortable with. Make sure that whatever directory structure you choose allows the
nginx user and group to write to it.
Slackware’s default PHP installation is already compiled with support for
mcrypt, and XML parsing. As mentioned before, you’ll probably want to install some extensions to increase performance. I’m going with
memcached, which you can also obtain from SlackBuilds.
If you choose to install
memcached, don’t forget to install the PHP extension as well. You can grab the older
memcache extension from SlackBuilds, but it’s probably easier to install the newer (confusingly named)
memcached extension through
This will require that you have
libmemcached (SlackBuild) installed. Remember to add
extension=memcached.so to your
php.ini file or simply create a new
/etc/php/memcached.ini file with that content. You’ll also want to change the user
memcached runs as in the
/etc/rc.d/rc.memcached init script to
nginx if you went the SlackBuilds route. I also recommend giving it its own run directory, assigning it to the
nginx user and group, and modifying the value of
/etc/rc.d/rc.memcached. In addition, add
-s /var/run/memcached/memcached.sock to the
memcached_start() function in the same file to use a socket instead of TCP:
While we’re changing permissions, you’ll also need to change the permissions of
/var/lib/php since we’re using
nginx instead of Apache to run PHP:
Note that in order to make proper use of
GD, you’ll need some
X11 libraries. These are most likely not installed if you’re working on a headless server. Get the needed dependencies from a Slackware mirror:
PHP-FPM with FastCGI in nginx
The default Slackware install includes PHP-FPM so you’ll need to make sure the startup script is executable. Start PHP-FPM at least once to let it create its default configuration files:
We’ll be making some changes to the
www pool in
/etc/php-fpm/php-fpm.conf. First, change the
group lines to
listen mode set to
0666. We’re going to be using Unix sockets throughout this guide so change
/var/run/php-fpm.sock . We also need to add
.html files to the scripts FPM will allow to pass. The relevant lines should look like this:
We’ll need to add a new
location block inside the HTTPS
server block in
/etc/nginx/nginx.conf telling it to use the FastCGI server we set up previously for PHP files:
Feel free to adjust those values to your needs. Pay attention to
fastcgi_pass, which connects to the Unix socket.
We are going to be using Dovecot to handle secure IMAP and POP3 connections and for SMTP authentication. Postfix Admin will store the user information in this setup instead of creating a Unix account for each one. The email will be stored in
/var/vmail organized by domain and user, so the email for firstname.lastname@example.org would be stored in
/var/vmail/example.org/admin. We’ll create a single user to own the mailboxes on the system and let Dovecot manage them. Dovecot will also need its own user and group:
Make sure the
UIDs used above do not interfere with any of your current users and groups. You can compile Dovecot from source with a simple
./configure && make && make install or grab the SlackBuild. Edit the
VERSION variable in the SlackBuild to build the latest version, which is 2.2.16 as of this writing. If you build from source on your own, make sure you compile with the
--with-mysql flag to enable MariaDB support. You are also responsible for creating an
init script to manage the service. There is one provided in the source in
doc/dovecot-initd.sh which should work with Slackware after some minor adjustments. You can also use Alan Hick’s simplied version from the SlackBuild if you like. Make sure it’s executable as well.
Once you have Dovecot installed, copy over the example configuration files from
/etc/dovecot and change its permissions while you’re there:
We are going to set up the database connection between Dovecot and MariaDB in the
/etc/dovecot/dovecot-sql.conf.ext file. Edit that file and make sure you set the following options:
You will also need to add two queries,
password_query to retrieve passwords and
user_query to get user information. This information will be obtained from the schema Postfix Admin will create. If you didn’t want to install the Postfix Admin web interface, you can still use it to generate schema for you so you can add users manually and still have Dovecot find them. Of course if you’re good with databases you can make up your own and tell Dovecot here how to find your users. See Dovecot’s SQL documentation for more. Either way, here’s what you need to add for Postfix Admin:
The next file to edit is
/etc/dovecot/conf.d/10-auth.conf. We will enable the SQL configuration file we just modified and disable plaintext authentication unless it’s already encrypted through TLS. We’ll also disable the
auth-system.conf.ext file that’s loaded by default. Don’t worry about authenticating with plain text; your connection will be secured with TLS so this is safe:
Now we’re going to tell Dovecot where the email is stored in the filesystem. Change the
UID in the following lines in
/etc/dovecot/conf.d/10-mail.conf to whatever you set it to when you created the
You need to edit
/etc/dovecot/conf.d/10-ssl.conf and set the path to the SSL certificate you obtained earlier for nginx. We are going to disable SSLv3 as we did with the web server. We can use the same SSL ciphers here
Dovecot needs to know how to authenticate to the userdb so uncomment the
mode lines in the
unix_listener auth-userdb section of the
service auth block in
/etc/dovecot/conf.d/10-master.conf. You also need to set up a
unix listener for Postfix. Uncomment that section as well and add
postfix as the user and group. We’ll create those later when we’re setting up Postfix.
Installing Postfix is simple if you use Alan Hick’s excellent SlackBuild script. Set the
DATABASE variable to
mysql before running the script to enable MariaDB support. You have the option, of course, to compile from source yourself. In that case you will need to pay attention to the Postfix configuration parameters outlined in section 4.6.2 of the
INSTALL file in Postfix’s official documentation . Whichever you choose, you will need to create a user and group for Postfix. Wietse suggests in the
INSTALL file to create a
postfix user with no login shell or home directory and a
postdrop group with a group ID that is not used by any other account, even the
postfix user. The SlackBuild script has the following, which is what I went with:
You’re also going to need a startup script. Alan’s rc.postfix script is good enough. We’re going to need the following configuration files to tell Postfix how to find your users in the database. These are lifted straight from Reason’s guide. Note in our setup, we’re using Unix sockets so that has been changed to
localhost. This will cause Postfix to connect to the default domain socket. The username and password used here are the same we’ll use when we set up Postfix Admin.
We’re going to strip the email client and IP address of each mail you send. Remember this is just security through obscurity and you’ll be violating RFC 2045 if you remove the
MIME-Version string. It’s still useful to prevent uninitiated recipients from figuring out where you are sending your mail from. Add these to the file
/etc/postfix/header_checks for now. We’ll enable it in the Postfix configuration later.
Postfix Main Configuration
There are way too many Postfix configuration options to be able to go through them all here. The default configuration file at
/etc/postfix/main.cf should have some good defaults which you can make minor adjustments to. We are specifically adding
mime_header_checks to enable the
/etc/postfix/header_checks file we created earlier.
The next section is to use Dovecot for authentication. You’ll need to add these
We’ll set up TLS next. We’re disabling the use of any SSL versions. The last two options are to force incoming and outgoing SMTP connections to use TLS. This may have some unwanted consquences. If a mail server you are trying to reach does not support this, you will not be able to communicate with it. You can change these options to
may instead of
encrypt to enable TLS but not enforce it. Check your logs frequently and if you see any incoming connections without TLS, you can suggest that server’s admin to enable this feature.
The SMTP parameters are below. You can tweak these to your tastes. These have to do with the amount of times server connections are retried if failed, how long you want to keep mail in your queue (in case the remote server is not reachable for some time), recipient limits, and so on.
We need to add some restrictions regarding who can send and receive mail on this server. This also allows for checks against various DNSBLs to block spam. We’ll also need
check_policy_service for Postgrey later on and we’ll set up the milters to use OpenDKIM. Use Unix sockets here.
The next section will use the MySQL configuration files we set up earlier and tell Postfix were the mail folders are located. Pay attention to the
Finally, we’re going to integrate Postfix with Amavis and Dovecot.
Postfix Master Configuration
That should take care of the
/etc/postfix/main.cf file. Now let’s edit
/etc/postfix/master.cf. Check the file out before editing to get a feel for the format and read the comments describing what the options do. Some of them you can edit and others you’ll have to add. First we’ll set up SMTP with TLS on port 587 and SMTPS on port 465
We’ll set up Amavis integration. Note the number 4 in the first line. This is the number of processes Amavis is allowed to run. Incrase this if you need more.
Uncomment the other external delivery methods if you need them. Let’s not forget to set up the Dovecot for local delivery
MariaDB and Postfix Admin
A note about web based interfaces
Installing a web based user interface for any of these services is entirely optional. This makes some tasks easier, such as adding a new domain and mailbox to your Postfix database. A web based email client can be beneficial if you are in an unfamiliar environment and only have access to a browser. However, you are increasing the attack vectors to your server. Web based control panels have long been a favorite gateway for script kiddies to gain unauthorized access to servers due to their popularity. You can protect yourself against common attacks (bots looking for
install.php, etc) by renaming the directory where the website files reside so they’re no longer accessible or changing the permissions. You can restrict access only to your home IP using your server’s firewall or through some file access rules in
nginx.conf. You can also simply not install them at all and work through the command line. For the sake of completeness, this guide will assume you want them.
MariaDB Initial Setup
Slackware officially switched to MariaDB starting with 14.1 but the
init scripts are still named
rc.mysqld. It should be included in a default Slackware install as part of the
AP/ series, but if you don’t have it just type
slackpkg install mysql as
root. Make sure the program starts at boot:
Now we need to perform the first time setup:
Start MariaDB then perform the secure installation. Make sure to set up a secure password for MariaDB’s root user.
Once that’s set up, log in as
mysql -u root -p and create the user and database that we’ll use for Postfix Admin. Choose a secure password here.
This one is a breeze to set up. You can create a new
server block in
nginx.conf to set it up as a subdomain, but I chose to install it as a subdirectory. Change into your main site’s
root and download the latest Postfix Admin tarball. As of this writing, that’s 2.92:
You can modify
config.inc.php, but I recommend you create a new
config.local.php and place your settings there. This has the advantage that whatever you don’t explicitly set is left at the default value in
config.inc.php and whatever you change takes precedence. This way your changes won’t be overwritten if you decide to upgrade Postfix Admin. Now we’re going to add some lines to tell Postfix Admin how to connect to MariaDB. We are also going to set
true and tell it how to store its data. The passwords will be stored using Dovecot’s crypt scheme:
Again, note that we are connecting using the MariaDB Unix socket. Next, visit https://mail.example.org/postfixadmin/setup.php to generate a setup password to use in
config.local.php. If you have been following this guide carefully, you should see everything OK. If you don’t see the setup page, check your nginx log files for any PHP errors or permission errors. I’ve found from experience that these PHP applications sometimes have difficulty parsing complex passwords in configuration files so if your database connection is failing, try removing some special characters from your password. Take it up with the developers, not me.
Before you continue, we’ll need to make a few changes to the Dovecot configuration files. We’ve made all the configuration changes in the
/etc/dovecot/conf.d directory so far. It turns out Postfix Admin has some difficulty parsing the
!include conf.d/*.conf line in
/etc/dovecot/dovecot.conf, so we’ll need to move all our configuration to that file. This is simple enough with the
doveconf utility. We’ll need to change the permissions of that file and add
nginx to the
dovecot group to give Postfix Admin access.
Once you’ve got that sorted out and placed your setup password in
config.local.php, the setup will ask you to create an admin user for Postfix Admin. You will need to provide the setup password you selected earlier. Use an email address for the admin user such as email@example.com and choose a password for it. Please make sure it’s secure.
The installer will claim you don’t need to remove
setup.php and it will recommend you block off access to it. You can do that or just delete the file. You can always get it back by downloading the source tarball again. Once you’re done, you can log in to Postfix Admin at https://mail.example.org/postfixadmin using the admin user you just created.
You should take this time to go back and read through
config.inc.php. It is very well commented. There are some options you may want to set such as your default admin email and footer links. Remember to add your changes to
Add Email Domains and Mailboxes
Log in to https://mail.example.org/postfixadmin and head over to Domain List > New Domain. Fill in whatever works for you here to add a new domain, then head to Virtual List > Add Mailbox and create your first user. I set up example.org as an email domain and firstname.lastname@example.org as my first user. Doing this will generate the needed database schema that Postfix will use. Go ahead and play around with this and make sure your aliases are set up
Amavis with ClamAV and SpamAssassin
Now that we’ve installed the major components, it’s time to add some virus and spam checking. We’ll be using Amavis for this. As is the case with several of the older open source projects, Amavis has gone through a few name and code base changes. The most recent, still maintained version is
amavisd-new, with the name of the program being
amavisd and the name of the project being Amavis. Most people use these interchangeably. Amavis will be the interface bewtween Postfix, ClamAV and SpamAssassin.
The Amavis and SpamAssassin packages are a pain to install manually mostly due to their long list of dependencies. They’re both written in Perl and need quite a few modules. These can be installed using CPAN but I would recommend you stick to the scripts provided by Nishant Limbachia at SlackBuilds.org. This makes it much easier to keep track of what you have installed with
slackpkg or whatever Slackware “package manager” you use. Before getting started you may want to install the
p7zip packages to allow SpamAssassin and ClamAV to handle different compressed files. These are all available on SlackBuilds.
Uncomment the lines
@bypass_spam_checks_maps at the top of
/etc/amavisd.conf and add the following
Go down a bit further and uncomment
@lookup_sql_dsn, then modify it to connect to your database using the Unix socket and the proper credentials. Amavis uses the
DBD::mysql Perl module. The documentation states setting the
host value to
localhost will use the socket. This configuration will enable spam checking for the domains you’ve added to your database either manually or through Postfix Admin
There are a couple of other settings we can change. For instance, make sure you also set
$max_servers to the same number of processes you allowed Amavis to use in
/etc/postfix/master.cf. Setting the
$sa_tag_level_deflt opton to a large negative number will ensure that spam headers are added to every single email. Change the user and group to the ones you created earlier, set up a home directory for configuraiton files and quarantine emails, and set your domain name (not the same as your hostname). Make sure you also uncomment the
amavis section in
@av_scanners. We are also setting the Unix socket for Amavis here too
$interface_policy('10026'). There may already be an
$interface_policy set up for
AM.PDP-SOCK. Comment it out or modify it to what I have above. Notice we’re placing the socket in the Postfix queue directory,
/var/spool/postfix. We’ll need to create the directory to hold the socket and assign some permissions as well.
Use the following commands to let Postfix create the
In order for the above to work, we need to set a
/etc/amavisd.conf. In my setup,
amavisd-new would ignore that configuration option and insist on using TCP port 10025. I could not for the life of me figure out how to get it to use a socket no matter what value I tried. I ended up having to modify the
/usr/sbin/amavisd Perl script directly. Look around line 926 or search for 10025. Comment out the existing
$forward_method and replace it with this:
Go through the rest of
/etc/amavisd.conf file and modify any settings you might want changed.
Get the SpamAssassin SlackBuild from here, or get the source files. You’ll notice one of the optional dependencies of SpamAssassin is
perl-Geo-IP, which requires
GeoIP (SlackBuild). If you decide to install that, I found that SpamAssassin’s
sa-update script expects the IPv6 database to be in
/usr/share/GeoIP/. You can get that file from MaxMind’s servers and place it where needed (as
If you chose to install from source, you can grab a startup script from the extracted tarball. The guys at Apache were nice enough to include a Slackware-ready script in the
spamd directory of the extracted source, named
slackware-rc-script.sh. Once you have SpamAssassin installed, edit the
/etc/spamassassin and set the following options. You only really need
ENABLED but the rest are a good idea.
The SpamAssassin source no longer includes rules, so you’ll have to download them. Run
sa-update to do this.
This one is pretty straightforward as well. Download the SlackBuild and set the
COUNTRY variable to your country’s two letter ISO code. Run the script to build automatically. You can also get the source directly and
./configure && make && make install. It doesn’t need anything outside a base Slackware installation. Grab the rc.clamav
init script from the SlackBuild for easier management. Wether you’re using the SlackBuild or installing manually from source, you’ll need a user and group created first.
While we’re at it, go ahead and add the
amavis user to the
clamav group and vice versa
/etc/clamd.conf file and change the
Now go ahead and update your virus database by running
root. Don’t worry if you get a message from
clamd was not updated. This is because we have not started
clamd yet. We also need to fix some permissions to get all three to play nicely.
This one is simple so we might as well get it out of the way. As usual, create your user and group first
Since Postgrey is just a Perl script, feel free to copy over the needed files from the source tarball to
contrib/postgrereport. Check the requirements to make sure you have the needed Perl modules. You can of course use the SlackBuild, too. If you install from source, grab the
init script from
contrib/postgrey.init and place it in
/etc/rc.d/rc.postgrey. Make sure you also get a copy of
postgrey_whitelist_clients and place them in
/etc/postfix. The SlackBuild already does this for you. If you do choose the SlackBuild, you’ll need to set
POSTGREYGID in the script to the values you set earlier when you created them.
Whichever you choose, you’ll need to edit the
init script and set
HOST to their proper values. Feel free to get rid of
PORT. Find the
postgrey_start() function and edit the
postgrey flags to make sure it uses a socket instead of TCP.
Setting up Roundcube is just like setting up any other PHP site. We’ve already configured nginx to use FastCGI so it’s a matter of downloading the files and placing them in a directory. As with Postfix Admin, feel free to create a new
server block for this or just stick with using a subdirectory of your existing site. Since I placed Postfix Admin in
/var/www/html/mail.example.org/postfixadmin I’ll place my Roundcube installation at the root, in
/var/www/html/mail.example.org/. Get the sources (I recommend the “complete” version) and extract. As of this writing, that’s 1.1.1
We’ll need to create a database for Roundcube to use. Log in to MariaDB with
mysql -u root -p and create it. Make sure you use a strong password.
Roundcube includes an SQL file that can create the necessary database structure for you
I recommend you check out the
INSTALL file included in the source for a more complete guide on the installation. Now head over to https://mail.example.org/installer and make sure everything is OK in the Check environment section. My installation complained about the
date.timezone setting in
php.ini so I had to set that. Get a list of supported time zones from here. You may need to restart
php-fpm for the changes to take effect.
Click Next when you’re done to move on to the Create config section. You can leave most of these settings alone. If you want to know what a specific setting does, check out Roundcube’s wiki. Fill in the Database setup section with the user and database you created earlier.
Make sure you do not enable spellchecking support. If you do, Roundcube will connect to external services to check your spelling. Why would we go through all this trouble to have a third party see every word we type?
IMAP and SMTP Settings
We’re going to set
tls://localhost and the
993 in the IMAP Settings section. In the SMTP Settings section, set
587 and check the Use the current IMAP username and password for SMTP authentication option. Click on Create config.
After it’s done writing your configuraiton file, we’ll add support for
memcached and make sure we only use HTTPS in
Click on Continue in the browser to go to Step 3
OpenDKIM, DNS and Building Trust
The setup up to this point should be pretty much complete and meet most people’s needs. Some mail servers are quite picky when it comes to receiving email. Gmail particularly doesn’t like when an email is not signed. The next section will walk you through signing your email with DomainKeys Identified Mail and setting up Sender Policy Framework. If you are using a hosting provider for your server, you will need to contact them and have them set up a PTR record for your IP address. This is also known as rDNS. Some mail servers will reject your email if the IP you are sending from does not point back to your domain name. In general, it should look something like this:
18.104.22.168.in-addr.arpa PTR 600 example.org
If you’re hosting at home, you can try asking your ISP to set this up for you but it is unlikely they’ll want to. They may be willing if you purchase a static IP. You’ll also need to add
MX records to your domain’s DNS records. You can add something like this
example.org MX 600 10 mail.example.org
That’s assuming mail.example.org points to your mail sever’s IP and you want a priority of 10. You can ask your DNS provider to add these for you. Check that the record has propagated with
You’ll want to grab the latest sources, which correspond to version 2.10.1 as of this writing. I also wrote a handy SlackBuild which you can use. Note that you will need
libbsd(SlackBuild) installed in order to be able to compile. Let’s make the user and group first:
We’ll need to create the run directory as well:
If you’re building manually, you may want to add
--prefix=/usr to the
configure script or else it’ll place everything in
/usr/local. We’ll need support for MariaDB, so pass
--with-sql-backend to the
configure script as well. If you’re using the SlackBuild set the
USE_MYSQL variable to
yes and run the script. I used a modified version of CentOS’s
init script for mine, but feel free to grab the one included in the source in the
Once it’s installed, we’ll need to set up a basic configuration file. You can copy the sample one from
/etc/opendkim and add the user and group we created earlier. Note that the SlackBuild already does this for you:
You’ll notice my
init script will automatically create some default keys for you in
/etc/opendkim/keys and create the directory if it doesn’t exist. We’re using Unix sockets in this guide, so let’s change a line in
We’ll generate a 2048 bit key with the
opendkim-genkey command. You can try something stronger like 4096 bits, but RFC 6376 suggests it might not fit in a 512 byte DNS UDP response. See section 3.3.3 Key Sizes for more information.
The selector is simply something to tell your key apart once you add it to your DNS records. You’ll end up with two files,
mailsvr.private, which is your key, and
mailsvr.txt which has a nicely formatted record you’ll need to add to your DNS zone. If you don’t manage your own DNS or have access to your zone file, simply copy the text starting with
v=DKIM1 as a
TXT record in whatever control panel your DNS provider uses. For the example above, this is what I got (truncated for demonstration):
You’ll need to wait a while before the DNS record propagates but once it does you can check it with
Sender Policy Framework
This basically consists of adding another
TXT record to your DNS zone. There used to be an
SPF type record but this was removed in RFC 7208. You’ll want to add something like this:
We’ll need to start all the components we’ve installed and check their logs to make sure everything is running smoothly. You can place your startup commands in
/etc/rc.d/rc.local and the stop commands in
/etc/rc.d/rc.local_shutdown. Make sure both are executable and add this content
Log in to your Roundcube webmail at https://mail.example.org and start sending email. Try sending to big providers like Gmail and Yahoo. You’ll note the first time you receive an email, it’ll be greylisted thanks to Postgrey. Check
Most mail servers will try once more after some time and will be allowed the second time they send. Spammers generally only try once so this should stop some most of the common spam you could receive. Once the mail passes through, Amavis will check for viruses and other malware.
You can also test your anti-virus using the EICAR test file. Send yourself an email from another mail server with only the following string in the body:
It will be detected as a virus and you’ll see this in the log as well:
In a similar fashion, you can test your spam filter using the GTUBE. Send a message from another mail server to yourself with only the following string in the body:
It will be detected as spam and you’ll see this in the log as well:
You’ll probably want to set up an email client such as Thunderbird or Claws Mail. They should automatically detect your sever’s open ports but you can use the following settings to set it up manually. You can substitute the hostname for example.org if that points to your server’s IP as well.
You’ll notice in your
/var/log/maillog file that there will be a ton of bots and compromised third party servers trying to relay using your server, trying to log in using common usernames (admin, support, test, etc) and generally just trying to wreak havoc on your mail server. The setup suggestions I described in this article should prevent most of those attacks. You may consider trying something like fail2ban to automatically ban these IPs. Get yourself a nice firewall using AlienBob’s Easy Firewall Generator and block anything you don’t need.
I hope you found this guide useful. I tested this setup to the best of my ability but you may find certain things didn’t work for you. If that’s the case or you have any suggestions, comments, or just want to say hi, feel free to contact me. Encrypted email is strongly encouraged and preferred :)