Here we are on a Debian Linux, such as Ubuntu and we want to run a mail server. Exim4 is currently the most popular email server, but getting it up and working for free is a hassle – who wants to pay for a SSL certificate, on an ongoing basis? And then there’s the maintenance of the security of it – constant renewal, renouncing and re-installation of the certificates.
Wherever you see example.com, swap in your Fully Qualified Domain Name. That may be mail.example.com
It’s assumed you’re not logged in as root, but user ubuntu
Wherever you see 220.127.116.11, swap in your machine’s local IP address, from
ifconfig | grep "inet addr" | grep -v "127.0.0.1"
Security is all handled automatically by LetsEncrypt’s certbot. I’ll let you look that one up yourself. Run it up and get your certificate for example.com
Once you’ve got that handled, punch a hole in your firewall so that port 25 can get through from the outside world to your machine. Be aware: the outside world is filled full of botnets trying to hack into your machine. After installing exim, keep an eye on the logs in /var/log/exim4/ for a while.
Let’s install exim4:
sudo apt-get install exim4
sudo dpkg-reconfigure exim4-config
- pick “Internet site”
- system mail name is example.com
- IP address is 18.104.22.168 (the one returned by ifconfig, not the externally accessable one)
- Other destinations: example.com
- No relays
- No smarthost
- No Dial-on-Demand
- mbox format (or whatever)
- Split the files
- ubuntu for postmaster mail
Check we’re now running a mail server:
sudo netstat -napt
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 22.214.171.124:25 0.0.0.0:* LISTEN 25700/exim4
Now we have a mail server, the world needs to find it. Check your nameserver setting to ensure mail is destined this machine. You probably want only one MX record.
Check the Internet can send mail to our server. After allowing for the appropriate propagation delay for your nameserver changes, use gmail or something to send an email to email@example.com – you should be able to read it by typing
Now it’s time to enable MTA-MTA link encryption for secure transport of mail, by enabling STARTTLS on exim4 using our LetsEncrypt certificate
sudo nano /etc/exim4/conf.d/main/03_exim4-config_tlsoptions
Enable STARTTLS by adding/setting in the tlsoptions section:
MAIN_TLS_ENABLE = yes
MAIN_TLS_CERTKEY = no
before any of the IF shenanigans. Also add/replace pointers to the certificates:
tls_certificate = /etc/letsencrypt/live/example.com/fullchain.pem
tls_privatekey = /etc/letsencrypt/live/example.com/privkey.pem
The MAIN_TLS_CERTKEY = no entry fixes an exim4 log message
2017-04-16 09:13:24 TLS error on connection from your.home.ip.com (IcePlanet) [126.96.36.199] (cert/key setup: cert=/etc/exim4/exim.crt key=/etc/exim4/exim.key): Error while reading file.
You will see this when testing with swaks:
$ swaks -a -tls -q HELO -s example.com -au test -ap '<>'
=== Trying example.com:25...
=== Connected to example.com.
< - 220 your.vps.host.com ESMTP Exim 4.86_2 Ubuntu Sun, 16 Apr 2017 09:13:24 +0000 -> EHLO IcePlanet
< - 250-your.vps.host.com Hello your.home.ip.com [188.8.131.52]
< ** 454 TLS currently unavailable *** STARTTLS attempted but failed -> QUIT
< - 221 your.vps.host.com closing connection
=== Connection closed with remote host.
Allow exim (which when running runs as user
Debian-exim) to get to the certificates:
sudo groupadd privkey_users sudo usermod -aG privkey_users Debian-exim sudo sudo chmod g+rx /etc/letsencrypt/live/ sudo sudo chmod g+rx /etc/letsencrypt/archive/ sudo chown root:privkey_users /etc/letsencrypt/archive/ sudo chown root:privkey_users /etc/letsencrypt/archive/example.com/ sudo chown root:privkey_users /etc/letsencrypt/archive/example.com/cert1.pem sudo chown root:privkey_users /etc/letsencrypt/archive/example.com/chain1.pem sudo chown root:privkey_users /etc/letsencrypt/archive/example.com/privkey1.pem sudo chown root:privkey_users /etc/letsencrypt/archive/example.com/fullchain1.pem sudo chown root:privkey_users /etc/letsencrypt/live/ sudo chown root:privkey_users /etc/letsencrypt/live/example.com/
Changing these permissions doesn’t affect apache2’s ability to get them.
The reason we’ve used a group here is to allow both exim and any other app (for example, a secondary service that wants to use 8080 to serve up a configuration page) to access the private keys; just add any other user that needs to use the private keys to the privkey_users group.
These permission changes prevent the following error message in your log file:
2008-06-03 08:27:35 TLS error on connection from me.at.home.com ([184.108.40.206]) [220.127.116.11] (cert/key setup: cert=/etc/ssl/certs/server.pem key=/etc/ssl/private/server.key): Error while reading file.
Restart the service and the TLS settings ought to be working
sudo service exim4 restart
Test STARTTLS is working from another machine
swaks -a -tls -q HELO -s example.com -au test -ap '<>'
There shouldn’t be any obvious complaining.
Thanks for your post. I followed your instructions and at the end got
<- 250 HELP
*** Host did not advertise STARTTLS
After removing the line below it now works.
MAIN_TLS_CERTKEY = no
You have sudo sudo in the first two chmod lines
sudo sudo chmod g+rx /etc/letsencrypt/live/
sudo sudo chmod g+rx /etc/letsencrypt/archive/
Do the owner and permission changes at /etc/letsencrypt/live/* remain after certbot renews the certificaties?
Hi, i have an error ;
(cert/key setup: cert=/etc/letsencrypt/live/yournotgoinghavemydomain/fullchain.pem key=/etc/letsencrypt/live/yournotgoinghavemydomain/fullchain.pem): The requested data were not available.
I’ve followed all steps.
Thank you for the interesting and very helpful article, but I am also getting the same error as the last guy here, “The requested data were not available”
Exim requires certs to be under /etc/exim, CONFDIR in the config files. Symlinks will not work, so you have to copy the files manually.
Pingback: Exim with letsencrypt certbot | Sarel, a Pragmatic Programmer
I was also very confused with “The requested data were not available.” Then I saw that exim tries to load cert and key from the same file.
The right variables are:
MAIN_TLS_CERTIFICATE = …/fullchain.pem
MAIN_TLS_PRIVATEKEY = …/privkey.pem
using MAIN_TLS_CERTKEY activates some legacy mode where BOTH certificate and key are read from the same file.