summaryrefslogtreecommitdiffstats
path: root/doc/wiki/Quota.Configuration.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/wiki/Quota.Configuration.txt')
-rw-r--r--doc/wiki/Quota.Configuration.txt513
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)