Installing iRedMail on Debian (Jessie) 8
I've run my own mail server for quite some time, but it's started to reach the point where a refresh is probably in order.
Normally, I'd prefer to build from scratch, but I thought, this time, I'd have a look at some of the "off-the-shelf" solutions that now exist. Mailinabox was quickly discounted because there's no real configurability, which doesn't sit well with me (it does simplify installation, but makes long-term management that much harder).
iRedMail seems to have a reasonable following, and a scan of it's website and documentation suggested that it is, at least, reasonably sane.
This documentation details the process I followed to install iRedMail on Debian 8 (Jessie). I used Jessie rather than Stretch (9) because that's what the VM I was repurposing was imaged with.
Introduction
Once this process is complete, we'll have a server set up and running iRedMail, using the following underlying components
- Postfix
- Dovecot
- MariaDB (or Postgres if you prefer - the installer will ask)
- Nginx
- Roundcube Webmail
- Amavis
- ClamAV
- SpamAssasin
- Fail2ban
- mlmmj (Mailing list manager)
We'll also make sure the system presents a valid SSL certificate obtained from Let's Encrypt.
Pre-Setup
There are a few small bits which need doing before fetching and triggering the installer.
You should install on a freshly installed OS to reduce the likelihood of conflicts during the install process.
Firstly, we need to make sure the server has (and knows) it's Fully Qualified Domain Name (FQDN) so that it identifies itself correctly when it connects out to other mailservers.
hostname -f
sohara.sys.bentasker.co.uk
We also need to ensure that we've got BZip install so that we can expand the installer
apt-get install bzip2
Make sure the OS install didn't dump exim onto the system
apt-get remove exim4
Install
The next thing to do is to fetch the installer.
There's a slight caveat here on Jessie. IRedMail seems to have dropped support for Jessie, so a slightly older release (0.9.7) needs to be installed rather than the latest (0.9.9). This isn't ideal, but the installer appears to use apt for major components, so we shouldn't be exposed to too much risk (as we'll still be getting the latest version the repositories have).
wget https://bitbucket.org/zhb/iredmail/downloads/iRedMail-0.9.7.tar.bz2
tar xjf iRedMail-0.9.7.tar.bz2
cd iRedMail-0.9.7
bash iRedMail.sh
The installer will now run, it's safe enough to accept the defaults and the options it asks for are fairly self explanatory
The only default I didn't accept is the firewall rules, I'll create those later
Once the installer completes, your system is nominally configured as a mail server (albeit using self-signed certificates for everything)
The management interfaces are available at:
- iRedAmin: https://[your domain]/iredadmin/
- Roundcube webmail: https://[your domain]/mail/
- Awstats: https://[your domain]/awstats/awstats.pl?config=web / https://[your domain]/awstats/awstats.pl?config=smtp
The admin account to use with iRedAdmin is the one you configured in the installer.
Use this to add a domain and the necessary user accounts
- "Domains and Accounts" -> Add Domain
- "Add" -> "User"

