diff options
Diffstat (limited to 'doc/wiki/Quota.Configuration.txt')
-rw-r--r-- | doc/wiki/Quota.Configuration.txt | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/doc/wiki/Quota.Configuration.txt b/doc/wiki/Quota.Configuration.txt new file mode 100644 index 0000000..75e78b2 --- /dev/null +++ b/doc/wiki/Quota.Configuration.txt @@ -0,0 +1,513 @@ +Quota Configuration +=================== + +Contents + + + 1. Quota Configuration + + 1. Quota rules + + 1. Limit configuration + + 2. Per-user quota + + 1. LDAP + + 2. MySQL + + 3. PostgreSQL, SQLite + + 4. passwd-file + + 5. passwd + + 3. Quota for public namespaces + + 4. Quota for private namespaces + + 5. Custom Quota Exceeded Message + + 6. Quota warnings + + 7. Overquota-flag (v2.2.16+) + + 8. Quota grace + + 9. Maximum saved mail size + + 10. Quota admin commands + +The configuration is split into multiple settings: + +First you have the quota root backend configuration. Quota root is a concept +from IMAP Quota specifications [http://www.rfc-editor.org/rfc/rfc2087.txt]. +Normally you'll have only one quota root, but in theory there could be e.g. +"user quota" and "domain quota" roots. It's unspecified how the quota roots +interact with each others (if at all). In some systems for example INBOX could +have a completely different quota root from the rest of the mailboxes (e.g. +INBOX in '/var/mail/' partition and others in '/home/' partition). + +Quota root configuration includes the backend name, quota root name and its +parameters, if there are any: + +---%<------------------------------------------------------------------------- +quota = <backend>[:<quota root name>[:<backend args>]] +---%<------------------------------------------------------------------------- + +The quota root name is just an arbitrary string that is sent to IMAP clients, +which in turn may show it to the user. The name has no meaning. By default an +empty string is used, but you may want to change that since some clients (Apple +Mail) break and don't show quota at all then. + +You can define multiple quota roots by appending an increasing number, for +example: + +---%<------------------------------------------------------------------------- +plugin { + quota = maildir:User quota + quota2 = fs:Disk quota + #quota3 = ... +} +---%<------------------------------------------------------------------------- + +Quota rules +----------- + +Quota rules configure the actual quota limits. The syntax is: + +---%<------------------------------------------------------------------------- +quota_rule = <mailbox name>:<limit configuration> +#quota_rule2 = ... +#quota_rule3 = ..etc.. +---%<------------------------------------------------------------------------- + +"*" as the mailbox name configures the default limit, which is applied on top +of a mailbox-specific limit if found. So for example: + +---%<------------------------------------------------------------------------- +quota_rule = *:storage=1G +quota_rule2 = Trash:storage=+100M +quota_rule3 = SPAM:ignore +---%<------------------------------------------------------------------------- + +This means that the user has 1GB quota, but when saving messages to Trash +mailbox it's possible to use up to 1.1GB of quota. The quota isn't specifically +assigned to Trash, so if you had 1GB of mails in Trash you could still save +100MB of mails to Trash, but nothing to other mailboxes. The idea of this is +mostly to allow the clients' move-to-Trash feature work while user is deleting +messages to get under quota. Additionally, any messages in the SPAM folder are +ignored per the 'ignore' directive and would not count against the quota. + +"?" as the mailbox name works almost like "*". The difference is that "?" is +used only if quota backend doesn't override the limit. For example with +Maildir++ [http://www.inter7.com/courierimap/README.maildirquota.html] quota if +'maildirsize' file exists the limits are taken from it, but if it doesn't exist +the "?" limits are used. + +"*" can't be used as a generic wildcard in mailbox names, so for example "box*" +wouldn't match "boxes". As shown in the above example, the first quota rule is +named 'quota_rule' while the following rules have an increasing digit in them. +You can have as many quota rules as you want. + +Limit configuration +------------------- + +The following limit names are supported: + + * *storage*: Quota limit in kilobytes, 0 means unlimited. + * *bytes*: Quota limit in bytes, 0 means unlimited. + * *messages*: Quota limit in number of messages, 0 means unlimited. This + probably isn't very useful. + * *backend*: Quota backend-specific limit configuration. + * *ignore*: Don't include the specified mailbox in quota at all. + +All of these support also b/k/M/G/T/% suffixes. So storage=100M and bytes=100M +both mean the exact same thing. messages=1k also means 1024 messages (not +1000). + +Percents are relative to the default rule. For example: + +---%<------------------------------------------------------------------------- +plugin { + quota = maildir:User quota + quota_rule = *:storage=1GB + # 10% of 1GB = 100MB + quota_rule2 = Trash:storage=+10%% + # 20% of 1GB = 200MB + quota_rule3 = Spam:storage=+20%% +} +---%<------------------------------------------------------------------------- + +Note that % is written twice to escape it, because <%variables> [Variables.txt] +are expanded in plugin section. <userdb> [UserDatabase.txt] configuration may +or may not require this escaping. + +Backend-specific configuration currently is used only with Maildir++ quota +backend. It means you can have the quota in Maildir++ format (e.g. +"10000000S"). + +Per-user quota +-------------- + +You can override quota rules in your <userdb> [UserDatabase.txt]'s <extra +fields> [UserDatabase.ExtraFields.txt]. Keep all the global settings in plugin +section and override only those settings you need to in your userdb. + +If you're wondering why per-user quota isn't working: + + * Check that 'dovecot-lda' is called with *-d* parameter. + * Check that you're not using <userdb static> [UserDatabase.Static.txt]. + * Check that 'quota_rule' setting is properly returned by userdb. Enable + 'auth_debug=yes' and 'mail_debug=yes' to see this. + +For example: + +---%<------------------------------------------------------------------------- +plugin { + quota = maildir:User quota + quota_rule = *:storage=1G + quota_rule2 = Trash:storage=+100M +} +---%<------------------------------------------------------------------------- + +Next override the default 1GB quota for users: + +LDAP +---- + +Quota limit is in quotaBytes field: + +---%<------------------------------------------------------------------------- +user_attrs = homeDirectory=home, quotaBytes=quota_rule=*:bytes=%$ +---%<------------------------------------------------------------------------- + +Remember that 'user_attrs' is used only if you use <userdb ldap> +[AuthDatabase.LDAP.txt]. + +MySQL +----- + +---%<------------------------------------------------------------------------- +user_query = SELECT uid, gid, home, \ + concat('*:bytes=', quota_limit_bytes) AS quota_rule \ + FROM users WHERE userid = '%u' + +# MySQL with userdb prefetch: Remember to prefix quota_rule with userdb_ +# (just like all other userdb extra fields): +password_query = SELECT userid AS user, password, \ + uid AS userdb_uid, gid AS userdb_gid, \ + concat('*:bytes=', quota_limit_bytes) AS userdb_quota_rule \ + FROM users WHERE userid = '%u' +---%<------------------------------------------------------------------------- + +Remember that 'user_query' is used only if you use <userdb sql> +[AuthDatabase.SQL.txt]. + +PostgreSQL, SQLite +------------------ + +---%<------------------------------------------------------------------------- +user_query = SELECT uid, gid, home, \ + '*:bytes=' || quota_limit_bytes AS quota_rule \ + FROM users WHERE userid = '%u' +---%<------------------------------------------------------------------------- + +Remember that 'user_query' is used only if you use <userdb sql> +[AuthDatabase.SQL.txt]. + +passwd-file +----------- + +Example passwd-file entries: + +---%<------------------------------------------------------------------------- +user:{plain}pass:1000:1000::/home/user::userdb_quota_rule=*:bytes=100M +user2:{plain}pass2:1001:1001::/home/user2::userdb_quota_rule=*:bytes=200M +user3:{plain}pass3:1002:1002::/home/user3::userdb_mail=maildir:~/Maildir +userdb_quota_rule=*:bytes=300M +---%<------------------------------------------------------------------------- + +passwd +------ + +The <passwd> [AuthDatabase.Passwd.txt] userdb doesn't support extra fields. +That's why you can't directly set users' quota limits to passwd file. One +possibility would be to write a script that reads quota limits from another +file, merges them with passwd file and produces another passwd-file, which you +could then use with Dovecot's <userdb passwd-file> +[AuthDatabase.PasswdFile.txt]. + +Quota for public namespaces +--------------------------- + +You can create a separate namespace-specific quota that's shared between all +users. This is done simply by adding ':ns=<namespace prefix>' parameter to +quota setting. For example you could have something like: + +---%<------------------------------------------------------------------------- +namespace { + type = public + prefix = Public/ + #location = .. +} + +plugin { + quota = maildir:User quota + quota2 = maildir:Shared quota:ns=Public/ + #quota_rules and quota2_rules.. +} +---%<------------------------------------------------------------------------- + +Quota for private namespaces +---------------------------- + +You can create a separate namespace-specific quota for a folder hierarchy. This +is done by adding another namespace and the ':ns=<namespace prefix>' parameter +to quota setting. For example you could have something like: + +---%<------------------------------------------------------------------------- +namespace { + type = private + prefix = Archive/ + #location = .. +} + +plugin { + # Maildir quota + quota = maildir:User quota:ns= + quota2 = maildir:Archive quota:ns=Archive/ + + # Dict quota + #quota = dict:User quota:%u.default:ns=:proxy::quota + #quota2 = dict:Archive quota:%u.archive:ns=Archive/:proxy::quota + + #quota_rules and quota2_rules.. +} +---%<------------------------------------------------------------------------- + +Note: If you're using dict quota, you need to make sure that the quota of the +'Archive' namespace is calculated for another "user" than the default +namespace. Either track different namespaces in different backends or make sure +the users differs.'%u.archive' defines '<username>.archive' as key to track +quota for the 'Archive' namespace, the '%u.default' tracks the quota of other +folders. See <Variables.txt> for further help on variables. + +Custom Quota Exceeded Message +----------------------------- + +You can configure Dovecot to send a custom string instead of the default quota +exceeded message. You could have something like: + +---%<------------------------------------------------------------------------- +plugin { + quota_exceeded_message = Quota exceeded, please go to +http://www.example.com/over_quota_help for instructions on how to fix this. +} +---%<------------------------------------------------------------------------- + +Dovecot can also read the quota exceeded message from a file: + +---%<------------------------------------------------------------------------- +plugin { + quota_exceeded_message = </path/to/quota_exceeded_message.txt +} +---%<------------------------------------------------------------------------- + +Quota warnings +-------------- + +You can configure Dovecot to run an external command when user's quota exceeds +a specified limit. Note that the warning is ONLY executed at the exact time +when the limit is being crossed, so when you're testing it you have to do it by +crossing the limit by saving a new mail. If something else besides Dovecot +updates quota so that the limit is crossed, the warning is never executed. The +syntax is: + +---%<------------------------------------------------------------------------- +quota_warning = <limit configuration> <quota-warning socket name> <parameters> +#quota_warning2 = ... +#quota_warning3 = ..etc.. +---%<------------------------------------------------------------------------- + +Limit configuration is almost exactly same as for rules, with the exception of +adding "-" before the value for "reverse" warnings where the script is called +when quota drops below the value. Usually you want to use percents instead of +absolute limits. Only the command for the first exceeded limit is executed, so +configure the highest limit first. The actual commands that are run need to be +created as services. + +An example configuration: + +---%<------------------------------------------------------------------------- +plugin { + quota_warning = storage=95%% quota-warning 95 %u + quota_warning2 = storage=80%% quota-warning 80 %u + quota_warning3 = -storage=100%% quota-warning below %u # user is no longer +over quota +} + +service quota-warning { + executable = script /usr/local/bin/quota-warning.sh + # use some unprivileged user for executing the quota warnings + user = vmail + unix_listener quota-warning { + } +} +---%<------------------------------------------------------------------------- + +With the above example when user's quota exceeds 80%, 'quota-warning.sh' is +executed with parameter 80. The same goes for when quota exceeds 95%. If user +suddenly receives a huge mail and the quota jumps from 70% to 99%, only the 95 +script is executed. + +You have to create the 'quota-warning.sh' script yourself. Here is an example +that sends a mail to the user: + +---%<------------------------------------------------------------------------- +#!/bin/sh +PERCENT=$1 +USER=$2 +cat << EOF | /usr/local/libexec/dovecot/dovecot-lda -d $USER -o +"plugin/quota=maildir:User quota:noenforcing" +From: postmaster@domain.com +Subject: quota warning + +Your mailbox is now $PERCENT% full. +EOF +---%<------------------------------------------------------------------------- + +The quota enforcing is disabled to avoid looping. You'll of course need to +change the 'plugin/quota' value to match the quota backend and other +configuration you use. Basically preserve your original "quota" setting and +just insert ":noenforcing" to proper location in it. For example with dict +quota, you can use something like:'-o "plugin/quota=dict:User +quota::noenforcing:proxy::quota"' + +Overquota-flag (v2.2.16+) +------------------------- + +Quota warnings scripts can be used to set an overquota-flag to userdb (e.g. +LDAP) when user goes over/under quota. This flag can be used by MTA to reject +mails to an user who is over quota already at SMTP RCPT TO stage. The only +problem with this has been that there are race conditions that in some rare +situations cause the overquota-flag to be set even when user is already under +quota. This situation doesn't get solved itself without manual admin +intervention or the new overquota-flag feature: This feature checks the flag's +value every time user logs in (or mail gets delivered or any other email access +to user) and compares it to the current actual quota usage. If the flag is +wrong, a script is executed that should fix up the situation. + +The overquota-flag name in userdb must be "quota_over_flag". There are two +settings to configure what to do: + +---%<------------------------------------------------------------------------- +plugin { + # If quota_over_flag=TRUE, the overquota-flag is enabled. Otherwise not. + quota_over_flag_value = TRUE + + # Any non-empty value for quota_over_flag means user is over quota. + # Wildcards can be used in a generic way, e.g. "*yes" or "*TRUE*" + #quota_over_flag_value = * + + # If set, overquota-flag is checked only when current quota usage is going to +be checked anyway. + # This can be used to optimize this check in case it's running too slowly. +(v2.2.25+) + #quota_over_flag_lazy_check = yes + + # Service script to execute if overquota-flag is wrong. Configured the + # same as quota_warning scripts. The current quota_over_flag's value is + # appended as the last parameter. + quota_over_script = quota-warning mismatch %u +} +---%<------------------------------------------------------------------------- + +Quota grace +----------- + +With v2.2+ by default the last mail can bring user over quota. This is useful +to allow user to actually unambiguously become over quota instead of fail some +of the last larger mails and pass through some smaller mails. Of course the +last mail shouldn't be allowed to bring the user hugely over quota, so by +default in v2.2+ this limit is 10% of the user's quota limit. (In v2.1 this is +disabled by default.) + +To change the quota grace, use: + +---%<------------------------------------------------------------------------- +plugin { + # allow user to become max 10% over quota + quota_grace = 10%% + # allow user to become max 50 MB over quota + quota_grace = 50 M +} +---%<------------------------------------------------------------------------- + +Maximum saved mail size +----------------------- + +(v2.2.29+) Dovecot allows specifying the maximum message size that is allowed +to be saved (e.g. by LMTP, IMAP APPEND or doveadm save). The default is 0, +which is unlimited. Since outgoing mail sizes are also typically limited on the +MTA size, it can be beneficial to prevent user from saving too large mails, +which would later on fail on the MTA side anyway. + +---%<------------------------------------------------------------------------- +plugin { + quota_max_mail_size = 100M +} +---%<------------------------------------------------------------------------- + +Quota admin commands +-------------------- + +The imap_quota plugin implements the SETQUOTA command, which allows changing +the logged in user's quota limit if the user is admin. Normally this means that +a master user must log in with 'userdb_admin=y' set in the master passdb. The +changing is done via dic_set() command, so you must configure the 'quota_set' +setting to point to some dictionary where your quota limit exists. Usually this +is in SQL, e.g.: + +dovecot.conf: + +---%<------------------------------------------------------------------------- +plugin { + quota_set = dict:proxy::sqlquota +} +dict { + sqlquota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +dovecot-dict-sql.conf.ext: + +---%<------------------------------------------------------------------------- +# Use "host= ... pass=foo#bar" with double-quotes if your password has '#' +character. +connect = host=/var/run/mysqld/mysqld.sock dbname=mails user=admin +password=pass +# Alternatively you can connect to localhost as well: +#connect = host=localhost dbname=mails user=admin password=pass # port=3306 + +map { + pattern = priv/quota/limit/storage + table = quota + username_field = username + value_field = bytes +} +map { + pattern = priv/quota/limit/messages + table = quota + username_field = username + value_field = messages +} +---%<------------------------------------------------------------------------- + +Afterwards the quota can be changed with: + +---%<------------------------------------------------------------------------- +a SETQUOTA "User quota" (STORAGE 12345 MESSAGES 123) +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) |