Challenge

In the following article I will explain how to setup postfix and dovecot on debian squeeze using virtual users stored in a text-file.
I wanted to setup a mail system which supports local mailboxes via imap and pop3. Next the mail server should provide connections using SSL / TLS.
Finally every users account should only be a virtual user account which is stored in a text-file instead of a MySQL database.

text-file versus MySQL database

On my server only few mailboxes are needed. I don’t need to run a MySQL server containing a database which has only 30 entries. I think running a MySQL server for this is not needed till you reach a threshold of 500 accounts.
It’s easier and faster for the services to lookup in a text-file instead of calling MySQL for a result.

Checking hostname

hostname
hostname --fqdn

postfix and other services use the full qualified domain name (short: fqdn) for recognition on the web. Be sure that this is set correctly.
It has to be a domain like sub.domain.tld, e.g. lukas.example.org.

Install postfix, dovecot and sasl

We need to install postfix and dovecot. For authorisation on the server, we also need sasl. It’s not neccessary to configure sasl, this will dovecot do for us.
First we check whether our system is up-to-date and after this, we install sasl, postfix and dovecot.

During the installation of postfix the installer asks you which configuration it should set up.
Choose Internet Site and enter the fqdn of your server on the next configuration page.

apt-get update
apt-get upgrade
apt-get install libsasl2-2 libsasl2-modules sasl2-bin postfix dovecot-common dovecot-imapd dovecot-pop3d

Configure sasl

Sasl is used for authentication on the server.
Because dovecot handles sasl, we only need to install and activate the sasl daemon.

Just open the file /etc/default/saslauthd and add or comment out

START=yes

This allows the sasl daemon to be started.

Now open or create /etc/postfix/sasl/smtpd.conf and input:

pwcheck_method: saslauthd

At the end start the sasl daemon manually. On the next boot it will be started automatically.

/etc/init.d/saslauthd start

Generate an SSL certificate

To enable SSL for your users, you need to generate an ssl certificate.
Some mail clients may have problems with self-signed certificates, because the are not signed by a recognized certificate authority. In this cases you may should use commercial certificates.
postfix can handle all kind of ssl certificate out there. So just create your own certificate the following way.

It’s important that you set the Common Name to the full domain your users connect to authenticate and send mails. If you use mail.example.org as smtp host for your users, the Common Name of your SSL certificate has to be mail.example.org!

openssl req -new -x509 -days 365 -nodes -out /etc/ssl/certs/postfix.pem -keyout /etc/ssl/private/postfix.key

Create system user for virtual mails

For handling the incoming mails we should create a separate user who has only access to the mailboxes.
We create this user with groupid 5000 and userid 5000.

groupadd vmail -g 5000

The user should created as a system-account (flag -r), so it has no login and is not saved in /etc/shadow.

useradd vmail -r -c "virtual mail user" -d /var/vmail -m -g 5000 -u 5000

System accounts also don’t get a home directory. Because of this we need to set and create an own.
We want to save our mails in /var/vmail, so we use /var/vmail as our new home directory. Also it must be created, so we add flag -m.

Now check if everything worked well:

id vmail

This sould return you the username, userid and groupid as mentioned above.

Last we have to give user vmail all rights for its home directory:

chown -R vmail:vmail /var/vmail

Postfix

Next we have to set up the configuration of postfix in /etc/postfix/main.cf.
Your main.cf should contain these lines:

# should be the FQDN of your machine
myhostname=lukas.example.org
# internet domain name of your system.
# Default is to use $myhostname without the sub-domain
mydomain=example.org
# the domain from which local emails will be from: [email protected]
myorigin=$mydomain

# in master.cf we use the flag D for single delivered-to headers
# so we need to tell dovecot that every recipient should get its own mail
dovecot_destination_recipient_limit = 1

# set to localhost, because we handle all domains via virtual_mailbox_domains
mydestination = localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
inet_interfaces = all
mailbox_size_limit = 0
recipient_delimiter = +

# debug level for messages in log. level 2 is the default one
debug_peer_level=2
# debug request only coming from this IP
#debug_peer_list=127.0.0.1

# the banner your mail system will greet a client who opens a socket to us
smtpd_banner=$myhostname ESMTP $mail_name
# disable information messages to local users about new emails
biff=no

# we don't use relayhost, so set it empty
relayhost=
# disable showing why the user does not exist in your system
show_user_unknown_table_name=no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

# allow MAIL FROM only from defined users
smtpd_sender_login_maps = hash:/etc/postfix/sender_login_maps
smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch

# local aliases for postmaster, root, ...
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

If you change the file /etc/aliases you have to call

postalias /etc/aliases

to activate the changes!

Virtual users and virtual mailboxes

We don’t want to create an user account on our server for every single mailbox.
So we use virtual mailboxes and virtual users defined in files to handle incoming e-mails.

The following table shows which functions are used together:

Domain_class Recipient_map Transport
Local(mydestination) local_recipient_maps local mailbox_transport
relay_domains relay_recipient_maps relay
virtual_mailbox_domains virtual_mailbox_maps virtual