Firewall Rules
Next, we're going to create the basic firewall set. Part of the reason I've done this separately is because I have a separate admin network, so will restrict HTTPS access from the wider web (if you intend to do this, bear in mind this will also mean no web mail).
The installer has already set up fail2ban, so there will be some rules for those. What we need to add is
- Allow established connections
- Allow loopback connections
- Allow SSH
- Allow Mailserver essential connections (SMTP, IMAPS etc)
- Reject everything else
So,
iptables -I INPUT -i lo -d 127.0.0.0/8 -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 25 -j ACCEPT -m comment --comment "SMTP in"
iptables -A INPUT -p tcp --dport 443 -j ACCEPT -m comment --comment "HTTPS" # I did this one differently
iptables -A INPUT -p tcp --dport 993 -j ACCEPT -m comment --comment "IMAPS"
iptables -A INPUT -p tcp --dport 995 -j ACCEPT -m comment --comment "POP3S"
iptables -A INPUT -p tcp --dport 587 -j ACCEPT -m comment --comment "SMTPS"
iptables -A INPUT -j REJECT
We then want to make sure that rules will persist following a reboot, so install the iptables-persistent package
apt-get install iptables-persistent
SSL Improvements
The server currently uses a self-signed certificate on all interfaces. Traditionally it wasn't unusual for mailservers to do this, but lets use LetsEncrypt so that we can present a valid certificate.
You will need to have updated DNS so that whatever name you're using for your mailserver resolves to it (I'm using mail2 below as I wasn't ready to update the MX record from pointing at mail just yet)
The first thing to do is to install certbot. To get the latest version we need to ensure the outdated Debian package isn't installed
apt-get remove certbot
Then we fetch and install certbot
wget https://dl.eff.org/certbot-auto
mv certbot-auto /usr/local/bin/certbot-auto
chown root /usr/local/bin/certbot-auto
chmod 0755 /usr/local/bin/certbot-auto
ln -s /usr/local/bin/certbot-auto /usr/local/bin/certbot
Next, we need to allow port 80 through the firewall
iptables -I INPUT 9 -p tcp --dport 80 -j ACCEPT
iptables-save > /etc/iptables/rules.v4
Now, lets give certbot a run. Remember to switch the domain for your mail domain
certbot certonly --webroot -w /var/www/html -d mail2.example.com
As it's the first run, certbot will install its dependencies, and then ask you a bunch of questions
Once it's complete, the cert and key will have been saved to
- /etc/letsencrypt/live/[your domain]/fullchain.pem
- /etc/letsencrypt/live/[your domain]/privkey.pem
Set up a cron to trigger the renewal check daily
echo "1 3 * * * root certbot renew --post-hook 'service postfix restart; service nginx restart; service dovecot restart'" > /etc/cron.d/certbot-renew
Now, we want to make the various services use the new certificate, so we'll move the snake-oil one out of the way and create a symlink
cd /etc/ssl/
mv certs/iRedMail.crt certs/iRedMail.crt.bkup
mv private/iRedMail.key private/iRedMail.key.bkup
ln -s /etc/letsencrypt/live/mail2.example.com/fullchain.pem certs/iRedMail.crt
ln -s /etc/letsencrypt/live/mail2.example.com/privkey.pem private/iRedMail.key
Now, if you're comparing this to the iRedMail documentation, you may think the next step is to chmod the LetsEncrypt directory to make it world readable. Do not do that, it's completely unnecessary (the daemons read the cert before they drop privileges) and means any user on the box could compromise your private key
If we restart the services they should now use the new cert
service postfix restart
service dovecot restart
service nginx restart
We can verify this from our desktop using OpenSSL's s_client module
echo | openssl s_client -connect mail2.example.com:587 -starttls smtp
echo | openssl s_client -connect mail2.example.com:995
echo | openssl s_client -connect mail2.example.com:443

