Slackware Mail Server with MySQL, Postfix, and Dovecot
25 Apr 2015Introduction
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 A/
, AP/
, D/
, L/
, and 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)
I based some of the Postfix and Dovecot configuration options on an existing mailserver guide by Reason.
Why?
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.
Read Ken Thompson’s Reflections on Trusting Trust and see why you can’t even trust your compiler. Trust is difficult. Email is horribly insecure.
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 global
and 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:
Adjust your root
device accordingly or contact your provider for assistance. Don’t forget to run lilo -C /mnt/etc/lilo.conf
before rebooting.
Self host
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.
Preparation
Hostname
Set up an FQDN as your hostname. We’ll use mail.example.org:
PHP + nginx
Install 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 VERSION
, USER
and 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 ~/.vim
.
SSL Certificate
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.
Configure nginx
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.
Configure PHP
Slackware’s default PHP installation is already compiled with support for GD
, curl
, 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 PECL
:
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 PID
to /var/run/memcached/memcached.pid
in /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 user
and group
lines to nginx
, with listen mode
set to 0666
. We’re going to be using Unix sockets throughout this guide so change listen
to /var/run/php-fpm.sock
. We also need to add .htm
and .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.
Dovecot
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 admin@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 GIDs
and 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 /usr/doc/dovecot-2.2.16/example-config
into /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 vmail
user:
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 user
, group
, and 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.
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.
/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf
/etc/postfix/mysql_virtual_alias_maps.cf
/etc/postfix/mysql_virtual_domains_maps.cf
/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf
/etc/postfix/mysql_virtual_mailbox_maps.cf
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 header_checks
and 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 UID
and GID
used.
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 /roundcube
, 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 root
using mysql -u root -p
and create the user and database that we’ll use for Postfix Admin. Choose a secure password here.
Postfix Admin
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 configured
to 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 admin@example.org 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 config.local.php
.
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 admin@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 sbopkg
, slackpkg
or whatever Slackware “package manager” you use. Before getting started you may want to install the arj
, unrar
, cabextract
, lzop
, nomarch
, and p7zip
packages to allow SpamAssassin and ClamAV to handle different compressed files. These are all available on SlackBuilds.
amavisd-new
Stick with the SlackBuild for this one. The dependencies are listed thoroughly in Nishant’s README.SBo file, including the ones for SpamAssassin. Create a user and group before you run the script.
Uncomment the lines @bypass_virus_checks_maps
and @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
Comment out $inet_socket_port
and $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 amavis-accept
PID:
In order for the above to work, we need to set a $forward_method
in /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.
SpamAssassin
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 root
):
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.
ClamAV
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
Edit the /etc/clamd.conf
file and change the LocalSocket
and LocalSocketGroup
options
Now go ahead and update your virus database by running freshclam
as root
. Don’t worry if you get a message from freshclam
saying 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.
Postgrey
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 /usr/bin
, notably postgrey
, policy-test
, and 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_recipients
and 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 POSTGREYUSR
, POSTGREYGRP
, POSTGREYUID
and 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 USER
, GROUP
, and 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.
Roundcube
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 nginx
and 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 default_host
to tls://localhost
and the default_port
to 993
in the IMAP Settings section. In the SMTP Settings section, set smtp_server
to tls://localhost
, smtp_port
to 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 config/config.inc.php
:
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:
34.216.184.93.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 host
:
OpenDKIM
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 contrib/init/generic/
directory.
Once it’s installed, we’ll need to set up a basic configuration file. You can copy the sample one from opendkim/opendkim.conf.simple
to /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 /etc/opendkim.conf
:
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 dig
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:
Testing
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
/etc/rc.d/rc.local
/etc/rc.d/rc.local_shutdown
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 /var/log/maillog
:
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.
Other Considerations
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 :)