This tutorial is based on How To Set Up a Postfix E-Mail Server with Dovecot and picks up where the first part ended.
Please go through that tutorial first.
In this article, we will divorce mailboxes from system accounts using dovecot’s LMTP server as delivery mechanism, as well as use postgresql to keep user records.
No more mail will be delivered to the standard linux mailboxes.
Like the first guide, this tutorial is based on Debian 7 wheezy, Postfix 2.9, and dovecot 2.1 (+ Postgresql 9.1).
Install postgresql:
# aptitude install postgresql postfix-pgsql
dovecot in version 2.1 should already come with pgsql enabled. If you’re on a system where dovecot is modularised, run
# aptitude install dovecot-lmtpd dovecot-pgsql
to install the needed modules.
Adjust this for your needs if you already have a postgres setup running! But from a fresh postgres install, let’s set up authentication so that we can give dovecot access to the database. Add the following to /etc/postgresql/9.1/main/pg_ident.conf
:
mailmap dovecot mailreader
mailmap postfix mailreader
mailmap root mailreader
And the following to /etc/postgresql/9.1/main/pg_hba.conf
(Warning: Make sure to add it right after the Put your actual configuration here
comment block! Otherwise one of the default entries might catch first and the databse authentication will fail. )
local mail all peer map=mailmap
Then reload postgresql (service postgresql reload
). Now set up the database:
# sudo -u postgres psql
postgres=# CREATE USER mailreader;
postgres=# REVOKE CREATE ON SCHEMA public FROM PUBLIC;
postgres=# REVOKE USAGE ON SCHEMA public FROM PUBLIC;
postgres=# GRANT CREATE ON SCHEMA public TO postgres;
postgres=# GRANT USAGE ON SCHEMA public TO postgres;
postgres=# CREATE DATABASE mail WITH OWNER mailreader;
postgres=# \q
# sudo psql -U mailreader -d mail
postgres=# \c mail
mail=# CREATE TABLE aliases (
alias text NOT NULL,
email text NOT NULL
);
mail=# CREATE TABLE users (
email text NOT NULL,
password text NOT NULL,
maildir text NOT NULL,
created timestamp with time zone DEFAULT now()
);
mail=# ALTER TABLE aliases OWNER TO mailreader;
mail=# ALTER TABLE users OWNER TO mailreader;
mail=# \q
You can then add virtual mailboxes like this, starting from a rootshell:
# doveadm pw -s sha512 -r 100
Enter new password: ...
Retype new password: ...
{SHA512}.............................................................==
# psql -U mailreader -d mail
mail=# INSERT INTO users (
email,
password,
maildir
) VALUES (
'foo@yourdomain.tld',
'{SHA512}.............................................................==',
'foo/'
);
If you don’t want to use the command line interface to maintain the mail database, you can set up an administration interface. Let’s first add a database user that is only allowed to edit the mail databse. Go back to /etc/postgresql/9.1/main/pg_hba.conf
and add this line just under the peer authentication line you added earlier:
host pgadmin mail 127.0.0.1/32 md5
This will allow local socket connections on port 5432. (The default port for postgres)
Add the database user:
# sudo -u postgres psql
postgres=# CREATE USER pgadmin WITH PASSWORD 'new password';
postgres=# \q
Give the user the privileges to edit the mail database:
# sudo psql -U mailreader -d mail
mail=> GRANT SELECT, UPDATE, INSERT, DELETE ON users TO pgadmin;
mail=> GRANT SELECT, UPDATE, INSERT, DELETE ON aliases TO pgadmin;
mail=> \q
You can now use an administration interface like pgAdmin that is capable of using SSH tunneling to directly connect to the database, or you could set up something like phpPgAdmin.
We need to connect dovecot to the database and set up the LMTP server. Set up a new user (dovecot will refuse to handle mail without a system user set up for it) and directory for maildirs first: (you could use /var/mail, but that traditionally uses the mbox format, while we’re going to be using the superior maildir format).
# adduser --system --no-create-home --uid 500 --group --disabled-password --disabled-login --gecos 'dovecot virtual mail user' vmail
# mkdir /home/mailboxes
# chown vmail:vmail /home/mailboxes
# chmod 700 /home/mailboxes
Now save the following configuration as /etc/dovecot/dovecot-sql.conf
:
driver = pgsql
connect = host=/var/run/postgresql/ dbname=mail user=mailreader
default_pass_scheme = SHA512
password_query = SELECT email as user, password FROM users WHERE email = '%u'
user_query = SELECT email as user, 'maildir:/home/mailboxes/maildir/'||maildir as mail, '/home/mailboxes/home/'||maildir as home, 500 as uid, 500 as gid FROM users WHERE email = '%u'
Make sure it is owned by root and chmodded 600.
Now open /etc/dovecot/dovecot.conf
and edit the passdb
and userdb
settings to look like this:
userdb {
driver = prefetch
}
passdb {
args = /etc/dovecot/dovecot-sql.conf
driver = sql
}
Change the protocols stanza to
protocols = imap lmtp
and add the lmtp service socket and some lmtp protocol settings:
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
group = postfix
mode = 0600
user = postfix
}
}
protocol lmtp {
postmaster_address=postmaster@yourdomain.com
hostname=mail.yourdomain.com
}
The mail_location stanza is now superfluous and can be removed.
We now need to tell postfix to deliver mail directly to dovecot. Open /etc/postfix/main.cf
and add
mailbox_transport = lmtp:unix:private/dovecot-lmtp
to the end. Now we need to set the database config for postfix.
Create the file /etc/postfix/pgsql-aliases.cf
and enter:
user=mailreader
dbname=mail
table=aliases
select_field=alias
where_field=email
hosts=unix:/var/run/postgresql
Then create the file /etc/postfix/pgsql-boxes.cf
and enter:
user=mailreader
dbname=mail
table=users
select_field=email
where_field=email
hosts=unix:/var/run/postgresql/
Now amend the alias_maps line in main.cf to read
alias_maps = hash:/etc/aliases proxy:pgsql:/etc/postfix/pgsql-aliases.cf
and the local_recipient_maps line to read
local_recipient_maps = proxy:pgsql:/etc/postfix/pgsql-boxes.cf $alias_maps
In whole, your main.cf should look similar to this:
myhostname = mail.mydomain.com
myorigin = mydomain.com
mydestination = mydomain.com, mail.mydomain.com, localhost, localhost.localdomain
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
alias_maps = hash:/etc/aliases proxy:pgsql:/etc/postfix/pgsql-aliases.cf
local_recipient_maps = proxy:pgsql:/etc/postfix/pgsql-boxes.cf $alias_maps
mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtpd_tls_cert_file=/etc/ssl/certs/mailcert.pem
smtpd_tls_key_file=/etc/ssl/private/mail.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_security_level=may
smtpd_tls_protocols = !SSLv2, !SSLv3
Now simply reload:
# postfix reload
# service dovecot restart
And you’re set! Test your setup as you did after the first article, and make sure mail to postmaster@yourdomain.com
finds its way into an attended mailbox!
Submitted by: Lukas Erlacher.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
<b>“If you’re on a system where dovecot is modularised”</b>
What does that mean? Is Ubuntu 12.04 such a system?
It would be way better if you included postfixadmin in tutorial for managing domains and mail accounts
Pablo - if you run “apt-cache show dovecot” it will tell you that dovecot is a virtual package, and you will have dovecot-core, dovecot-common, dovecot-imapd etc. as separate packages. In the old, non-modularised setup, there is just one dovecot package that contains all dovecot modules. I don’t know how Ubuntu does it but I’d wager they’ve also moved to modularised.
amar - Maybe another day. Personally I think it’s important to do a mail server setup “by hand”. Cookie-cutter solutions like postfixadmin restrict what you can do and usually break if you want to do something like the lmtp setup in this tutorial. And if they aren’t walled off from the internet, they are usually an open door to getting your box hacked - and most people don’t want to set up tunneling or a VPN to do that.
Gave me an error: The message could not be sent because the connection to SMTP server “mail.domainname.com” timed out. Try again or contact your network administrator. What can be wrong?
@nandor: Did you create proper DNS records for mail.domainname.com? Both MX and A records.
Yes, and after applying your first tutorial the mail server was working very well. Only this part is not ok for me.
I tried the above on a CentOS 6 system instead, and everything seems to work accept for when I try a remote IMAP connection to the server. I then get the following error:
Jan 13 20:32:42 dovecot: auth: Fatal: No passdbs specified in configuration file. PLAIN mechanism needs one Jan 13 20:32:42 dovecot: master: Error: service(auth): command startup failed, throttling
Any idea what part I missed or mistyped?
@mark: Please pastebin dovecot’s config file. Make sure you try restarting it first in case it didn’t catch a config file edit or something.
Hi Kamal, I checked the log and realized I just mistyped one thing. So it’s working very well. :) And thanks a lot in the name of many people. You are one of the people who gave us a really working config and explanation as well. We are waiting for the 3rd part of the config. :) When checking the mail.log I saw many attempt from different IPs. I would lovely read an another very useful tutorial how to make the server more secure. Thanks a lot! :)
@nandor: Glad you managed to get it working!
P.S.: <a href=“https://twitter.com/learlyman”>Lukas Erlacher</a> wrote this article, not me. :]