Mail Server with Dovecot and Exim4
Posted on January 19th, 2009 in Linux | No Comments »
I am changing my hosting around at the moment and have a new server, that is completely managed by myself. One of my first requirements is to setup up mail hosting for my domains. Since I am not using any sort of control panel or packaged software, I have to configure this by hand. My needs are simple: virtual users, TLS/SSL security and to run with a small footprint. Further down the track, I also plan on adding virus and spam filtering.
Software
First off, I had to choose the software I would use. I elected t use Dovecot for my IMAP server and Exim4 for my MTA. Dovecot is an excellent choice for an IMAP server as it is designed with security in mind, is simple to configure has a low memory footprint, performs excellently and supports the Maildir format which I intended to use. Exim4 is a good MTA, with a simple and clean configuration (relative to Sendmail!) and is designed with consideration to security.
My server is running Debian Etch, so installation of these packages through apt is easy. However, I had to install Exim4 from Backports as version 6.64 and later include an authentication driver for dovecot that allowing Exim4 to authenticate SMTP sessions against the Dovecot user database. The version of Exim4 that ships with Etch is 6.63, which means I either had to compile a new version from source or use Exim4 from Backports. I elected to use Backports. Installing the required software is easy, once you have the etch-backports repository (note, exim4-daemon-heavy has the extra Dovecot authentication driver):
Configuration
I started by configuring Dovecot so I could access a users Maildir through IMAPS. Because all users would be virtual, the Maildir's would be stored in /home/vmail/$user@$domain/Maildir/ and owned by vmail:vmail. It should be noted here that the Maildir's have the executable permission set on them so that Exim4 can validate that the user exists. Failure to do so will cause Exim4 to report an Unroutable Address error.
The contents of my /etc/dovecot/dovecot.conf contains a line by line description in comments, and is more or less pretty painless:
This then leaves my user configuration in /etc/dovecot/passwd formatted as follows:
To generate passwords other then plain, use the dovecotpw program, e.g. dovecotpw -s SSHA
Configuring Exim4 is slightly tricker, also note that I am using the Debian split configuration here, so if you are using the monolithic single file configuration, you will have to figure out where things go yourself.
First either update your update-exim4.conf.conf by hand and issue the `update-exim4.conf` command or use `dpkg-reconfigure exim4-config` to configure your install as a Internet mail server listening on a public interface and to accept email for the domains you plan to host email for. Once this was done I began to configure Exim4 to work the way I wanted. In order to do this I had to do a few things.
Configuring TLS
If you do not already have a certificate you may use `/usr/share/doc/exim4-base/examples/exim-gencert` to generate the exim.crt and exim.key files which are placed in /etc/exim4. Once I had my certificates I set the MAIN_TLS_ENABLE macro to true. I did this by creating the file /etc/exim4/conf.3/main/00_local containing:
You should notice that the server_socket corresponds to my configuration in the Dovecot config file.
Alias & Virtual Emails Routing
My actual email accounts do not correspond to system users and as such Exim4 needs a mechanism to know if an email is valid (and how to deliver it, however I deal with that in the next section). As well as this, I wanted to allow aliases to be created, for example alias@example.org is an alias for user1@example.org. In order to do this I created both an alias router and a router to my virtual mailbox's (my Dovecot configuration expects the mailboxes to be in /home/vmail/user@domain/Mailbox).
I first created a router for Dovecot in /etc/exim4/conf.d/router/880_dovecot_router. It must be noted that this sends it to a transport called dovecot_transport. This is not yet created, however I will create one shortly. Also, we allow the local part to have a suffix, this allows us to route emails such as user1+emailsuffix@example.org which you may wish to mark certain subscriptions with.
I also created a virtual alias router to allow me to specify mappings, such as a catchall for a domain *@example.org -> user1@example.org or aliases such as alias@example.org -> user1@example.org. To do this I created the file /etc/exim4/conf.d/router/870_virtual_aliases
Along with this, I also maintain two files /etc/exim4/virtual.users that specifies my aliases:
Virtual Email Delivery
In order to deliver mail to my virtual user's Maildir, which will allow Dovecot to read them I had to create my own transport. There are two ways to accomplish this. I could deliver to the Maildir directly or use Dovecot's deliver binary. Dovecot's deliver will do magical things such as update Dovecot's transparent indexes, so this is the approach I took, and would recommend. I will however also provide the Maildir transport but commented out. I defined my dovecot_transport in /etc/exim4/conf.d/transport/36_dovecot_transport:
Testing
You may also test your configuration with a few commands in order to work out how and where email is being delivered to, I recommend you try this on an alias. You should see it map to a virtual address.
To run exim in address testing mode (pass the -d flag for debugging information)
And lastly, you are able to use SMTP directly by starting a telnet session to port 25 and testing things out. It should appear something like this (the lines without the prefixed numbers are what I type):
Software
First off, I had to choose the software I would use. I elected t use Dovecot for my IMAP server and Exim4 for my MTA. Dovecot is an excellent choice for an IMAP server as it is designed with security in mind, is simple to configure has a low memory footprint, performs excellently and supports the Maildir format which I intended to use. Exim4 is a good MTA, with a simple and clean configuration (relative to Sendmail!) and is designed with consideration to security.
My server is running Debian Etch, so installation of these packages through apt is easy. However, I had to install Exim4 from Backports as version 6.64 and later include an authentication driver for dovecot that allowing Exim4 to authenticate SMTP sessions against the Dovecot user database. The version of Exim4 that ships with Etch is 6.63, which means I either had to compile a new version from source or use Exim4 from Backports. I elected to use Backports. Installing the required software is easy, once you have the etch-backports repository (note, exim4-daemon-heavy has the extra Dovecot authentication driver):
sudo apt-get -t etch-backports install exim4-daemon-heavy sudo apt-get install dovecot-imapd
Configuration
I started by configuring Dovecot so I could access a users Maildir through IMAPS. Because all users would be virtual, the Maildir's would be stored in /home/vmail/$user@$domain/Maildir/ and owned by vmail:vmail. It should be noted here that the Maildir's have the executable permission set on them so that Exim4 can validate that the user exists. Failure to do so will cause Exim4 to report an Unroutable Address error.
The contents of my /etc/dovecot/dovecot.conf contains a line by line description in comments, and is more or less pretty painless:
# Protocols (others available imap, pop3, pop3s)
protocols = imaps
# Log files for Dovecot
log_path = /var/log/dovecot/main.log
info_log_path = /var/log/dovecot/info.log
# SSL settings (I already generated my certificate, if you don't know how visit http://letmegooglethatforyou.com/?q=openssl%20generate%20certificate).
ssl_listen = *
ssl_disable = no
ssl_cert_file = /etc/ssl/certs/example.crt
ssl_key_file = /etc/ssl/private/exmaple.key
# Auth Settings (do not allow plaintext auth (except when under SSL/TLS)
disable_plaintext_auth = yes
# We are not really a very busy imap server, so we dont need a large number of processes waiting for logon
login_processes_count = 1
# So we get information about processes (in ps).
verbose_proctitle = yes
# Login process can auth multiple connections (less secure then yes, but I'm aiming for less overall processes)
login_process_per_connection = no
# We're using Maildir format
mail_location = maildir:~/Maildir
# we want group xwrx--x-- so exim can validate the addresses (it does a stat on /home/vmail/local_part@domain_part/
umask = 0066
# Not required for me, but in there in case I ever want to support pop3.
# Outlook 2003 has problems with the default, while %08Xu%08Xv is regarded as more or less safe.
pop3_uidl_format = %08Xu%08Xv
# 108 is my vmail user id. If this is too high, Dovecot will not allow the user to read/write the Maildir's
first_valid_uid = 108
# Optimizations
maildir_copy_with_hardlinks=yes
# Authentication Config
auth_verbose = yes
auth default {
mechanisms = plain login
passdb passwd-file {
args = /etc/dovecot/passwd
}
userdb static {
args = uid=vmail gid=vmail home=/home/vmail/%u
}
socket listen {
# This allows authentication to take place between lda (the dovecot deliver) and dovecot
master {
path = /var/run/dovecot/auth-master
mode = 0600
user = vmail
group = vmail
}
# This allows Exim4 to authenticate against Dovecot's user database
client {
path = /var/run/dovecot/auth-client
mode = 0666
user = vmail
group = vmail
}
}
}
# deliver Configuration
protocol lda {
postmaster_address = postmaster@example.org
log_path = /var/log/dovecot/deliver.log
info_log_path = /var/log/dovecot/deliver.log
auth_socket_path = /var/run/dovecot/auth-master
}
This then leaves my user configuration in /etc/dovecot/passwd formatted as follows:
#
# Example.org
#
user1@example.org:{PLAIN}plaintxtpass
user2@example.org:{SSHA}mp9sL0Xl1kqi2N/3g/E6qU/PTtV/+qEx
To generate passwords other then plain, use the dovecotpw program, e.g. dovecotpw -s SSHA
Configuring Exim4 is slightly tricker, also note that I am using the Debian split configuration here, so if you are using the monolithic single file configuration, you will have to figure out where things go yourself.
First either update your update-exim4.conf.conf by hand and issue the `update-exim4.conf` command or use `dpkg-reconfigure exim4-config` to configure your install as a Internet mail server listening on a public interface and to accept email for the domains you plan to host email for. Once this was done I began to configure Exim4 to work the way I wanted. In order to do this I had to do a few things.
Configuring TLS
If you do not already have a certificate you may use `/usr/share/doc/exim4-base/examples/exim-gencert` to generate the exim.crt and exim.key files which are placed in /etc/exim4. Once I had my certificates I set the MAIN_TLS_ENABLE macro to true. I did this by creating the file /etc/exim4/conf.3/main/00_local containing:
MAIN_TLS_ENABLE = trueConfiguring Authentication with Dovecot As I said before, Exim4 can be used to authenticate against Dovecot. In order do do this I created the file /etc/exim4/conf.d/auth/20_dovecot and inside placed:
dovecot_login: driver = dovecot public_name = LOGIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 dovecot_plain: driver = dovecot public_name = PLAIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1
You should notice that the server_socket corresponds to my configuration in the Dovecot config file.
Alias & Virtual Emails Routing
My actual email accounts do not correspond to system users and as such Exim4 needs a mechanism to know if an email is valid (and how to deliver it, however I deal with that in the next section). As well as this, I wanted to allow aliases to be created, for example alias@example.org is an alias for user1@example.org. In order to do this I created both an alias router and a router to my virtual mailbox's (my Dovecot configuration expects the mailboxes to be in /home/vmail/user@domain/Mailbox).
I first created a router for Dovecot in /etc/exim4/conf.d/router/880_dovecot_router. It must be noted that this sends it to a transport called dovecot_transport. This is not yet created, however I will create one shortly. Also, we allow the local part to have a suffix, this allows us to route emails such as user1+emailsuffix@example.org which you may wish to mark certain subscriptions with.
dovecot_router:
driver = accept
local_part_suffix = +*
local_part_suffix_optional
require_files = +/home/vmail/${local_part}@${domain}/Maildir
transport = dovecot_transport
I also created a virtual alias router to allow me to specify mappings, such as a catchall for a domain *@example.org -> user1@example.org or aliases such as alias@example.org -> user1@example.org. To do this I created the file /etc/exim4/conf.d/router/870_virtual_aliases
virtual:
driver = redirect
allow_defer
allow_fail
data = ${lookup{$local_part@$domain}lsearch*@{/etc/exim4/virtual.users}}
domains = partial-lsearch;/etc/exim4/virtual.domains
retry_use_local_part
Along with this, I also maintain two files /etc/exim4/virtual.users that specifies my aliases:
# # Example.org # alias@example.org : user1@example.org *@example2.org : user2@example.orgAnd /etc/exim4/virtual.domains which specifies any domain with a virtual alias:
example.org example2.org
Virtual Email Delivery
In order to deliver mail to my virtual user's Maildir, which will allow Dovecot to read them I had to create my own transport. There are two ways to accomplish this. I could deliver to the Maildir directly or use Dovecot's deliver binary. Dovecot's deliver will do magical things such as update Dovecot's transparent indexes, so this is the approach I took, and would recommend. I will however also provide the Maildir transport but commented out. I defined my dovecot_transport in /etc/exim4/conf.d/transport/36_dovecot_transport:
#dovecot_transport:
# driver = appendfile
# user = vmail
# group = vmail
# mode = 0600
# directory=/home/vmail/${lc:$local_part}@${lc:$domain}/Maildir/
# maildir_format = true
# mode_fail_narrower = false
# envelope_to_add = true
# return_path_add = true
dovecot_transport:
driver = pipe
command = /usr/lib/dovecot/deliver -d $local_part@$domain
message_prefix =
message_suffix =
log_output =
delivery_date_add
envelope_to_add
return_path_add
group = vmail
user = vmail
Rebuilding Configuration& Restarting
With all this done, I rebuilt the exim4 configuration file with `update-exim4.conf.template` and restarted both Dovecot and Exim4. They should be now configured to process and serve Email together:
sudo update-exim4.conf.template -r sudo /etc/init.d/dovecot restart sudo /etc/init.d/exim4 restart
Testing
You may also test your configuration with a few commands in order to work out how and where email is being delivered to, I recommend you try this on an alias. You should see it map to a virtual address.
To run exim in address testing mode (pass the -d flag for debugging information)
exim -bt 'user1@example.org'To run exim in address verification mode (pass the -d flag for debugging information)
exim -bv 'user1@example.org'
And lastly, you are able to use SMTP directly by starting a telnet session to port 25 and testing things out. It should appear something like this (the lines without the prefixed numbers are what I type):
khaless@galactica:~$ telnet localhost 25 Trying 127.0.0.1... Connected to localhost.localdomain. Escape character is '^]'. 220 galactica ESMTP Exim 4.69 Mon, 19 Jan 2009 01:38:29 -0500 EHLO example.org 250-galactica Hello localhost.localdomain [127.0.0.1] 250-SIZE 52428800 250-PIPELINING 250-AUTH LOGIN PLAIN 250-STARTTLS 250 HELP MAIL FROM: user1@example.org 250 OK RCPT TO: user2@example.org 250 Accepted DATA 354 Enter message, ending with "." on a line by itself Subject: My Test Email Hello, I am a test email. . 250 OK id=1LOnmh-0006Hx-Vt quit 221 galactica closing connection Connection closed by foreign host. khaless@galactica:~$