E. Dovecot configuration Dovecot configuration is considerably simpler. Everything is put under /etc/dovecot/ from the sample configuration directory. In the top level, dovecot.conf is very simple. It only contains two directives: first, to include all the *.conf files under conf.d/. Second, to include a "/etc/dovecot/local.conf" if it exists (and not complain if it does not exist.) The other two files in /etc/dovecot/ are sql-deny.conf.ext and sql.conf.ext, each referenced from the actual configuration. These are the files that tell Dovecot how to connect to and query the SQLite database. They are covered in detail at the appropriate point in the configuration (when references are made thereto.) List of modular configuration files under /etc/dovecot/conf.d: FILENAME Notes Purpose ======== ===== ======= 10-auth.conf Authentication 10-logging.conf No-op Log settings 10-mail.conf Mailbox and processes 10-master.conf Services 10-ssl.conf SSL/TLS 15-lda.conf No-op LDA (unused) 20-imap.conf IMAP 20-lmtp.conf No-op LMTP 20-pop3.conf POP3 90-acl.conf No-op Access control 90-plugin.conf No-op Plugins auth-deny.conf.ext Deny login query auth-master.conf.ext NOT included Master users auth-sql.conf.ext Virtual user auth auth-system.conf.ext System user auth That is an ASCII sort, which is the order in which they are included. The numeric prefixes were added by Dovecot to keep them in the proper order. (These are mostly Dovecot's file names, not mine.) The auth*.ext files at the end are included (or not, as the case may be) from 10-auth.conf, and are shown here when appropriate (in the order given, after 10-auth.conf.) Most of what follows are the actual files, with some text added where necessary, either before or after the file content. 1. 10-auth.conf Note: this file has been configured to provide SASL AUTH for Postfix, although as mentioned elsewhere, this document will not try to cover that. (It is a relatively simple feature to activate.) ## ## Authentication processes ## # Disable LOGIN command and all other plaintext authentications unless # SSL/TLS is used (LOGINDISABLED capability). Note that if the remote IP # matches the local IP (ie. you're connecting from the same computer), # the connection is considered secure and plaintext authentication is # allowed. #disable_plaintext_auth = yes ### disable_plaintext_auth is generally something I enable, but since ### this example does not go into detail on TLS configuration, I am ### leaving it commented, with a recommendation for the reader to see ### the Dovecot wiki pages regarding TLS. # Space separated list of wanted authentication mechanisms: # plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp # skey gss-spnego # NOTE: See also disable_plaintext_auth setting. auth_mechanisms = plain ## ## Password and user databases ## # Password database is used to verify user's password (and nothing # more). You can have multiple passdbs and userdbs. This is useful if # you want to allow both system users (/etc/passwd) and virtual users # to login without duplicating the system users into virtual database. # # # # User database specifies where mails are located and what user/group # IDs own them. # # ### These can be included if desired. ### This is a list of disabled credentials. The account otherwise is ### normal; the address can receive mail. But login is not allowed. A ### typical use case is when an account has been exploited (Windows ### malware, for example) and is being used to send spam. This is an ### important feature to implement, so I did. !include auth-deny.conf.ext ### This is a list of "master" credentials which can get into any ### mailbox. Since root can do that at the console without IMAP, I do ### not see the need to implement this. Nevertheless I have left the ### file and this comment for those who might be interested. #!include auth-master.conf.ext ### We are indeed using system and SQLite virtual users, so both of ### these are needed: !include auth-system.conf.ext !include auth-sql.conf.ext ### Other auth-* files removed, such as for LDAP or other data backends. ### See your Dovecot sample configuration directory if interested. 2. auth-deny.conf.ext # Deny access for users. Included from auth.conf. # Users can be (temporarily) disabled by adding a passdb with deny=yes. # If the user is found from that database, authentication will fail. # The deny passdb should always be specified before others, so it gets # checked first. # Example deny passdb using passwd-file. You can use any passdb though. #passdb { #driver = passwd-file #deny = yes # File contains a list of usernames, one per line #args = /etc/dovecot/deny-users #} ### Here is how we can implement this in SQL passdb { driver = sql deny = yes args = /etc/dovecot/sql-deny.conf.ext } a. /etc/dovecot/sql-deny.conf.ext Note: the parameters set herein will be explained in detail below, in the /etc/dovecot/sql.conf.ext file. driver = sqlite connect = /etc/dovecot/private/mail.sqlite ### deny password_query # The "deny=yes" passdb needs to handle either a "user@domain" or a # plain "user" credential. In the former case, we look up the domain; # latter case we assume (and have hardcoded the value of) the Postfix # myhostname setting. password_query = SELECT '%u' FROM Address AS A1 \ JOIN Domain AS D1 ON (A1.addDomNum=D1.domNum) \ WHERE A1.addLocalpart IS '%n' \ AND (CASE WHEN '%u' GLOB '*@*' THEN \ D1.domName IS '%d' ELSE \ D1.domName IS 'myhostname.example.org' END) \ AND A1.active=-1 # end of sql-deny.conf.ext Here is where we are using the third state of the Address.active column. When it is not zero, Postfix will still accept mail for the address. But when it is -1, Dovecot will deny login. 3. auth-master.conf.ext This file is NOT included; the include line was left commented for reasons as discussed above under 10-auth.conf. Also, this has not been edited to do the passdb lookup from SQLite. It could be done much like the auth-deny.conf.ext with a fourth state such as Address.active=2. I don't think that would break anything; the checks for that column are looking for Address.active!=0. But hey, we are already root and have lots of other options at our disposal, such as just searching in a maildir with grep(1) and reading mail with less(1). So it will remain unimplemented, with these suggestions given to those who [think they] want master users. # Authentication for master users. Included from auth.conf. # By adding master=yes setting inside a passdb you make the passdb a # list of "master users", who can log in as anyone else. # # Example master user passdb using passwd-file. You can use any passdb # though. passdb { driver = passwd-file master = yes args = /etc/dovecot/master-users # Unless you're using PAM, you probably still want the destination # user to be looked up from passdb that it really exists. pass=yes # does that. pass = yes } 4. auth-system.conf.ext This too is a non-SQLite file, because it controls how system users authenticate, as opposed to the SQLite-based virtual users. PAM and shadow are the two most common choices. I use shadow, but left the PAM part in because it is probably more widely used. # Authentication for system users. Included from auth.conf. # # # # PAM authentication. Preferred nowadays by most systems. # PAM is typically used with either userdb passwd or userdb static. # REMEMBER: You'll need /etc/pam.d/dovecot file created for PAM # authentication to actually work. #passdb { #driver = pam # [session=yes] [setcred=yes] [failure_show_msg=yes] [max_requests=] # [cache_key=] [] #args = dovecot #} # System users (NSS, /etc/passwd, or similiar). # In many systems nowadays this uses Name Service Switch, which is # configured in /etc/nsswitch.conf. passdb { driver = passwd # [blocking=no] #args = } ### Deprecated or not, I set this up on a non-PAM system. If you're ### using PAM, there it is above. Here's mine: # Shadow passwords for system users (NSS, /etc/shadow or similiar). # Deprecated by PAM nowadays. # passdb { driver = shadow # [blocking=no] #args = } ## ## User databases ## # System users (NSS, /etc/passwd, or similiar). In many systems # nowadays this uses Name Service Switch, which is configured in # /etc/nsswitch.conf. userdb { # driver = passwd # [blocking=no] #args = # Override fields from passwd #override_fields = home=/home/virtual/%u } 5. auth-sql.conf.ext Here is the heart of the SQLite configuration. This file defines the passdb and userdb lookups, and points to the file in the parent directory where the actual queries are defined. # Authentication for SQL users. Included from auth.conf. # # passdb { driver = sql # Path for SQL configuration file, see # example-config/dovecot-sql.conf.ext args = /etc/dovecot/sql.conf.ext } # "prefetch" user database means that the passdb already provided the # needed information and there's no need to do a separate userdb lookup. # userdb { driver = prefetch } userdb { driver = sql args = /etc/dovecot/sql.conf.ext } a. /etc/dovecot/sql.conf.ext ### Default comments [mostly] removed from here, except this (and a few ### others: # This file is opened as root, so it should be owned by root and mode # 0600. ### For SQLite, there is nothing secure in this file, so 644 works. # Database driver: mysql, pgsql, sqlite driver = sqlite # Database connection string. This is driver-specific setting. # # sqlite: # The path to the database file. # connect = /etc/dovecot/private/mail.sqlite # Default password scheme. # # List of supported schemes is in # http://wiki2.dovecot.org/Authentication/PasswordSchemes # default_pass_scheme = MD5 # Commonly used available substitutions (see # http://wiki2.dovecot.org/Variables for full list): # %u = entire user@domain # %n = user part of user@domain # %d = domain part of user@domain ### passdb and userdb lookups # # For both queries: the VMailbox table contains vmNum, a numeric # pointer to addNum in the Address table. Address has a text string, # addLocalpart, and addDomNum, a numeric pointer to domNum in the Domain # table. Domain contains the text string, domName. So Address is # joined on vmNum=addNum, and Domain is joined on addDomNum=domNum. ### password_query (passdb) # # We use %u (as provided by the client) as user, and look up each # component (%n and %d) in the appropriate tables. Where found, we # return vmPasswd as password. ### This was a working separate query before prefetch #password_query = SELECT '%u' AS user, V1.vmPasswd AS password \ # FROM VMailbox AS V1 \ # JOIN Address AS A1 ON (V1.vmNum=A1.addNum) \ # JOIN Domain AS D1 ON (A1.addDomNum=D1.domNum) \ # WHERE A1.addLocalpart IS '%n' \ # AND D1.domName IS '%d' \ # AND V1.active!=0 # WHERE A1.addLocalpart || '@' || D1.domName IS '%u' \ ### This has merged the userdb query for the prefetch userdb; it means ### one less SQL query is required. The passdb parts are described in ### the comments above; the userdb parts are described with user_query ### below. The only difference is that we preface the uid, gid and home ### field names with "userdb_" in this query. password_query = SELECT '%u' AS user, V1.vmPasswd AS password, \ coalesce(V1.vmUid, D1.domClass) AS userdb_uid, \ coalesce(V1.vmGid, 800) AS userdb_gid, \ '/home/' || coalesce(V1.vmHome, 'vmail/%d/%n') AS userdb_home \ FROM VMailbox AS V1 \ JOIN Address AS A1 ON (V1.vmNum=A1.addNum) \ JOIN Domain AS D1 ON (A1.addDomNum=D1.domNum) \ WHERE A1.addLocalpart IS '%n' \ AND D1.domName IS '%d' \ AND V1.active!=0 ### user_query (userdb) # # We take the first non-null value of vmUid (which can be NULL) and # domClass (which must not be NULL) as uid; then the first non-null of # vmGid (which can be NULL) or 800 as gid. Then home is constructed of # "/home/" and the first non-null value of vmHome (which can be NULL) # and "vmail//". The WHERE clause is the same as in # password_query. ### Even with the prefetch userdb, a user_query is still needed. user_query = SELECT coalesce(V1.vmUid, D1.domClass) AS uid, \ coalesce(V1.vmGid, 800) AS gid, \ '/home/' || coalesce(V1.vmHome, 'vmail/%d/%n') AS home \ FROM VMailbox AS V1 \ JOIN Address AS A1 ON (v1.vmNum=A1.addNum) \ JOIN Domain AS D1 ON (A1.addDomNum=D1.domNum) \ WHERE A1.addLocalpart IS '%n' \ AND D1.domName IS '%d' \ AND V1.active!=0 # Query to get a list of all usernames. #iterate_query = (not implemented, not needed) 6. 10-logging.conf ### Nothing is changed in this file, but considering the importance of ### logging, I left it here. If you have problems, you might need to ### change and uncomment things here. In particular you might want to ### consider "auth_verbose = yes". ## ## Log destination. ## # Log file to use for error messages. "syslog" logs to syslog, # /dev/stderr logs to stderr. #log_path = syslog # Log file to use for informational messages. Defaults to log_path. #info_log_path = # Log file to use for debug messages. Defaults to info_log_path. #debug_log_path = # Syslog facility to use if you're logging to syslog. Usually if you # don't want to use "mail", you'll use local0..local7. Also other # standard facilities are supported. #syslog_facility = mail ## ## Logging verbosity and debugging. ## # Log unsuccessful authentication attempts and the reasons why they # failed. #auth_verbose = no # In case of password mismatches, log the attempted password. Valid # values are no, plain and sha1. sha1 can be useful for detecting brute # force password attempts vs. user simply trying the same password over # and over again. #auth_verbose_passwords = no # Even more verbose logging for debugging purposes. Shows for example # SQL queries. #auth_debug = no # In case of password mismatches, log the passwords and used scheme so # the problem can be debugged. Enabling this also enables auth_debug. #auth_debug_passwords = no # Enable mail process debugging. This can help you figure out why # Dovecot isn't finding your mails. #mail_debug = no # Show protocol level SSL errors. #verbose_ssl = no # mail_log plugin provides more event logging for mail processes. plugin { # Events to log. Also available: flag_change append #mail_log_events = delete undelete expunge copy mailbox_delete # mailbox_rename # Available fields: uid, box, msgid, from, subject, size, vsize, flags # size and vsize are available only for expunge and copy events. #mail_log_fields = uid box msgid size } ## ## Log formatting. ## # Prefix for each line written to log file. % codes are in strftime(3) # format. #log_timestamp = "%b %d %H:%M:%S " # Space-separated list of elements we want to log. The elements which # have a non-empty variable value are joined together to form a comma- # separated string. #login_log_format_elements = user=<%u> method=%m rip=%r lip=%l # mpid=%e %c # Login log format. %$ contains login_log_format_elements string, %s # contains the data we want to log. #login_log_format = %$: %s # Log prefix for mail processes. See doc/wiki/Variables.txt for list of # possible variables you can use. #mail_log_prefix = "%s(%u): " # Format to use for logging mail deliveries. You can use variables: # %$ - Delivery status message (e.g. "saved to INBOX") # %m - Message-ID # %s - Subject # %f - From address # %p - Physical size # %w - Virtual size #deliver_log_format = msgid=%m: %$ 7. 10-mail.conf ### This was a very big file; I took most of it out. Refer to your ### sample 10-mail.conf file for some of the things you can do. ## ## Mailbox locations and namespaces ## # Location for users' mailboxes. The default is empty, which means that # Dovecot tries to find the mailboxes automatically. This won't work if # the user doesn't yet have any mail, so you should explicitly tell # Dovecot the full location. # # # mail_location = maildir:~/Mail ## ## Mail processes ## ### I set this to my lowest virtual UID and 65535. # Valid UID range for users, defaults to 500 and above. This is mostly # to make sure that users can't log in as daemons or other system users. # Note that denying root logins is hardcoded to dovecot binary and can't # be done even if first_valid_uid is set to 0. first_valid_uid = 801 last_valid_uid = 65535 ### I set this to 100(users) which is the primary GID for system users. ### There is no need for system accounts to use IMAP. # Valid GID range for users, defaults to non-root/wheel. Users having # non-valid GID as primary group ID aren't allowed to log in. If user # belongs to supplementary groups with non-valid GIDs, those groups are # not set. first_valid_gid = 100 last_valid_gid = 65535 8. 10-master.conf #default_process_limit = 100 #default_client_limit = 1000 # Default VSZ (virtual memory size) limit for service processes. This is # mainly intended to catch and kill processes that leak memory before # they eat up everything. #default_vsz_limit = 256M # Login user is internally used by login processes. This is the most # untrusted user in Dovecot system. It shouldn't have access to # anything at all. #default_login_user = dovenull # Internal user is used by unprivileged processes. It should be # separate from login user, so that login processes can't disturb # other processes. #default_internal_user = dovecot service imap-login { inet_listener imap { #port = 143 } inet_listener imaps { #port = 993 #ssl = yes } # Number of connections to handle before starting a new process. # Typically the only useful values are 0 (unlimited) or 1. 1 is more # secure, but 0 is faster. #service_count = 1 # Number of processes to always keep waiting for more connections. #process_min_avail = 0 # If you set service_count=0, you probably need to grow this. #vsz_limit = 64M } service pop3-login { inet_listener pop3 { #port = 110 } inet_listener pop3s { #port = 995 #ssl = yes } } ### Eventually I will implement this, not yet. #service lmtp { # unix_listener lmtp { # #mode = 0666 # } # Create inet listener only if you can't use the above UNIX socket #inet_listener lmtp { # Avoid making LMTP visible for the entire internet #address = #port = #} #} service imap { # Most of the memory goes to mmap()ing files. You may need to increase # this limit if you have huge mailboxes. #vsz_limit = 256M # Max. number of IMAP processes (connections) #process_limit = 1024 } service pop3 { # Max. number of POP3 processes (connections) #process_limit = 1024 } service auth { # auth_socket_path points to this userdb socket by default. It's # typically used by dovecot-lda, doveadm, possibly imap process, etc. # Users that have full permissions to this socket are able to get a # list of all usernames and get the results of everyone's userdb # lookups. # # The default 0666 mode allows anyone to connect to the socket, but # the userdb lookups will succeed only if the userdb returns an "uid" # field that matches the caller process's UID. Also if caller's uid or # gid matches the socket's uid or gid the lookup succeeds. Anything # else causes a failure. # # To give the caller full permissions to lookup all users, set the # mode to something else than 0666 and Dovecot lets the kernel enforce # the permissions (e.g. 0777 allows everyone full permissions). unix_listener auth-userdb { #mode = 0666 #user = #group = } # Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } # Auth process is run as this user. user = root ### Because of /etc/shadow we cannot use $default_internal_user } service auth-worker { # Auth worker process is run as root by default, so that it can access # /etc/shadow. If this isn't necessary, the user should be changed to # $default_internal_user. #user = root } service dict { # If dict proxy is used, mail processes should have access to its # socket. For example: mode=0660, group=vmail and global # mail_access_groups=vmail unix_listener dict { #mode = 0600 #user = #group = } } 9. 10-ssl.conf ## ## SSL settings ## # SSL/TLS support: yes, no, required. ssl = yes # PEM encoded X.509 SSL/TLS certificate and private key. They're # opened before dropping root privileges, so keep the key file # unreadable by anyone but root. ssl_cert = . #postmaster_address = # Hostname to use in various parts of sent mails, eg. in Message-Id. # Default is the system's real hostname. #hostname = # If user is over quota, return with temporary failure instead of # bouncing the mail. #quota_full_tempfail = no # Binary to use for sending mails. #sendmail_path = /usr/sbin/sendmail # If non-empty, send mails via this SMTP host[:port] instead of sendmail. #submission_host = # Subject: header to use for rejection mails. You can use the same variables # as for rejection_reason below. #rejection_subject = Rejected: %s # Human readable error message for rejection mails. You can use variables: # %n = CRLF, %r = reason, %s = original subject, %t = recipient #rejection_reason = Your message to <%t> was automatically rejected:%n%r # Delimiter character between local-part and detail in email address. ### default is + recipient_delimiter = - ### If you change this it must be changed in /etc/postfix/main.cf and ### /etc/postfix/query/maps-valias.query as well! # Header where the original recipient address (SMTP's RCPT TO: address) is taken # from if not available elsewhere. With dovecot-lda -a parameter overrides this. # A commonly used header for this is X-Original-To. #lda_original_recipient_header = # Should saving a mail to a nonexistent mailbox automatically create it? #lda_mailbox_autocreate = no # Should automatically created mailboxes be also automatically subscribed? #lda_mailbox_autosubscribe = no protocol lda { # Space separated list of plugins to load (default is global mail_plugins). #mail_plugins = $mail_plugins } 11. 20-imap.conf This file was not edited from the sample except to shorten it. Again, refer to your own sample configuration directory if interested. ## ## IMAP specific settings ## protocol imap { # Workarounds for various client bugs: # delay-newmail: # Send EXISTS/RECENT new mail notifications only when replying to # NOOP and CHECK commands. Some clients ignore them otherwise, for # example OSX Mail ( for list of plugins and # their configuration. Note that %variable expansion is done for all values. plugin { #setting_name = value }