We are using the last one: virtual_mailbox_domains with virtual_mailbox_maps.

First we need a list of all accepted domains.
If you accept emails also coming from a sub-domain of a domain, you have to list it explicitely!
The list has 2 columns on which the domains are listed on the left-handed side.
The content of the right-handed side is not needed, so you can place there comments or something else.

Create a file /etc/postfix/virtual_mailbox_domains

example.org OK
shop.example.org OK
example.com OK

The file virtual_mailbox_maps contains all mailboxes you want to store on your server.
You can use any directory structure you want, but I prefer to sort it by the domain names. A mailbox for @example.org should be found in the directory /var/vmail/example.org.
The file is also a 2 columns file.
On the left side you have to give the full e-mail address.
On the right side you have to give the relative path to the mailbox.

Create a file /etc/postfix/virtual_mailbox_maps

[email protected] example.org/contact
[email protected] example.org/lukas
[email protected] example.org/lukas

The folder structure is important for dovecot. If you have 2 mailaddresses for a single mailbox, the user will only be able to login with [email protected].

The third file /etc/postfix/virtual_alias_maps contains all e-mail addresses which you want to redirect to another one.
It’s again a 2 columns file with the incoming e-mail address on the left side and the e-mail addresses you want to redirect on the right side.
You can separate multiple destinations by a comma.

Create a file /etc/postfix/virtual_alias_maps

To check whether your virtual mail information is valid you can call

postmap -q [email protected] hash:/etc/postfix/virtual_alias_maps

To redirect aliases like root, postmaster etc. just add

to your virtual_alias_maps or add it like an mailbox to virtual_mailbox_maps.

After every change you have to call postmap /etc/postfix/[changed-file] and reload postfix to activate the changes!

postmap hash:/etc/postfix/virtual_mailbox_domains
postmap hash:/etc/postfix/virtual_mailbox_maps
postmap hash:/etc/postfix/virtual_alias_maps
postfix reload # or: /etc/init.d/postfix reload

Next we need to add the virtual information to the configuration of postfix in /etc/postfix/main.cf

# virtual domain options
###############################
# save destination of the incoming mails
virtual_mailbox_base=/var/vmail
# the following 3 files are 2-columns files. I will call the left column the left side handed (LSH) and the right column the right side handed (RSH)
# contains the domain names for which emails will be accepted. The LSH contains the names, the RSH any string but at least one char (e.g. OK)
virtual_mailbox_domains=hash:/etc/postfix/virtual_mailbox_domains
# contains the virtual mailboxes for which emails will be saved on this system. LSH: incoming e-mail address, RSH: location of the mailbox relative to $virtual_mailbox_base
virtual_mailbox_maps=hash:/etc/postfix/virtual_mailbox_maps
# contains the redirections. LSH: incoming e-mail address, RSH: forwarding e-mail address, multiple forwading addresses are seperated with comma
virtual_alias_maps=hash:/etc/postfix/virtual_alias_maps

# userid of the virtual mailbox user we created
virtual_uid_maps=static:5000
# groupid of the virtual mailbox user we created
virtual_gid_maps=static:5000
# delivery agent we use to save the mails
virtual_transport=dovecot

Allow specific MAIL-FROMs for defined users

If you want to allow that every user can send e-mails from every sender-name comment the following lines in our /etc/postfix.main.cf:

# allow MAIL FROM only from defined users
smtpd_sender_login_maps = hash:/etc/postfix/sender_login_maps
smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch

Otherwise you have to define every single sender address for every user!

The file /etc/postfix/sender_login_maps has two columns:

Because we use our e-mail address as username, in the second column the e-mail address has to be repeated.
User [email protected] is allowed to send e-mails from schulze@…, book@…, and info@…
User [email protected] cannot use schulze@… as sender address.
User [email protected] is not allowed to send e-mails from bob@…, he can only use info@…

After every change on the file /etc/postfix/sender_login_maps you have to create a new hash file and reload the postfix server:

postmap hash:/etc/postfix/sender_login_maps
postfix reload # or: /etc/init.d/postfix reload

Dovecot

Now it’s time to configure dovecot.

First we set some general settings.
We have to add the supported protocols and who’s responsible for authentication.
The lda protocol is needed for interacting with postfix.
Open file /etc/dovecot/dovecot.conf and set:

protocols = imap imaps pop3 pop3s
log_timestamp = "%Y-%m-%d %H:%M:%S "

auth_executable = /usr/lib/dovecot/dovecot-auth
auth_verbose = yes

protocol lda {
auth_socket_path = /var/run/dovecot/auth-master
postmaster_address = [email protected]
mail_plugins = sieve
log_path =
}

Now we make sure that only the user vmail is used for pop3 and imap logins.

#only allow vmail user to login
first_valid_uid=5000
last_valid_uid=5000
first_valid_gid=5000
last_valid_gid=5000
mail_privileged_group = vmail

