Configuring for System and Virtual Users
Hi! I am trying to configure postfix and dovecot 2.4.1 under Debian Trixie to handle both system and virtual users.
Some of my virtual users have the same username part as system users (e.g., system account 'mark' and virtual user 'mark@jumpforjoysoftware.com').
I've been struggling with getting help from Claude Code and Gemini Pro for several days now, and still can't get everything working.
From watching the logs, the problem appears to stem from the username part not being extracted from the FQ user before mail is handled off to lmtp for final delivery.
Here are what I believe are the relevant sections of my dovecot.conf:
overall default, need to handle system accounts as exceptions
auth_username_format = %{user | lower}
virtual users specified first so search will end when they are found
passdb passwd-file { passwd_file_path = /etc/dovecot/passwd }
userdb passwd-file { passwd_file_path = /etc/dovecot/passwd
userdb_fields { uid = 5000 gid = 5000 home = /var/mail/vhosts/%{user | domain | lower }/%{user | username | lower } mail_driver = maildir mail_path = ~/Maildir } }
system users
passdb pam {
apparently, this next line gets ignored
auth_username_format = %{user | username | lower}
service_name = dovecot }
userdb passwd {
or maybe this line does
auth_username_format = %{user | username | lower}
userdb_fields { home = /home/%{user} mail_driver = maildir mail_path = ~/Maildir } }
protocol lmtp { auth_username_format = %{user | username | lower} }
service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { mode = 0660 user = postfix group = postfix } }
not sure this is part of the problem, but...
service auth { unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } }
I believe the relevant sections of my postfix main.cf file are:
myhostname = mail.theboilingfrog.net mydomain = theboilingfrog.net myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
mailbox_transport = lmtp:unix:private/dovecot-lmtp virtual_transport = lmtp:unix:private/dovecot-lmtp
My system hostname is theboilingfrog.net.
This configuration fails to recognize mark@theboilingfrog.net...which is why I think the passdb pam block is ignoring the auth_username_format directive which should strip out the username portion.
Claude Code finally got around to suggesting I cut dovecot out of the loop for delivery of emails to system users. I guess I could do that, but I'd love to know if it's possible to keep dovecot engaged with delivering system user emails and have it work property.
Another thing is I could update all my email clients to use 'mark' rather than 'mark@theboilingfrog.net' to access their email. But, again, I'm curious if there's a way to configure things so I don't have to do that.
If it turns out what I'm trying to do is not supported, please let me know.
- Mark
There's a number of way you could solve this, but I think might be easier to do something like:-
virtual users
passdb passwd-file { passwd_file_path = /etc/dovecot/passwd username_filter = *@* auth_username_format = %{user | lower} # auth_verbose = yes
}
system users
passdb pam { service_name = dovecot username_filter = !*@* auth_username_format = %{user | username | lower } # Skip if an earlier passdb already authenticated the user successfully skip = authenticated # auth_verbose = yes }
userdb virtual_users { driver = passwd-file passwd_file_path = /etc/dovecot/passwd auth_username_format = %{user | lower}
fields { home = /var/mailboxes/%{user | domain | lower}/%{user | username | lower} } }
system users / fallback
userdb passwd { auth_username_format = %{user | username | lower}
fields {
home = /home/%{user}
# or maybe
# /home/%{user | username}
mail_driver = maildir
mail_path = ~/Maildir
}
skip = found }
Presumably PAM supplies the system user's actual home directory but maybe not the domain. Or is mail for system users stored in a different location to virtual?
PAM is typically used with either userdb passwd or userdb static.
Static settings generated from template
<https://doc.dovecot.org/latest/core/config/auth/databases/static.html> #userdb static { #driver = static
Can return anything a userdb could normally return. For example:
fields {
uid = 500
gid = 500
home = /var/mail/%{user}
}
LDA and LMTP needs to look up users only from the userdb. This of
course
doesn't work with static userdb because there is no list of users.
Normally static userdb handles this by doing a passdb lookup. This
works
with most passdbs, with PAM being the most notable exception. If you
do
the user verification another way, you can add allow_all_users=yes
in which case the passdb lookup is skipped.
#allow_all_users = yes #}
On 2026-10-01 18:56, Mark Olbert via dovecot wrote:
Hi! I am trying to configure postfix and dovecot 2.4.1 under Debian Trixie to handle both system and virtual users.
Some of my virtual users have the same username part as system users (e.g., system account 'mark' and virtual user 'mark@jumpforjoysoftware.com').
I've been struggling with getting help from Claude Code and Gemini Pro for several days now, and still can't get everything working.
From watching the logs, the problem appears to stem from the username part not being extracted from the FQ user before mail is handled off to lmtp for final delivery.
participants (2)
-
Mark Olbert
-
Rob Lister