If you look at the output, you'll see some information on the certificate
subject=/CN=mail2.example.com issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
What you want to check is that the Issuer is Let's Encrypt, and the Subject matches your mailserver name.
Enabling SMTPS
You may have noticed on that first openssl call that we had to tell the software to use STARTTLS in order to establish a SSL session.
This is because, by default, iRedMail doesn't ship with SMTPS enabled. The documentation notes that this is deliberate because "SMTPS is deprecated, so iRedMail disable it by default".
Whilst it's true that SMTPS is deprecated in favour of STARTTLS, various ISPs have been caught actively stripping the STARTTLS command from their customer's SMTP sessions in order to perform a downgrade-to-plain attack on the connection.
Whether SMTPS is deprecated or not, the trivial ability to perform a downgrade in this manner means SMTPS remains preferable in my book.
Enabling it is fairly straight forward
nano /etc/postfix/master.cf
# Find the commented out SMTPS line and insert this
465 inet n - n - - 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 content_filter=smtp-amavis:[127.0.0.1]:10026
Then restart postfix, and verify it's listening on port 465
service postfix restart
netstat -lnp | grep 465
tcp 0 0 0.0.0.0:465 0.0.0.0:* LISTEN 17943/master
tcp6 0 0 :::465 :::* LISTEN 17943/master
Allow port 465 through the firewall
iptables -I INPUT 9 -p tcp --dport 465 -j ACCEPT -m comment --comment "SMTPS"
iptables-save > /etc/iptables/rules.v4
You should now be able to connect with s_client and get a valid cert back
openssl s_client -connect mail2.example.com:465
MX Record
We now have a fully configured and functioning mail server, but it won't currently receive any mail because we either don't have an MX record configured, or (as in my case) it's still pointing at the old server.
So, our MX record needs to point to the name of our server (so that the cert is considered valid)
IN MX 5 mail2.example.com.
Once that's live (and TTLs have expired), mail should start coming into your server
You should also create or update your Sender Policy Framework (SPF) records.
Client Config
We now need to configure our mail clients so they can actually use the server (assuming you're not intending to just use the webmail)
Server: your server
User: ben@example.com
Receiving
- IMAP: SSL/TLS port 993. Auth PLAIN/Normal Password, or
- POP3: SSL/TLS port 995. Auth PLAIN/Normal Password
Sending:
- SMTPS: SSL/TLS port 465. Auth PLAIN/Normal Password

Conclusion
iRedMail quickly provides you with a functional, and reasonably feature complete mailserver fairly quickly.
Apart from the exclusion of SMTPS (which, to be fair, is well rationalised in their documentation) and an utterly insane step in their LetsEncrypt guide, the installation seems to be reasonably sound by default.
I am a little concerned about the iRedAdmin interface - not only am I running an older version (because of support for Debian oldstable being dropped), but the installer also installs PHP 5.6 which is technically EOL (although Debian do backport security fixes, so it's not quite as severe as it sounds).
That said, because I have an admin network available, I do have the advantage of being able to segregate that interface away from the network.
Time will tell what iRedMail is like for ongoing maintenance (installing upgrades does look like it might be a pain), but given it's underpinned by software that I was already using (Postfix, Dovecot) it shouldn't be the end of the world if (as an extreme) I find that the server needs to have the iRed* bits of it removed.
Additional
Disabling Greylisting
Greylisting is a technique used to deter spam by slightly delaying mail from domains/servers that haven't been seen before. The general principle is that our mailserver will reject mail from "new" servers for an hour.
Sending mailservers that are compatible with RFC 821 will retry later and the mail will be accepted, whereas most spam bots won't bother retrying and the spam won't be received.
The problem with greylisting, like all anti-spam defences, is it does mean there's a risk of "real" mail getting lost (or, at the very least, delayed). With this mailserver, I place more priority on ensuring mail is actually received, so decided to disable greylisting:
nano /opt/iredapd/settings.py
# locate "plugins" and remove greylisting from it
service iredapd restart
However, there is an alternative to this, which is to switch the greylisting plugin into training mode (so that it'll sit and learn about servers you commonly hear from, without actually rejecting anything)
nano /opt/iredapd/settings.py
# Add the following
GREYLISTING_TRAINING_MODE = True
systemctl restart iredapd
You can then periodically check which domains it knows about using the greylisting admin plugin. Details on how to use it are here.
Mbox Import
My old mailserver uses MBox format storage, whereas iRedMail uses Maildir, so in order to import my mailboxes I first needed to configure them.
On a Ubuntu desktop, I copied the Mbox down from my old server and then did
apt-get install mb2md
mb2md -s /tmp/user.example.com
scp -r ~/Maildir/ sohara:/tmp/
# On the mailserver, move into location
mv /tmp/Maildir/cur/* /var/vmail/vmail1/example.com/u/s/e/user-2019.05.25.12.23.36/Maildir/cur/
mv /tmp/Maildir/new/* /var/vmail/vmail1/example.com/u/s/e/user-2019.05.25.12.23.36/Maildir/new/
chown -R vmail:vmail /var/vmail/vmail1/example.com/u/s/e/user-2019.05.25.12.23.36/Maildir/
At which point, the original mail appeared in the user's inbox
Mailbox Aliases
I make fairly heavy use of mailbox aliases - i.e. so foobarsed@example.com gets delivered into my actual inbox
IRedAdmin pro exposes a form to allow you to create these, but with prices starting at $499/year that's way, way out of my price range
Instead, we just need to make a simple script to create the aliases for us (I saved as /root/add_alias.sh)
#!/bin/bash
#
# Add Alias
# Adds an alias address for an existing mailbox
if [ "$1" == "" ] || [ "$2" == "" ]
then
echo "Usage: $0 [alias@domain] [dest@domain]"
exit 1
fi
alias=$1
dest=$2
destdomain=${dest#*@}
aliasdomain=${alias#*@}
cat << EOM | mysql vmail
INSERT INTO forwardings (address, forwarding,
domain, dest_domain,
is_alias, active)
VALUES ('$alias', '$dest',
'$destdomain', '$aliasdomain',
1, 1);
EOM
Make it executable, and then add an alias
chmod +x /root/add_alias.sh
/root/add_alias.sh foobarsed@example.com ben@example.com