Last active
March 5, 2026 21:50
-
-
Save bmatthewshea/93579a6c4af3ed3a6a4da5c3a04a48d3 to your computer and use it in GitHub Desktop.
Dovecot 2.4 - Working configuration for use with PostfixAdmin and SQL Virtual Users
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ### /etc/dovecot/local.conf - OVERRIDES TO DEFAULTS ONLY! ### | |
| ### By: Brady Shea - 05MAR2026 | |
| ### Original location: https://gist.github.com/bmatthewshea/93579a6c4af3ed3a6a4da5c3a04a48d3 | |
| # You may or may not need this: | |
| #dovecot_config_version = 2.4.2 | |
| protocols { | |
| lmtp = yes | |
| imap = yes | |
| pop3 = yes | |
| sieve= yes | |
| } | |
| ################ | |
| # 10-auth.conf # | |
| ################ | |
| auth_mechanisms = plain login | |
| # IMPORTANT: To use sql/mysql as the sole authentication method, | |
| # The following line is commented in 'conf.d/10-auth.conf': | |
| # -> #!include auth-system.conf.ext | |
| # ^ In 2.4 'ext' files are not suppose to be used, so I am not sure if this is needed anymore to stop local user pam lookups | |
| sql_driver = mysql | |
| # Some local-only varients - socket is used below: | |
| # -> mysql /var/run/mysqld/mysqld.sock { | |
| # -> mysql 127.0.0.1 { | |
| # -> mysql localhost { | |
| mysql /var/run/mysqld/mysqld.sock { | |
| user = (DATABASE USERNAME HERE) | |
| password = (PASSWORD HERE) | |
| dbname = (DATABASE NAME HERE) | |
| } | |
| # In 2.4 to allow md5 passwords, or other weaker schemes (See "passdb sql" below) | |
| # https://doc.dovecot.org/2.3/configuration_manual/authentication/password_schemes/ | |
| # Enable this if using a weaker scheme like MD5: | |
| # auth_allow_weak_schemes = yes | |
| # | |
| # The quota stored in postfixadmin database looks like it is stored in bytes (so the B designator is concatenated on end of quota #). | |
| # | |
| # "iterate_query" is used for the 'doveadm users' command. | |
| userdb sql { | |
| query = SELECT concat(quota, 'B') AS quota_storage_size \ | |
| FROM mailbox WHERE username = '%{user}' AND active = '1'; | |
| iterate_query = SELECT username \ | |
| FROM mailbox WHERE active = '1'; | |
| } | |
| passdb sql { | |
| default_password_scheme = sha512-crypt | |
| query = SELECT username as user, domain, password \ | |
| FROM mailbox WHERE username = '%{user}' AND active = '1'; | |
| } | |
| ################### | |
| # 10-logging.conf # | |
| ################### | |
| # Additional logging setup wil be needed in rsyslog and logrotate | |
| # I store logs in /var/log/dovecot/ | |
| log_path = syslog | |
| syslog_facility = local5 | |
| auth_verbose = yes | |
| # Debug | |
| #mail_debug = yes | |
| #auth_debug_passwords = yes | |
| #auth_debug = no | |
| #verbose_ssl = yes | |
| ################ | |
| # 10-mail.conf # | |
| ################ | |
| # The first two are definitely be needed. As for the last 3, it works so I left it in (they're from an older config) | |
| mail_uid = vmail | |
| mail_gid = mail | |
| first_valid_uid = 150 | |
| last_valid_uid = 150 | |
| mail_privileged_group = mail | |
| # READ THIS. | |
| # The 'mail_location' directive has been redefined: | |
| # ** In 2.4, the new home/mail location directives are extremely important to get right. ** | |
| # It also took me hours to figure out I need a mail_inbox_path (bug?) (see "mail_inbox_path" below). | |
| # If I didn't include inbox path, 2.4 kept wanting to store email in '/var/mail'. | |
| # NOTE: I made the mistake of setting the home and mail locations the same on a server in the past. | |
| # You will want to store emails/imapfolders in a separate directory ('~/mail' in example below). | |
| # (I use "~/mail" below but "~/Maildir" or anything could be used as far as I know.) | |
| # Once you set the home directory, you simply point everything there (~). | |
| # See: https://doc.dovecot.org/2.3/configuration_manual/home_directories_for_virtual_users/#home-directories-for-virtual-users | |
| # "Home directory shouldn’t be the same as mail directory with mbox or Maildir formats" (We are using Maildir format) | |
| mail_driver = maildir | |
| # "Home" stores dovecot data files/etc: | |
| mail_home = /var/vmail/%{user|domain}/%{user|username} | |
| # The mail path stores actual {new,cur,tmp}/inbox folders for incoming emails: | |
| mail_path = ~/mail | |
| # RE: mail_inbox_path | |
| # This seems to be a bug?: If I do not include this, | |
| # the 'mail_path' seems to override and defaults back to /var/mail/. | |
| # This may not be needed in your own config - test w/o first: | |
| mail_inbox_path = ~/mail | |
| ################## | |
| # 10-master.conf # | |
| ################## | |
| service auth { | |
| unix_listener auth-userdb { | |
| mode = 0660 | |
| user = vmail | |
| group = mail | |
| } | |
| unix_listener /var/spool/postfix/private/auth { | |
| mode = 0660 | |
| user = postfix | |
| group = postfix | |
| } | |
| user = dovecot | |
| } | |
| service lmtp { | |
| unix_listener /var/spool/postfix/private/dovecot-lmtp { | |
| mode = 0660 | |
| user = postfix | |
| group = postfix | |
| } | |
| } | |
| service auth-worker { | |
| user = vmail | |
| } | |
| service managesieve-login { | |
| inet_listener sieve { | |
| port = 4190 | |
| } | |
| } | |
| service stats { | |
| unix_listener stats-reader { | |
| user = vmail | |
| group = mail | |
| mode = 0660 | |
| } | |
| unix_listener stats-writer { | |
| user = vmail | |
| group = mail | |
| mode = 0660 | |
| } | |
| } | |
| ############### | |
| # 10-ssl.conf # | |
| ############### | |
| ssl = yes | |
| # core email domain | |
| ssl_server_cert_file = /etc/letsencrypt/live/example.com/fullchain.pem | |
| ssl_server_key_file = /etc/letsencrypt/live/example.com/privkey.pem | |
| ssl_server_dh_file = /etc/dovecot/dhparam.pem | |
| ssl_min_protocol = TLSv1.2 | |
| # OPTIONAL: multi domain / site specific - if not found dovecot defaults to ^core certficate | |
| # Additional domains will utilize SNI and may not work on all clients - though, this advice is getting outdated quickly. | |
| # | |
| #local_name smtp.example.org { | |
| # ssl_server_cert_file = /etc/letsencrypt/live/example.org/fullchain.pem | |
| # ssl_server_key_file = /etc/letsencrypt/live/example.org/privkey.pem | |
| #} | |
| #local_name mail.example.com { | |
| # ssl_server_cert_file = /etc/letsencrypt/live/example.net/fullchain.pem | |
| # ssl_server_key_file = /etc/letsencrypt/live/example.net/privkey.pem | |
| #} | |
| # add more as needed.. | |
| ############################### | |
| # 15-lda.conf / 20-lmtp.conf # | |
| ############################### | |
| postmaster_address = postmaster@example.net | |
| recipient_delimiter = + | |
| # add sieve | |
| protocol lmtp { | |
| auth_username_format = %{user} | |
| mail_plugins { | |
| sieve = yes | |
| notify = yes | |
| push_notification = yes | |
| } | |
| } | |
| ##################### | |
| # 15-mailboxes.conf # | |
| ##################### | |
| namespace inbox { | |
| inbox = yes | |
| separator = / | |
| # | |
| #mailbox name { | |
| # auto = create -> will automatically create this mailbox. | |
| # auto = subscribe -> will both create and subscribe to the mailbox. | |
| # auto = no -> defines it - nothing else | |
| # RFC 6154: \All \Archive \Drafts \Flagged \Junk \Sent \Trash : | |
| # special_use = What is its function? | |
| #} | |
| mailbox Drafts { | |
| auto = subscribe | |
| special_use = \Drafts | |
| } | |
| # In 2.4, sieve junk learning is now called in this section. | |
| # I assume we could also add a "Spam" mailbox and put the same script in it. | |
| # In this fashion, you should be able to detail more than one junk mailbox to learn spam. | |
| # I have not tried this yet, though. | |
| mailbox "Junk E-mail" { # Outlook | |
| auto = subscribe | |
| special_use = \Junk | |
| sieve_script LearnSpam { | |
| cause = COPY | |
| driver = file | |
| path = /var/vmail/sieve/global/learn-spam.sieve | |
| type = before | |
| } | |
| } | |
| mailbox Archives { | |
| auto = subscribe | |
| special_use = \Archive | |
| } | |
| mailbox "Deleted Items" { #Outlook | |
| auto = subscribe | |
| special_use = \Trash | |
| } | |
| mailbox "Templates" { #Thunderbird | |
| } | |
| mailbox "Notes" { | |
| } | |
| mailbox "Public" { | |
| type = public | |
| } | |
| # Generally outlook/thunderbird: | |
| mailbox "Sent Items" { | |
| auto = subscribe | |
| special_use = \Sent | |
| } | |
| # sieve 'learn HAM' is now in inbox namespace: | |
| imapsieve_from Spam { | |
| sieve_script LearnHam { | |
| cause = COPY | |
| driver = file | |
| path = /var/vmail/sieve/global/learn-ham.sieve | |
| type = before | |
| } | |
| } | |
| } # Ends inbox namespace | |
| ########################## | |
| # 20-imap.conf overrides # | |
| ########################## | |
| protocol imap { | |
| mail_plugins { | |
| quota = yes | |
| imap_quota = yes | |
| imap_sieve = yes | |
| } | |
| mail_max_userip_connections = 50 | |
| } | |
| ############### | |
| #20-pop3.conf # | |
| ############### | |
| # no overrides | |
| ################# | |
| # 90-sieve.conf # | |
| ################# | |
| sieve_plugins { | |
| sieve_imapsieve = yes | |
| sieve_extprograms = yes | |
| } | |
| sieve_script spam-global { | |
| type = before | |
| driver = file | |
| path = /var/vmail/sieve/global/spam-global.sieve | |
| } | |
| sieve_script personal { | |
| type = personal | |
| driver = file | |
| path = /var/vmail/sieve/%{user|domain}/%{user|username}/scripts | |
| active_path = /var/vmail/sieve/%{user|domain}/%{user|username}/active-script.sieve | |
| } | |
| sieve_pipe_bin_dir = /usr/bin | |
| sieve_extensions { | |
| vnd.dovecot.pipe = yes | |
| } | |
| ### QUOTA ### | |
| quota_exceeded_message = User %{user} has exceeded allowed storage space. | |
| quota "User quota" { | |
| driver = count | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment