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.