Virtual User Accounts

[OpenBSD 4.7 Stable, postfix-2.7.1]

We like Unix mail servers and we don't like having user accounts on our hosts just to let people get mail. Virtual e-mail accounts is a reasonable solution for this dilemma and Postfix is flexible and straight forward to install for providing virtual e-mail accounts.

We install and test a Virtual Users Accounts stored in

  • text files
  • an MySQL database

Basic Configuration information that will be used throughout the guide are:

Item Description
Host myhost.example.org
Mail Base Directory /var/spool/postfix/vmail
An arbitrary location within Postfix's chroot folder structure.
Domain alpha.example.org
The host for the mail server can be on a different domain (eg. fred.example.net). All that's needed to service a domain is the DNS MX record for the domain (alpha.example.org) points to this Postfix host.
Users alfred, bob, charlie

[Ref: Postfix Virtual Domain Hosting Howto - VIRTUAL_README.html]

We install the text file based Virtual User Accounts, because there are fewer variables/items to review to ensure your server is up and running. The text file service is also quite legitimate a solution when you have a manageable number of users and do not need the complexity of a database for managing user accounts.

Main Configuration

We'll put in some basic configuration information for virtual hosting into Postfix's main.cf

File Fragment: /etc/postfix/main.cf

Virtual Mailbox Services - Local

virtual_mailbox_base = /var/spool/postfix/vmail
virtual_mailbox_domains = hash:/etc/postfix/virtual/domains
virtual_mailbox_maps = hash:/etc/postfix/virtual/accounts
virtual_minimum_uid = 900
virtual_transport = virtual
virtual_uid_maps = static:901
virtual_gid_maps = static:901
parent_domain_match_subdomains =

Notes:

  • parentdomainmatchsubdomains set to blank, which is optional if you have relaydomains set to blank.
  • The virtualminimumuid has to be less than or equal to virtual_uid_maps and virtual_gid_maps, otherwise you will get an error during mail receipt processing.
  • 901 is arbitrary, although it must be maintained through a few other places in these instructions and in the dovecot instructions. I don't know whether this '901' clashes with any other OpenBSD port, but I specifically chose it to be below the standard starting ID used for normal user accounts which tend to start from 1,000.
Disk Layout

We need to layout our files mentioned in the configuration file above and I have chosen the following which is hopefully scaleable if you want to use this as the basis (ignoring the simpler database solution reviewed later.)

  • Path: **/etc/postfix/virtual** - the base directory to store virtual related configurations
  • Path: ./alias - for virtual alias files
    • File: common
  • Path: ./mailbox - for virtual mailbox configuration files
    • File: domains
    • File: accounts

Screen Session

mv /etc/postfix/virtual /etc/postfix/virtual_aliases
mkdir -p /etc/postfix/virtual
mv /etc/postfix/virtual_aliases /etc/postfix/virtual/aliases
touch /etc/postfix/virtual/domains
touch /etc/postfix/virtual/accounts

We move the current virtual alias file from /etc/postfix/virtual to /etc/postfix/virtual/aliases.

Virtual Domains

We specify for postfix which virtual domains we want it to receive email with the following configuration option:

File Fragment: /etc/postfix/main.cf

virtual_mailbox_domains = hash:/etc/postfix/virtual/domains

File:/etc/postfix/virtual/mailbox/domains

alpha.example.org      IGNORED_PARAMETER

After creating or making any changes to the above domains file, recreate the hash database using postmap

# /usr/local/sbin/postmap /etc/postfix/virtual/domains

Virtual Mailbox

For OpenBSD, the default chroot'd postfix installation stores its files in /var/spool/postfix so we'll specify the location for virtual email accounts within that structure.

File Fragment: /etc/postfix/main.cf

virtual_mailbox_base = /var/spool/postfix/vmail

When setting up virtual mailboxes (in this manner), it makes sense to structure the directories for scalability and to prevent clashing namespaces. Prior to setting up accounts we'll consider that our mailbox accounts will be structured by domain.

For example:

  • /var/spool/postfix/vmail/alpha.example.org/accountX
  • /var/spool/postfix/vmail/alpha.example.org/accountY
  • /var/spool/postfix/vmail/alpha.example.org/accountZ

We can now create some sample user accounts into our virtual mailbox

File Fragment: /etc/postfix/main.cf

virtual_mailbox_maps = hash:/etc/postfix/virtual/accounts 

Obviously, each valid user needs a corresponding mailbox storage space. The mailbox file is specified relative to the virtual_mailbox_base shown above and since we already have our directory design structure above, we can go ahead and create some accounts.

Virtual Accounts - alpha.example.org

File: /etc/postfix/virtual/accounts

#account                    --> Storage location
alfred@alpha.example.org    alpha.example.org/alfred/
bob@alpha.example.org       alpha.example.org/bob/
charlie@alpha.example.org   alpha.example.org/charlie/

After creating or making any changes to the above accounts file, recreate the hash database using postmap

# /usr/local/sbin/postmap /etc/postfix/virtual/accounts

NOT WORKING YET.

Virtual Aliases (broken)

NOT WORKING YET.