Next we have to set the location for the mails. This is /var/vmail.
In dovecot %d maps to the domain name, %n maps to the username of the e-mail address and %u maps to the full e-mail address.
We use the location /var/vmail/example.org/contact for the e-mail address [email protected].
For this our mail_location has to be set to

mail_location = maildir:/var/vmail/%d/%n/Maildir

We use the Maildir directory because the rules for server-side filtering (like sieve) save the rules in the users directory. Otherwise the virtual user would not be able to create a rule with name dovecot-uidlist.
There are definitively less problems if you use an additional directory like Maildir.

Now we set up the users who can login to our server via pop3 and imap.
We must add the authorisation section to the dovecot configuration.

Some mail clients send login as authorisation information. For these clients we have to support both mechanisms: plain and login.
We save the users and their passwords in /etc/dovecot/users.conf.
The standard password hashing algorithmus is SHA1.
The user-database is a static file and our system user vmail is allowed to create every mailbox directory for which the dovecot delivery agent gets e-mails.

auth default {
mechanisms = plain login
passdb passwd-file {
args = scheme=SHA1 /etc/dovecot/users.conf
}
userdb static {
args = uid=5000 gid=5000 home=/var/vmail/%d/%n allow_all_users=yes
}
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0600
user = vmail
group = vmail
}
client {
path = /var/spool/postfix/private/auth
mode = 0660
user = postfix
group = postfix
}
}
}

Now we need to create the users database.
Create an empty text-file named /etc/dovecot/users.conf.

Now run

dovecotpw -s SHA1

and enter a password.
It outputs you a hash like {SHA1}Za3aQyaRRXZAXJ46YvSQTZZXOGM=
Next open /etc/dovecot/users.conf and add an user:

[email protected]:{SHA1}Za3aQyaRRXZAXJ46YvSQTZZXOGM=

Every e-mail address defined in /etc/postfix/virtual_mailbox_maps should be found in the users.conf
It is very important that the username [email protected] is the same as the e-mail address defined in virtual_mailbox_maps!

Dovecot automatically maps the username to existing mailboxes. The username [email protected] maps to the mailbox /var/vmail/example.org/contact.
This user can login into your system using the username [email protected] and the password you added in /etc/dovecot/users.conf.

It is important that we set the correct permissions on /etc/dovecot/users.conf and /etc/dovecot/dovecot.conf.

# vmail must be able to read the dovecot configuration
chgrp vmail /etc/dovecot/dovecot.conf
chmod g+r /etc/dovecot/dovecot.conf

# don't let the world read your dovecot users and passwords
chown root:root /etc/dovecot/users.conf
chmod 600 /etc/dovecot/users.conf

Now we have to tell postfix that it should deliver incoming mails to dovecot.
For this open /etc/postfix/master.cf, not the main.cf!
Add at the end:

# Dovecot LDA
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}

The 2 white spaces in front of flags=DRhu are important!

After saving /etc/postfix/master.cf you have to restart postfix. Only reloading postfix is not enough.

Now restart postfix and dovecot and it should work.

Activate SSL

Add the SLL certificate to the dovecot configuration on /etc/dovecot/dovecot.conf.

disable_plaintext_auth=yes
# ssl certificates
ssl_cert_file = /etc/ssl/certs/postfix.pem
ssl_key_file = /etc/ssl/private/postfix.key

Add SSL support and the SSL certificates to the postfix configuration on /etc/postfix/main.cf.

# TLS parameters
# our self-created certificate
smtpd_tls_cert_file=/etc/ssl/certs/postfix.pem
smtpd_tls_key_file=/etc/ssl/private/postfix.key
# accept certificates from other mail servers while their certificates are signed by a Certificate Authority
smtpd_tls_CAfile=/etc/ssl/certs/ca-certificates.crt
smtp_tls_CAfile=/etc/ssl/certs/ca-certificates.crt

# allow using tls to connect to our mail server
smtp_use_tls=yes
smtpd_use_tls=yes
# outcomment this to allow only tls connections
#smtpd_tls_auth_only=yes
# set log level
smtpd_tls_loglevel=1

smtpd_tls_received_header=yes
tls_random_source=dev:/dev/urandom
smtp_tls_note_starttls_offer=yes

smtpd_tls_session_cache_timeout=3600s
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

queue_directory=/var/spool/postfix
smtpd_sasl_type=dovecot
smtpd_sasl_path=private/auth
smtpdirtualMailBoxClamSmtpHowto">https://help.ubuntu.com/community/PostfixVirtualMailBoxClamSmtpHowto
  • http://www.postfix.org/postconf.5.html
  • http://wiki2.dovecot.org
  • http://workaround.org/ispmail/squeeze/postfix-domain-types
  • http://workaround.org/ispmail/squeeze/setting-up-dovecot
  • http://www.splitbrain.org/blog/2008-01/31-setup_postfix_and_dovecot_on_debian_etch
  • http://www.postfix.org/VIRTUAL_README.html
  • http://www.postfix.org/DEBUG_README.html
  • http://www.postfix.org/ADDRESS_CLASS_README.html
  • Die Kommentarfunktion ist geschlossen.