2. Create the system user account for managing virtual mail

[Ref: virtual_uid_maps, virtual_gid_maps]

Mail delivery happens with the recipient's UID/GID privileges specified with virtualuidmaps and virtualgidmaps, therefore the virtual mailbox files must be owned by a system user account and associated with a group on your system.

Fortunately Postfix is flexible to allow each mailbox to be owned by a unique system user account or by a single system user account for all domains, and even one system user account per domain. This is set by using the virtualuidmaps and virtualgidmaps setting.

virtual_uid_maps = static:901
virtual_gid_maps = static:901

The 'static' map type tells Postfix that you want the uid/gid to be for all accounts.

We can now create the system user account "_vmail" to manage virtual email mailboxes. Review OpenBSD Porting Guide - Update Checklist for appropriate selection of port related user-accounts /usr/ports/infrastructure/db/user.list

Screen Session

useradd -d /var/spool/postfix/vmail -g=uid -u 901 \
    -s /sbin/nologin -m -c 'Virtual Mailbox Owner' _vmail
chmod -R 770 /var/spool/postfix/vmail

A by-product of the user/group creation is that the 'base' directory will also be created with the correct permissions.

If we wanted to use different users, groups for managing mailboxes, then we could have used a lookup file instead.

virtual_uid_maps = hash:/etc/postfix/virtual/uids
virtual_gid_maps = hash:/etc/postfix/virtual/gids

Ensure the standard (non-virtual) alias file is built by using Postfix's newaliases.

/usr/local/sbin/newaliases

Restart Postfix

/usr/local/sbin/postfix stop
/usr/local/sbin/postfix start

3. Testing Configuration

postconf

Use postconf -n to compare whether what we expect in virtual_* parameter settings is what is running on the system.

Screen Session

/usr/local/sbin/postconf | grep ^virtual
virtual_alias_domains = $virtual_alias_maps
virtual_alias_expansion_limit = 1000
virtual_alias_maps = $virtual_maps
virtual_alias_recursion_limit = 1000
virtual_destination_concurrency_limit = $default_destination_concurrency_limit
virtual_destination_recipient_limit = $default_destination_recipient_limit
virtual_gid_maps = static:901
virtual_mailbox_base = /var/spool/postfix/vmail
virtual_mailbox_domains = hash:/etc/postfix/virtual/domains
virtual_mailbox_limit = 51200000
virtual_mailbox_lock = fcntl
virtual_mailbox_maps = hash:/etc/postfix/virtual/accounts
virtual_minimum_uid = 900
virtual_transport = virtual
virtual_uid_maps = static:901

telnet localhost smtp

Remember to review the log files (/var/log/maillog) and validate postfix has started without errors. You can also repeat the above 'telnet localhost smtp' to review nothing has drastically broken.

Screen Session

$ telnet localhost smtp
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 myhost.example.org ESMTP Postfix (2.3.2)
ehlo example.org
250-myhost.example.org
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
mail from: <samt@example.org>
250 2.1.0 Ok
rcpt to: <alfred@alpha.example.org>
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
Subject: Welcome Virtual Users

Hopefully you are all virtually OK.

Welcome to email

.
250 2.0.0 Ok: queued as BA1FC5A950
quit
221 2.0.0 Bye
Connection closed by foreign host.

Mail Log

The corresponding /var/log/maillog entry should look something like the following

File: /var/log/maillog

connect from unknown[::1]
client=unknown[::1]
message-id=<20070208214647.BA1FC5A950@myhost.example.org>
from=<samt@example.org>, size=393, nrcpt=3 (queue active)
to=<alfred@alpha.example.org>, relay=virtual, delay=69, 
delays=67/0.05/0/1.8, dsn=2.0.0, status=sent (delivered to maildir) 
removed
disconnect from unknown[::1]

Mail Store

We should also be able to see evidence of the virtual account mails in the file system such as has occurred on this installation.

Screen Session

# ls -l /var/spool/postfix/vmail/alpha.example.org/alfred/new/
total 4
-rw------- 1 _vmail _vmail 481 Feb 9 10:47 
1170971257.V5I5a95aM294234.myhost.example.org
cat /var/spool/postfix/vmail/alpha.example.org/alfred/new/1170971257.V5I5a95aM294234.myhost.example.org
Return-Path: <samt@example.org>
X-Original-To: alfred@alpha.example.org
Delivered-To: alfred@alpha.example.org
Received: from example.org (unknown [IPv6:::1])
by myhost.example.org (Postfix) with ESMTP id BA1FC5A950;
Fri, 9 Feb 2007 10:46:30 +1300 (TOT)
Subject: Welcome Virtual Users
Message-Id: <20070208214647.BA1FC5A950@myhost.example.org>
Date: Fri, 9 Feb 2007 10:46:30 +1300 (TOT)
From: samt@example.org
To: undisclosed-recipients:; 

Hopefully you are all virtually OK. 

Welcome to email 

Reference Resources

There is a plethora of documentation out there using Postfix with Virtual Accounts, likewise there is also quite a few with OpenBSD as the server operating system.

Postfix Documentation