From 5d6d1a3a536813f1ac3adfbbf2d12b731ade4a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= Date: Thu, 29 Jun 2023 16:12:11 +0300 Subject: [PATCH] Improve Markdown formatting * use

and
elements to separate configuration directives * use elements to mark constants, fs paths, module names etc. * fix unneeded "\_" escaping * fix list formatting --- docs/reference/auth/dovecot_sasl.md | 8 +- docs/reference/auth/external.md | 23 ++-- docs/reference/auth/ldap.md | 65 ++++++---- docs/reference/auth/netauth.md | 15 +-- docs/reference/auth/pam.md | 24 ++-- docs/reference/auth/pass_table.md | 12 +- docs/reference/auth/plain_separate.md | 11 +- docs/reference/auth/shadow.md | 16 ++- docs/reference/blob/fs.md | 5 +- docs/reference/blob/s3.md | 56 +++++---- docs/reference/checks/actions.md | 6 +- docs/reference/checks/authorize_sender.md | 62 +++++---- docs/reference/checks/command.md | 113 ++++++----------- docs/reference/checks/dkim.md | 28 +++-- docs/reference/checks/dnsbl.md | 65 ++++++---- docs/reference/checks/milter.md | 12 +- docs/reference/checks/misc.md | 33 ++--- docs/reference/checks/rspamd.md | 58 ++++++--- docs/reference/checks/spf.md | 50 +++++--- docs/reference/config-syntax.md | 16 +-- docs/reference/endpoints/imap.md | 61 ++++++--- docs/reference/endpoints/openmetrics.md | 1 + docs/reference/endpoints/smtp.md | 140 ++++++++++++--------- docs/reference/global-config.md | 88 +++++++------ docs/reference/modifiers/dkim.md | 122 +++++++++++------- docs/reference/modifiers/envelope.md | 5 +- docs/reference/smtp-pipeline.md | 140 +++++++++++++-------- docs/reference/storage/imapsql.md | 131 +++++++++++-------- docs/reference/table/chain.md | 7 +- docs/reference/table/email_localpart.md | 7 +- docs/reference/table/email_with_domains.md | 6 +- docs/reference/table/regexp.md | 25 ++-- docs/reference/table/sql_query.md | 46 ++++--- docs/reference/table/static.md | 2 +- docs/reference/targets/queue.md | 45 ++++--- docs/reference/targets/remote.md | 118 +++++++++++------ docs/reference/targets/smtp.md | 87 ++++++------- docs/reference/tls-acme.md | 68 ++++++---- docs/reference/tls.md | 132 +++++++++---------- 39 files changed, 1111 insertions(+), 798 deletions(-) diff --git a/docs/reference/auth/dovecot_sasl.md b/docs/reference/auth/dovecot_sasl.md index b00f9c77..919d42b8 100644 --- a/docs/reference/auth/dovecot_sasl.md +++ b/docs/reference/auth/dovecot_sasl.md @@ -1,6 +1,6 @@ # Dovecot SASL -The 'auth.dovecot\_sasl' module implements the client side of the Dovecot +The 'auth.dovecot_sasl' module implements the client side of the Dovecot authentication protocol, allowing maddy to use it as a credentials source. Currently SASL mechanisms support is limited to mechanisms supported by maddy @@ -16,11 +16,11 @@ dovecot_sasl unix://socket_path ## Configuration directives -**Syntax**: endpoint _schema://address_
-**Default**: not set +### endpoint _schema://address_ +Default: not set Set the address to use to contact Dovecot SASL server in the standard endpoint format. -tcp://10.0.0.1:2222 for TCP, unix:///var/lib/dovecot/auth.sock for Unix +`tcp://10.0.0.1:2222` for TCP, `unix:///var/lib/dovecot/auth.sock` for Unix domain sockets. diff --git a/docs/reference/auth/external.md b/docs/reference/auth/external.md index 6c28d743..9b9659ef 100644 --- a/docs/reference/auth/external.md +++ b/docs/reference/auth/external.md @@ -1,12 +1,12 @@ # System command auth.external module for authentication using external helper binary. It looks for binary -named maddy-auth-helper in $PATH and libexecdir and uses it for authentication +named `maddy-auth-helper` in $PATH and libexecdir and uses it for authentication using username/password pair. The protocol is very simple: Program is launched for each authentication. Username and password are written -to stdin, adding \\n to the end. If binary exits with 0 status code - +to stdin, adding \n to the end. If binary exits with 0 status code - authentication is considered successful. If the status code is 1 - authentication is failed. If the status code is 2 - another unrelated error has happened. Additional information should be written to stderr. @@ -21,19 +21,24 @@ auth.external { ## Configuration directives -**Syntax**: helper _file\_path\_ +### helper _file_path_ -Location of the helper binary. **Required.** +**Required.**
+Location of the helper binary. -**Syntax**: perdomain _boolean_
-**Default**: no +--- + +### perdomain _boolean_ +Default: `no` Don't remove domain part of username when authenticating and require it to be present. Can be used if you want user@domain1 and user@domain2 to be different accounts. -**Syntax**: domains _domains..._
-**Default**: not specified +--- + +### domains _domains..._ +Default: not specified Domains that should be allowed in username during authentication. @@ -43,5 +48,5 @@ name in addition to just username. If used without 'perdomain', domain part will be removed from login before check with underlying auth. mechanism. If 'perdomain' is set, then -domains must be also set and domain part WILL NOT be removed before check. +domains must be also set and domain part **will not** be removed before check. diff --git a/docs/reference/auth/ldap.md b/docs/reference/auth/ldap.md index c2c3ce6b..a4ced551 100644 --- a/docs/reference/auth/ldap.md +++ b/docs/reference/auth/ldap.md @@ -8,7 +8,7 @@ directory search or template . Note that storage backends conventionally use email addresses, if you use non-email identifiers as usernames then you should map them onto -emails on delivery by using auth\_map (see documentation page for used storage backend). +emails on delivery by using `auth_map` (see documentation page for used storage backend). auth.ldap also can be a used as a table module. This way you can check whether the account exists. It works only if DN template is not used. @@ -42,72 +42,89 @@ auth.ldap ldap://maddy.test.389 { ## Configuration directives -**Syntax:** urls _servers...\_ +### urls _servers..._ -REQUIRED. +**Required.** URLs of the directory servers to use. First available server is used - no load-balancing is done. -URLs should use 'ldap://', 'ldaps://', 'ldapi://' schemes. +URLs should use `ldap://`, `ldaps://`, `ldapi://` schemes. -**Syntax:** bind off
-bind unauth
-bind external
-bind plain _username_ _password_
-**Default:** off +--- + +### bind `off` | `unauth` | `external` | `plain` _username_ _password_ + +Default: `off` Credentials to use for initial binding. Required if DN lookup is used. -'unauth' performs unauthenticated bind. 'external' performs external binding -which is useful for Unix socket connections (ldapi://) or TLS client certificate -authentication (cert. is set using tls\_client directive). 'plain' performs a +`unauth` performs unauthenticated bind. `external` performs external binding +which is useful for Unix socket connections (`ldapi://`) or TLS client certificate +authentication (cert. is set using tls_client directive). `plain` performs a simple bind using provided credentials. -**Syntax:** dn\_template _template\_ +--- + +### dn_template _template_ -DN template to use for binding. '{username}' is replaced with the +DN template to use for binding. `{username}` is replaced with the username specified by the user. -**Syntax:** base\_dn _dn\_ +--- + +### base_dn _dn_ Base DN to use for lookup. -**Syntax:** filter _str\_ +--- + +### filter _str_ -DN lookup filter. '{username}' is replaced with the username specified +DN lookup filter. `{username}` is replaced with the username specified by the user. Example: + ``` (&(objectClass=posixAccount)(uid={username})) ``` Example (using ActiveDirectory): + ``` (&(objectCategory=Person)(memberOf=CN=user-group,OU=example,DC=example,DC=org)(sAMAccountName={username})(!(UserAccountControl:1.2.840.113556.1.4.803:=2))) ``` Example: + ``` (&(objectClass=Person)(mail={username})) ``` -**Syntax:** starttls _bool_
-**Default:** off +--- + +### starttls _bool_ +Default: `off` Whether to upgrade connection to TLS using STARTTLS. -**Syntax:** tls\_client { ... } +--- + +### tls_client { ... } Advanced TLS client configuration. See [TLS configuration / Client](/reference/tls/#client) for details. -**Syntax:** connect\_timeout _duration_
-**Default:** 1m +--- + +### connect_timeout _duration_ +Default: `1m` Timeout for initial connection to the directory server. -**Syntax:** request\_timeout _duration_
-**Default:** 1m +--- + +### request_timeout _duration_ +Default: `1m` Timeout for each request (binding, lookup). diff --git a/docs/reference/auth/netauth.md b/docs/reference/auth/netauth.md index 074b74c8..2664d41f 100644 --- a/docs/reference/auth/netauth.md +++ b/docs/reference/auth/netauth.md @@ -9,7 +9,7 @@ mail address. Note that storage backends conventionally use email addresses. Since NetAuth recommends *nix compatible usernames, you will need to map the -email identifiers to NetAuth Entity IDs using auth\_map (see +email identifiers to NetAuth Entity IDs using `auth_map` (see documentation page for used storage backend). auth.netauth also can be used as a table module. This way you can @@ -33,15 +33,16 @@ auth.netauth {} ## Configuration directives -**Syntax:** require\_group _group_ +### require_group _group_ -OPTIONAL. +Optional. Group that entities must possess to be able to use maddy services. This can be used to provide email to just a subset of the entities present in NetAuth. -**Syntax** debug off
-debug on
-debug off
-**Default:** off +--- + +### debug `on` | `off` + +Default: `off` diff --git a/docs/reference/auth/pam.md b/docs/reference/auth/pam.md index 79331fce..89f0f3e3 100644 --- a/docs/reference/auth/pam.md +++ b/docs/reference/auth/pam.md @@ -4,7 +4,8 @@ auth.pam module implements authentication using libpam. Alternatively it can be use helper binary like auth.external module does. maddy should be built with libpam build tag to use this module without -'use\_helper' directive. +'use_helper' directive. + ``` go get -tags 'libpam' ... ``` @@ -18,25 +19,28 @@ auth.pam { ## Configuration directives -**Syntax**: debug _boolean_
-**Default**: no +### debug _boolean_ +Default: `no` Enable verbose logging for all modules. You don't need that unless you are reporting a bug. -**Syntax**: use\_helper _boolean_
-**Default**: no +--- + +### use_helper _boolean_ +Default: `no` -Use LibexecDirectory/maddy-pam-helper instead of directly calling libpam. +Use `LibexecDirectory/maddy-pam-helper` instead of directly calling libpam. You need to use that if: -1. maddy is not compiled with libpam, but maddy-pam-helper is built separately. -2. maddy is running as an unprivileged user and used PAM configuration requires additional - privileges (e.g. when using system accounts). -For 2, you need to make maddy-pam-helper binary setuid, see +1. maddy is not compiled with libpam, but `maddy-pam-helper` is built separately. +2. maddy is running as an unprivileged user and used PAM configuration requires additional privileges (e.g. when using system accounts). + +For 2, you need to make `maddy-pam-helper` binary setuid, see README.md in source tree for details. TL;DR (assuming you have the maddy group): + ``` chown root:maddy /usr/lib/maddy/maddy-pam-helper chmod u+xs,g+x,o-x /usr/lib/maddy/maddy-pam-helper diff --git a/docs/reference/auth/pass_table.md b/docs/reference/auth/pass_table.md index 6b1e2146..39fea6fc 100644 --- a/docs/reference/auth/pass_table.md +++ b/docs/reference/auth/pass_table.md @@ -3,7 +3,7 @@ auth.pass_table module implements username:password authentication by looking up the password hash using a table module (maddy-tables(5)). It can be used to load user credentials from text file (via table.file module) or SQL query -(via table.sql\_table module). +(via table.sql_table module). Definition: @@ -30,15 +30,15 @@ smtp tcp://0.0.0.0:587 { ## Password hashes -pass\_table expects the used table to contain certain structured values with +pass_table expects the used table to contain certain structured values with hash algorithm name, salt and other necessary parameters. -You should use 'maddy hash' command to generate suitable values. -See 'maddy hash --help' for details. +You should use `maddy hash` command to generate suitable values. +See `maddy hash --help` for details. ## maddy creds If the underlying table is a "mutable" table (see maddy-tables(5)) then -the 'maddy creds' command can be used to modify the underlying tables -via pass\_table module. It will act on a "local credentials store" and will write +the `maddy creds` command can be used to modify the underlying tables +via pass_table module. It will act on a "local credentials store" and will write appropriate hash values to the table. diff --git a/docs/reference/auth/plain_separate.md b/docs/reference/auth/plain_separate.md index 0e1cb09b..f5b57667 100644 --- a/docs/reference/auth/plain_separate.md +++ b/docs/reference/auth/plain_separate.md @@ -1,6 +1,6 @@ # Separate username and password lookup -auth.plain\_separate module implements authentication using username:password pairs but can +auth.plain_separate module implements authentication using username:password pairs but can use zero or more "table modules" (maddy-tables(5)) and one or more authentication providers to verify credentials. @@ -24,19 +24,22 @@ How it works: ## Configuration directives -***Syntax:*** user _table module\_ +### user _table-module_ Configuration block for any module from maddy-tables(5) can be used here. Example: + ``` user file /etc/maddy/allowed_users ``` -***Syntax:*** pass _auth provider\_ +--- + +### pass _auth-provider_ Configuration block for any auth. provider module can be used here, even -'plain\_split' itself. +'plain_split' itself. The used auth. provider must provide username:password pair-based authentication. diff --git a/docs/reference/auth/shadow.md b/docs/reference/auth/shadow.md index e3c41c8c..0fc3e89b 100644 --- a/docs/reference/auth/shadow.md +++ b/docs/reference/auth/shadow.md @@ -12,23 +12,27 @@ auth.shadow { ## Configuration directives -**Syntax**: debug _boolean_
-**Default**: no +### debug _boolean_ + +Default: `no` Enable verbose logging for all modules. You don't need that unless you are reporting a bug. -**Syntax**: use\_helper _boolean_
-**Default**: no +--- + +### use_helper _boolean_ +Default: `no` -Use LibexecDirectory/maddy-shadow-helper instead of directly reading /etc/shadow. +Use `LibexecDirectory/maddy-shadow-helper` instead of directly reading `/etc/shadow`. You need to use that if maddy is running as an unprivileged user privileges (e.g. when using system accounts). -You need to make maddy-shadow-helper binary setuid, see +You need to make `maddy-shadow-helper` binary setuid, see cmd/maddy-shadow-helper/README.md in source tree for details. TL;DR (assuming you have maddy group): + ``` chown root:maddy /usr/lib/maddy/maddy-shadow-helper chmod u+xs,g+x,o-x /usr/lib/maddy/maddy-shadow-helper diff --git a/docs/reference/blob/fs.md b/docs/reference/blob/fs.md index 4bc1c897..ef94b54b 100644 --- a/docs/reference/blob/fs.md +++ b/docs/reference/blob/fs.md @@ -7,14 +7,15 @@ storage.blob.fs { root } ``` + ``` storage.blob.fs ``` ## Configuration directives -**Syntax:** root _path_
-**Default:** not set +### root _path_ +Default: not set Path to the FS directory. Must be readable and writable by the server process. If it does not exist - it will be created (parent directory should be writable diff --git a/docs/reference/blob/s3.md b/docs/reference/blob/s3.md index ac02ed48..54b6a4e2 100644 --- a/docs/reference/blob/s3.md +++ b/docs/reference/blob/s3.md @@ -18,6 +18,7 @@ storage.blob.s3 { ``` Example: + ``` storage.imapsql local_mailboxes { ... @@ -34,53 +35,64 @@ storage.imapsql local_mailboxes { ## Configuration directives -**Syntax:** endpoint _address:port\_ +### endpoint _address:port_ + +**Required**. -REQUIRED. +Root S3 endpoint. e.g. `s3.amazonaws.com` -Root S3 endpoint. e.g. s3.amazonaws.com +--- -**Syntax:** secure _boolean_
-**Default:** yes +### secure _boolean_ +Default: `yes` Whether TLS should be used. -**Syntax:** access\_key _string_
-**Syntax:** secret\_key _string\_ +--- -REQUIRED. +### access_key _string_
secret_key _string_ + +**Required**. Static S3 credentials. -**Syntax:** bucket _name\_ +--- + +### bucket _name_ -REQUIRED. +**Required**. S3 bucket name. The bucket must exist and be read-writable. -**Syntax:** region _string_
-**Default:** not set +--- -S3 bucket location. May be called "endpoint" -in some manuals. +### region _string_ +Default: not set -**Syntax:** object\_prefix _string_
-**Default:** empty string +S3 bucket location. May be called "endpoint" in some manuals. + +--- + +### object_prefix _string_ +Default: empty string String to add to all keys stored by maddy. Can be useful when S3 is used as a file system. -**Syntax:** creds _string_
-**Default:** access_key +--- + +### creds `access_key` | `file_minio` | `file_aws` | `iam` +Default: `access_key` Credentials to use for accessing the S3 Bucket. Credential Types: - - access_key: use AWS access key and secret access key - - file_minio: use credentials for Minio present at ~/.mc/config.json - - file_aws: use credentials for AWS S3 present at ~/.aws/credentials - - iam: use AWS IAM instance profile for credentials. + + - `access_key`: use AWS access key and secret access key + - `file_minio`: use credentials for Minio present at ~/.mc/config.json + - `file_aws`: use credentials for AWS S3 present at ~/.aws/credentials + - `iam`: use AWS IAM instance profile for credentials. By default, access_key is used with the access key and secret access key present in the config. diff --git a/docs/reference/checks/actions.md b/docs/reference/checks/actions.md index 7ab88288..d9e9f9c9 100644 --- a/docs/reference/checks/actions.md +++ b/docs/reference/checks/actions.md @@ -4,16 +4,16 @@ When a certain check module thinks the message is "bad", it takes some actions depending on its configuration. Most checks follow the same configuration structure and allow following actions to be taken on check failure: -- Do nothing ('action ignore') +- Do nothing (`action ignore`) Useful for testing deployment of new checks. Check failures are still logged but they have no effect on message delivery. -- Reject the message ('action reject') +- Reject the message (`action reject`) Reject the message at connection time. No bounce is generated locally. -- Quarantine the message ('action quarantine') +- Quarantine the message (`action quarantine`) Mark message as 'quarantined'. If message is then delivered to the local storage, the storage backend can place the message in the 'Junk' mailbox. diff --git a/docs/reference/checks/authorize_sender.md b/docs/reference/checks/authorize_sender.md index b65ea2d0..0ceacff8 100644 --- a/docs/reference/checks/authorize_sender.md +++ b/docs/reference/checks/authorize_sender.md @@ -3,7 +3,7 @@ Module check.authorize_sender verifies that envelope and header sender addresses belong to the authenticated user. Address ownership is established via table that maps each user account to a email address it is allowed to use. -There are some special cases, see user\_to\_email description below. +There are some special cases, see `user_to_email` description below. ``` check.authorize_sender { @@ -28,16 +28,16 @@ check { ## Configuration directives -**Syntax:** user\_to\_email _table_
-**Default:** identity +### user_to_email _table_ +Default: `identity` Table that maps authorization username to the list of sender emails the user is allowed to use. In additional to email addresses, the table can contain domain names or -special string "\*" as a value. If the value is a domain - user +special string "*" as a value. If the value is a domain - user will be allowed to use any mailbox within it as a sender address. -If it is "\*" - user will be allowed to use any address. +If it is "*" - user will be allowed to use any address. By default, table.identity is used, meaning that username should be equal to the sender email. @@ -45,8 +45,10 @@ be equal to the sender email. Before username is looked up via the table, normalization algorithm defined by auth_normalize is applied to it. -**Syntax:** prepare\_email _table_
-**Default:** identity +--- + +### prepare_email _table_ +Default: `identity` Table that is used to translate email addresses before they are matched against user_to_email values. @@ -59,36 +61,48 @@ done in default configuration. If table does not contain any mapping for the used sender address, it will be used as is. -**Syntax:** check\_header _boolean_
-**Default:** yes +--- + +### check_header _boolean_ +Default: `yes` Whether to verify header sender in addition to envelope. Either Sender or From field value should match the authorization identity. -**Syntax:** unauth\_action _action_
-**Default:** reject +--- + +### unauth_action _action_ +Default: `reject` What to do if the user is not authenticated at all. -**Syntax:** no\_match\_action _action_
-**Default:** reject +--- + +### no_match_action _action_ +Default: `reject` What to do if user is not allowed to use the sender address specified. -**Syntax:** malformed\_action _action_
-**Default:** reject +--- + +### malformed_action _action_ +Default: `reject` What to do if From or Sender header fields contain malformed values. -**Syntax:** err\_action _action_
-**Default:** reject +--- + +### err_action _action_ +Default: `reject` -What to do if error happens during prepare\_email or user\_to\_email lookup. +What to do if error happens during prepare_email or user_to_email lookup. -**Syntax:** auth\_normalize _action_
-**Default:** auto +--- + +### auth_normalize _action_ +Default: `auto` Normalization function to apply to authorization username before further processing. @@ -107,10 +121,12 @@ PRECIS profiles are defined by RFC 8265. In short, they make sure that Unicode strings that look the same will be compared as if they were the same. CaseMapped profiles also convert strings to lower case. -**Syntax:** from\_normalize _action_
-**Default:** auto +--- + +### from_normalize _action_ +Default: `auto` Normalization function to apply to email addresses before further processing. -Available options are same as for auth\_normalize. +Available options are same as for `auth_normalize`. diff --git a/docs/reference/checks/command.md b/docs/reference/checks/command.md index 3cbb4892..6475efcf 100644 --- a/docs/reference/checks/command.md +++ b/docs/reference/checks/command.md @@ -23,47 +23,23 @@ system shell. There is a set of special strings that are replaced with the corresponding message-specific values: -- {source\_ip} - - IPv4/IPv6 address of the sending MTA. - -- {source\_host} - - Hostname of the sending MTA, from the HELO/EHLO command. - -- {source\_rdns} - - PTR record of the sending MTA IP address. - -- {msg\_id} - - Internal message identifier. Unique for each delivery. - -- {auth\_user} - - Client username, if authenticated using SASL PLAIN - -- {sender} - - Message sender address, as specified in the MAIL FROM SMTP command. - -- {rcpts} - - List of accepted recipient addresses, including the currently handled +- `{source_ip}` – IPv4/IPv6 address of the sending MTA. +- `{source_host}` – Hostname of the sending MTA, from the HELO/EHLO command. +- `{source_rdns}` – PTR record of the sending MTA IP address. +- `{msg_id}` – Internal message identifier. Unique for each delivery. +- `{auth_user}` – Client username, if authenticated using SASL PLAIN +- `{sender}` – Message sender address, as specified in the MAIL FROM SMTP command. +- `{rcpts}` – List of accepted recipient addresses, including the currently handled one. +- `{address}` – Currently handled address. This is a recipient address if the command + is called during RCPT TO command handling (`run_on rcpt`) or a sender + address if the command is called during MAIL FROM command handling (`run_on + sender`). -- {address} - - Currently handled address. This is a recipient address if the command - is called during RCPT TO command handling ('run\_on rcpt') or a sender - address if the command is called during MAIL FROM command handling ('run\_on - sender'). - - -If value is undefined (e.g. {source\_ip} for a message accepted over a Unix +If value is undefined (e.g. `{source_ip}` for a message accepted over a Unix socket) or unavailable (the command is executed too early), the placeholder is replaced with an empty string. Note that it can not remove the argument. -E.g. -i {source\_ip} will not become just -i, it will be -i "" +E.g. `-i {source_ip}` will not become just `-i`, it will be `-i ""` Undefined placeholders are not replaced. @@ -77,55 +53,44 @@ The header from stdout will be **prepended** to the message header. ## Configuration directives -**Syntax**: run\_on conn|sender|rcpt|body
-**Default**: body +### run_on `conn` | `sender` | `rcpt` | `body` +Default: `body` When to run the command. This directive also affects the information visible for the message. -- conn - - Run before the sender address (MAIL FROM) is handled. - - **Stdin**: Empty
- **Available placeholders**: {source\_ip}, {source\_host}, {msg\_id}, {auth\_user}. - -- sender - - Run during sender address (MAIL FROM) handling. - - **Stdin**: Empty
- **Available placeholders**: conn placeholders + {sender}, {address}. - - The {address} placeholder contains the MAIL FROM address. - -- rcpt - - Run during recipient address (RCPT TO) handling. The command is executed - once for each RCPT TO command, even if the same recipient is specified - multiple times. - - **Stdin**: Empty
- **Available placeholders**: sender placeholders + {rcpts}. +- `conn`
+ Run before the sender address (MAIL FROM) is handled.
+ **Stdin**: Empty
+ **Available placeholders**: {source_ip}, {source_host}, {msg_id}, {auth_user}. - The {address} placeholder contains the recipient address. +- `sender`
+ Run during sender address (MAIL FROM) handling.
+ **Stdin**: Empty
+ **Available placeholders**: conn placeholders + {sender}, {address}. + The {address} placeholder contains the MAIL FROM address. -- body +- `rcpt`
+ Run during recipient address (RCPT TO) handling. The command is executed + once for each RCPT TO command, even if the same recipient is specified + multiple times.
+ **Stdin**: Empty
+ **Available placeholders**: sender placeholders + {rcpts}. + The {address} placeholder contains the recipient address. - Run during message body handling. +- `body`
+ Run during message body handling.
+ **Stdin**: The message header + body
+ **Available placeholders**: all except for {address}. - **Stdin**: The message header + body
- **Available placeholders**: all except for {address}. +--- -**Syntax**:
-code _integer_ ignore
-code _integer_ quarantine
-code _integer_ reject [SMTP code] [SMTP enhanced code] [SMTP message] +### code _integer_ ignore
code _integer_ quarantine
code _integer_ reject _smtp-code_ _smtp-enhanced-code_ _smtp-message_ -This directives specified the mapping from the command exit code _integer_ to +This directive specifies the mapping from the command exit code _integer_ to the message pipeline action. Two codes are defined implicitly, exit code 1 causes the message to be rejected with a permanent error, exit code 2 causes the message to be quarantined. Both -action can be overridden using the 'code' directive. +actions can be overridden using the 'code' directive. diff --git a/docs/reference/checks/dkim.md b/docs/reference/checks/dkim.md index 5aa2dc34..7ab14a6d 100644 --- a/docs/reference/checks/dkim.md +++ b/docs/reference/checks/dkim.md @@ -16,14 +16,16 @@ check.dkim { } ``` -**Syntax**: debug _boolean_
-**Default**: global directive value +### debug _boolean_ +Default: global directive value Log both successful and unsuccessful check executions instead of just unsuccessful. -**Syntax**: required\_fields _string..._
-**Default**: From Subject +--- + +### required_fields _string..._ +Default: `From Subject` Header fields that should be included in each signature. If signature lacks any field listed in that directive, it will be considered invalid. @@ -31,24 +33,30 @@ lacks any field listed in that directive, it will be considered invalid. Note that From is always required to be signed, even if it is not included in this directive. -**Syntax**: no\_sig\_action _action_
-**Default**: ignore (recommended by RFC 6376) +--- + +### no_sig_action _action_ +Default: `ignore` (recommended by RFC 6376) Action to take when message without any signature is received. Note that DMARC policy of the sender domain can request more strict handling of missing DKIM signatures. -**Syntax**: broken\_sig\_action _action_
-**Default**: ignore (recommended by RFC 6376) +--- + +### broken_sig_action _action_ +Default: `ignore` (recommended by RFC 6376) Action to take when there are not valid signatures in a message. Note that DMARC policy of the sender domain can request more strict handling of broken DKIM signatures. -**Syntax**: fail\_open _boolean_
-**Default**: no +--- + +### fail_open _boolean_ +Default: `no` Whether to accept the message if a temporary error occurs during DKIM verification. Rejecting the message with a 4xx code will require the sender diff --git a/docs/reference/checks/dnsbl.md b/docs/reference/checks/dnsbl.md index bb3615b9..a2d27362 100644 --- a/docs/reference/checks/dnsbl.md +++ b/docs/reference/checks/dnsbl.md @@ -60,13 +60,15 @@ check { ## Configuration directives -**Syntax**: debug _boolean_
-**Default**: global directive value +### debug _boolean_ +Default: global directive value Enable verbose logging. -**Syntax**: check\_early _boolean_
-**Default**: no +--- + +### check_early _boolean_ +Default: `no` Check BLs before mail delivery starts and silently reject blacklisted clients. @@ -74,22 +76,27 @@ For this to work correctly, check should not be used in source/destination pipeline block. In particular, this means: + - No logging is done for rejected messages. -- No action is taken if quarantine\_threshold is hit, only reject\_threshold +- No action is taken if `quarantine_threshold` is hit, only `reject_threshold` applies. -- defer\_sender\_reject from SMTP configuration takes no effect. +- `defer_sender_reject` from SMTP configuration takes no effect. - MAIL FROM is not checked, even if specified. If you often get hit by spam attacks, it is recommended to enable this setting to save server resources. -**Syntax**: quarantine\_threshold _integer_
-**Default**: 1 +--- + +### quarantine_threshold _integer_ +Default: `1` DNSBL score needed (equals-or-higher) to quarantine the message. -**Syntax**: reject\_threshold _integer_
-**Default**: 9999 +--- + +### reject_threshold _integer_ +Default: `9999` DNSBL score needed (equals-or-higher) to reject the message. @@ -110,46 +117,56 @@ Directive name and arguments specify the actual DNS zone to query when checking the list. Using multiple arguments is equivalent to specifying the same configuration separately for each list. -**Syntax**: client\_ipv4 _boolean_
-**Default**: yes +### client_ipv4 _boolean_ +Default: `yes` Whether to check address of the IPv4 clients against the list. -**Syntax**: client\_ipv6 _boolean_
-**Default**: yes +--- + +### client_ipv6 _boolean_ +Default: `yes` Whether to check address of the IPv6 clients against the list. -**Syntax**: ehlo _boolean_
-**Default**: no +--- + +### ehlo _boolean_ +Default: `no` Whether to check hostname specified n the HELO/EHLO command against the list. This works correctly only with domain-based DNSBLs. -**Syntax**: mailfrom _boolean_
-**Default**: no +--- + +### mailfrom _boolean_ +Default: `no` Whether to check domain part of the MAIL FROM address against the list. This works correctly only with domain-based DNSBLs. -**Syntax**: responses _cidr|ip..._
-**Default**: 127.0.0.1/24 +--- + +### responses _cidr_ | _ip..._ +Default: `127.0.0.1/24` IP networks (in CIDR notation) or addresses to permit in list lookup results. Addresses not matching any entry in this directives will be ignored. -**Syntax**: score _integer_
-**Default**: 1 +--- + +### score _integer_ +Default: `1` Score value to add for the message if it is listed. -If sum of list scores is equals or higher than quarantine\_threshold, the +If sum of list scores is equals or higher than `quarantine_threshold`, the message will be quarantined. -If sum of list scores is equals or higher than rejected\_threshold, the message +If sum of list scores is equals or higher than `rejected_threshold`, the message will be rejected. It is possible to specify a negative value to make list act like a whitelist diff --git a/docs/reference/checks/milter.md b/docs/reference/checks/milter.md index 4f597636..8286a79b 100644 --- a/docs/reference/checks/milter.md +++ b/docs/reference/checks/milter.md @@ -32,15 +32,17 @@ via. See below. ## Configuration directives -***Syntax:*** endpoint _scheme://path_
-***Default:*** not set +### endpoint _scheme://path_ +Default: not set Specifies milter protocol endpoint to use. The endpoit is specified in standard URL-like format: -'tcp://127.0.0.1:6669' or 'unix:///var/lib/milter/filter.sock' +`tcp://127.0.0.1:6669` or `unix:///var/lib/milter/filter.sock` -***Syntax:*** fail\_open _boolean_
-***Default:*** false +--- + +### fail_open _boolean_ +Default: `false` Toggles behavior on milter I/O errors. If false ("fail closed") - message is rejected with temporary error code. If true ("fail open") - check is skipped. diff --git a/docs/reference/checks/misc.md b/docs/reference/checks/misc.md index 25e1ff63..19c71ad0 100644 --- a/docs/reference/checks/misc.md +++ b/docs/reference/checks/misc.md @@ -4,40 +4,45 @@ Following directives are defined for all modules listed below. -**Syntax**:
-fail\_action ignore
-fail\_action reject
-fail\_action quarantine
-**Default**: quarantine +### fail_action `ignore` | `reject` | `quarantine` +Default: `quarantine` -Action to take when check fails. See Check actions for details. +Action to take when check fails. See [Check actions](../actions/) for details. -**Syntax**: debug _boolean_
-**Default**: global directive value +--- + +### debug _boolean_ +Default: global directive value Log both successful and unsuccessful check executions instead of just unsuccessful. -## require\_mx\_record +--- + +### require_mx_record Check that domain in MAIL FROM command does have a MX record and none of them are "null" (contain a single dot as the host). By default, quarantines messages coming from servers missing MX records, -use 'fail\_action' directive to change that. +use `fail_action` directive to change that. -## require\_matching\_rdns +--- + +### require_matching_rdns Check that source server IP does have a PTR record point to the domain specified in EHLO/HELO command. By default, quarantines messages coming from servers with mismatched or missing -PTR record, use 'fail\_action' directive to change that. +PTR record, use `fail_action` directive to change that. + +--- -## require\_tls +### require_tls Check that the source server is connected via TLS; either directly, or by using the STARTTLS command. By default, rejects messages coming from unencrypted servers. Use the -'fail\_action' directive to change that. \ No newline at end of file +`fail_action` directive to change that. \ No newline at end of file diff --git a/docs/reference/checks/rspamd.md b/docs/reference/checks/rspamd.md index cf30d512..90063ae9 100644 --- a/docs/reference/checks/rspamd.md +++ b/docs/reference/checks/rspamd.md @@ -22,58 +22,76 @@ rspamd http://127.0.0.1:11333 ## Configuration directives -**Syntax:** tls\_client { ... }
-**Default:** not set +### tls_client { ... } +Default: not set Configure TLS client if HTTPS is used. See [TLS configuration / Client](/reference/tls/#client) for details. -**Syntax:** api\_path _url_
-**Default:** http://127.0.0.1:11333 +--- + +### api_path _url_ +Default: `http://127.0.0.1:11333` URL of HTTP API endpoint. Supports both HTTP and HTTPS and can include path element. -**Syntax:** settings\_id _string_
-**Default:** not set +--- + +### settings_id _string_ +Default: not set Settings ID to pass to the server. -**Syntax:** tag _string_
-**Default:** maddy +--- + +### tag _string_ +Default: `maddy` Value to send in MTA-Tag header field. -**Syntax:** hostname _string_
-**Default:** value of global directive +--- + +### hostname _string_
+Default: value of global directive Value to send in MTA-Name header field. -**Syntax:** io\_error\_action _action_
-**Default:** ignore +--- + +### io_error_action _action_ +Default: `ignore` Action to take in case of inability to contact the rspamd server. -**Syntax:** error\_resp\_action _action_
-**Default:** ignore +--- + +### error_resp_action _action_ +Default: `ignore` Action to take in case of 5xx or 4xx response received from the rspamd server. -**Syntax:** add\_header\_action _action_
-**Default:** quarantine +--- + +### add_header_action _action_ +Default: `quarantine` Action to take when rspamd requests to "add header". X-Spam-Flag and X-Spam-Score are added to the header irregardless of value. -**Syntax:** rewrite\_subj\_action _action_
-**Default:** quarantine +--- + +### rewrite_subj_action _action_ +Default: `quarantine` Action to take when rspamd requests to "rewrite subject". X-Spam-Flag and X-Spam-Score are added to the header irregardless of value. -**Syntax:** flags _string list..._
-**Default:** pass\_all +--- + +### flags _string-list..._ +Default: `pass_all` Flags to pass to the rspamd server. See [https://rspamd.com/doc/architecture/protocol.html](https://rspamd.com/doc/architecture/protocol.html) for details. diff --git a/docs/reference/checks/spf.md b/docs/reference/checks/spf.md index 83bc81b0..f0afb347 100644 --- a/docs/reference/checks/spf.md +++ b/docs/reference/checks/spf.md @@ -14,12 +14,12 @@ Authentication-Results field is generated irregardless of status. It is recommended by the DMARC standard to don't fail delivery based solely on SPF policy and always check DMARC policy and take action based on it. -If enforce\_early is no, check.spf module will not take any action on SPF +If `enforce_early` is `no`, check.spf module will not take any action on SPF policy failure if sender domain does have a DMARC record with 'quarantine' or 'reject' policy. Instead it will rely on DMARC support to take necesary actions using SPF results as an input. -Disabling enforce\_early without enabling DMARC support will make SPF policies +Disabling `enforce_early` without enabling DMARC support will make SPF policies no-op and is considered insecure. ## Configuration directives @@ -35,49 +35,63 @@ check.spf { } ``` -**Syntax**: debug _boolean_
-**Default**: global directive value +### debug _boolean_ +Default: global directive value Enable verbose logging for check.spf. -**Syntax**: enforce\_early _boolean_
-**Default**: no +--- + +### enforce_early _boolean_ +Default: `no` Make policy decision on MAIL FROM stage (before the message body is received). This makes it impossible to apply DMARC override (see above). -**Syntax**: none\_action reject|quarantine|ignore
-**Default**: ignore +--- + +### none_action `reject` | `quarantine` | `ignore` +Default: `ignore` Action to take when SPF policy evaluates to a 'none' result. See [https://tools.ietf.org/html/rfc7208#section-2.6](https://tools.ietf.org/html/rfc7208#section-2.6) for meaning of SPF results. -**Syntax**: neutral\_action reject|quarantine|ignore
-**Default**: ignore +--- + +### neutral_action `reject` | `quarantine` | `ignore` +Default: `ignore` Action to take when SPF policy evaluates to a 'neutral' result. See [https://tools.ietf.org/html/rfc7208#section-2.6](https://tools.ietf.org/html/rfc7208#section-2.6) for meaning of SPF results. -**Syntax**: fail\_action reject|quarantine|ignore
-**Default**: quarantine +--- + +### fail_action `reject` | `quarantine` | `ignore` +Default: `quarantine` Action to take when SPF policy evaluates to a 'fail' result. -**Syntax**: softfail\_action reject|quarantine|ignore
-**Default**: ignore +--- + +### softfail_action `reject` | `quarantine` | `ignore` +Default: `ignore` Action to take when SPF policy evaluates to a 'softfail' result. -**Syntax**: permerr\_action reject|quarantine|ignore
-**Default**: reject +--- + +### permerr_action `reject` | `quarantine` | `ignore` +Default: `reject` Action to take when SPF policy evaluates to a 'permerror' result. -**Syntax**: temperr\_action reject|quarantine|ignore
-**Default**: reject +--- + +### temperr_action `reject` | `quarantine` | `ignore` +Default: `reject` Action to take when SPF policy evaluates to a 'temperror' result. diff --git a/docs/reference/config-syntax.md b/docs/reference/config-syntax.md index 506ff023..72e18d41 100644 --- a/docs/reference/config-syntax.md +++ b/docs/reference/config-syntax.md @@ -182,21 +182,15 @@ Also note that the following is not valid, unlike Duration values syntax: 32M5K ``` -# ADDRESS DEFINITIONS +## Address Definitions Maddy configuration uses URL-like syntax to specify network addresses. -- unix://file\_path - Unix domain socket. Relative paths are relative to runtime directory - (/run/maddy). +- `unix://file_path` – Unix domain socket. Relative paths are relative to runtime directory (`/run/maddy`). +- `tcp://ADDRESS:PORT` – TCP/IP socket. +- `tls://ADDRESS:PORT` – TCP/IP socket using TLS. -- tcp://ADDRESS:PORT - TCP/IP socket. - -- tls://ADDRESS:PORT - TCP/IP socket using TLS. - -# DUMMY MODULE +## Dummy Module No-op module. It doesn't need to be configured explicitly and can be referenced using "dummy" name. It can act as a delivery target or auth. diff --git a/docs/reference/endpoints/imap.md b/docs/reference/endpoints/imap.md index 41e4f2f3..86904941 100644 --- a/docs/reference/endpoints/imap.md +++ b/docs/reference/endpoints/imap.md @@ -27,11 +27,12 @@ imap tcp://0.0.0.0:143 tls://0.0.0.0:993 { } ``` -**Syntax**: tls _certificate\_path_ _key\_path_ { ... }
-**Default**: global directive value +### tls _certificate-path_ _key-path_ { ... } +Default: global directive value TLS certificate & key to use. Fine-tuning of other TLS properties is possible by specifying a configuration block and options inside it: + ``` tls cert.crt key.key { protocols tls1.2 tls1.3 @@ -40,36 +41,50 @@ tls cert.crt key.key { See [TLS configuration / Server](/reference/tls/#server-side) for details. -**Syntax**: io\_debug _boolean_
-**Default**: no +--- + +### io_debug _boolean_ +Default: `no` Write all commands and responses to stderr. -**Syntax**: io\_errors _boolean_
-**Default**: no +--- + +### io_errors _boolean_ +Default: `no` Log I/O errors. -**Syntax**: debug _boolean_
-**Default**: global directive value +--- + +### debug _boolean_ +Default: global directive value Enable verbose logging. -**Syntax**: insecure\_auth _boolean_
-**Default**: no (yes if TLS is disabled) +--- -**Syntax**: auth _module\_reference\_ +### insecure_auth _boolean_ +Default: `no` (`yes` if TLS is disabled) -Use the specified module for authentication. +--- + +### auth _module-reference_ **Required.** -**Syntax**: storage _module\_reference\_ +Use the specified module for authentication. -Use the specified module for message storage. +--- + +### storage _module-reference_ **Required.** -**Syntax**: storage\_map _module\_reference_
-**Default**: identity +Use the specified module for message storage. + +--- + +### storage_map _module-reference_ +Default: `identity` Use the specified table to map SASL usernames to storage account names. @@ -78,6 +93,7 @@ Before username is looked up, it is normalized using function defined by This directive is useful if you want users user@example.org and user@example.com to share the same storage account named "user". In this case, use + ``` storage_map email_localpart ``` @@ -88,6 +104,7 @@ authentication provider. It also does not affect how message delivery is handled, you should specify `delivery_map` in storage module to define how to map email addresses to storage accounts. E.g. + ``` storage.imapsql local_mailboxes { ... @@ -95,13 +112,17 @@ to storage accounts. E.g. } ``` -**Syntax**: storage\_map_normalize _function_
-**Default**: auto +--- + +### storage_map_normalize _function_ +Default: `auto` Same as `auth_map_normalize` but for `storage_map`. -**Syntax**: auth\_map_normalize _function_
-**Default**: auto +--- + +### auth_map_normalize _function_ +Default: `auto` Overrides global `auth_map_normalize` value for this endpoint. diff --git a/docs/reference/endpoints/openmetrics.md b/docs/reference/endpoints/openmetrics.md index df77665c..f455f716 100644 --- a/docs/reference/endpoints/openmetrics.md +++ b/docs/reference/endpoints/openmetrics.md @@ -4,6 +4,7 @@ Various server statistics are provided in OpenMetrics format by the "openmetrics" module. To enable it, add the following line to the server config: + ``` openmetrics tcp://127.0.0.1:9749 { } ``` diff --git a/docs/reference/endpoints/smtp.md b/docs/reference/endpoints/smtp.md index 6ddbba1f..6b412868 100644 --- a/docs/reference/endpoints/smtp.md +++ b/docs/reference/endpoints/smtp.md @@ -36,8 +36,8 @@ smtp tcp://0.0.0.0:25 { ## Configuration directives -**Syntax**: hostname _string_
-**Default**: global directive value +### hostname _string_ +Default: global directive value Server name to use in SMTP banner. @@ -45,11 +45,14 @@ Server name to use in SMTP banner. 220 example.org ESMTP Service Ready ``` -**Syntax**: tls _certificate\_path_ _key\_path_ { ... }
-**Default**: global directive value +--- + +### tls _certificate-path_ _key-path_ { ... } +Default: global directive value TLS certificate & key to use. Fine-tuning of other TLS properties is possible by specifying a configuration block and options inside it: + ``` tls cert.crt key.key { protocols tls1.2 tls1.3 @@ -58,94 +61,107 @@ tls cert.crt key.key { See [TLS configuration / Server](/reference/tls/#server-side) for details. +--- -**Syntax**: io\_debug _boolean_
-**Default**: no +### io_debug _boolean_ +Default: `no` Write all commands and responses to stderr. -**Syntax**: debug _boolean_
-**Default**: global directive value +--- + +### debug _boolean_ +Default: global directive value Enable verbose logging. -**Syntax**: insecure\_auth _boolean_
-**Default**: no (yes if TLS is disabled) +--- + +### insecure_auth _boolean_ +Default: `no` (`yes` if TLS is disabled) Allow plain-text authentication over unencrypted connections. Not recommended! -**Syntax**: read\_timeout _duration_
-**Default**: 10m +--- + +### read_timeout _duration_ +Default: `10m` I/O read timeout. -**Syntax**: write\_timeout _duration_
-**Default**: 1m +--- + +### write_timeout _duration_ +Default: `1m` I/O write timeout. -**Syntax**: max\_message\_size _size_
-**Default**: 32M +--- + +### max_message_size _size_ +Default: `32M` Limit the size of incoming messages to 'size'. -**Syntax**: max\_header\_size _size_
-**Default**: 1M +--- + +### max_header_size _size_ +Default: `1M` Limit the size of incoming message headers to 'size'. -**Syntax**: auth _module\_reference_
-**Default**: not specified +--- + +### auth _module-reference_ +Default: not specified Use the specified module for authentication. -**Syntax**: defer\_sender\_reject _boolean_
-**Default**: yes +--- + +### defer_sender_reject _boolean_ +Default: `yes` Apply sender-based checks and routing logic when first RCPT TO command is received. This allows maddy to log recipient address of the rejected message and also improves interoperability with (improperly implemented) clients that don't expect an error early in session. -**Syntax**: max\_logged\_rcpt\_errors _integer_
-**Default**: 5 +--- + +### max_logged_rcpt_errors _integer_ +Default: `5` Amount of RCPT-time errors that should be logged. Further errors will be handled silently. This is to prevent log flooding during email dictionary attacks (address probing). -**Syntax**: max\_received _integer_
-**Default**: 50 +--- + +### max_received _integer_ +Default: `50` Max. amount of Received header fields in the message header. If the incoming message has more fields than this number, it will be rejected with the permanent error 5.4.6 ("Routing loop detected"). -**Syntax**:
-buffer ram
-buffer fs _[path]_
-buffer auto _max\_size_ _[path]_
-**Default**: auto 1M StateDirectory/buffer +--- -Temporary storage to use for the body of accepted messages. +### buffer `ram`
buffer `fs` _path_
buffer `auto` _max-size_ _path_ +Default: `auto 1M StateDirectory/buffer` -- ram - -Store the body in RAM. - -- fs +Temporary storage to use for the body of accepted messages. -Write out the message to the FS and read it back as needed. +- `ram` – Store the body in RAM. +- `fs` – Write out the message to the FS and read it back as needed. _path_ can be omitted and defaults to StateDirectory/buffer. +- `auto` – Store message bodies smaller than `_max_size_` entirely in RAM, +otherwise write them out to the FS. _path_ can be omitted and defaults to `StateDirectory/buffer`. -- auto +--- -Store message bodies smaller than _max\_size_ entirely in RAM, otherwise write -them out to the FS. -_path_ can be omitted and defaults to StateDirectory/buffer. - -**Syntax**: smtp\_max\_line\_length _integer_
-**Default**: 4000 +### smtp_max_line_length _integer_ +Default: `4000` The maximum line length allowed in the SMTP input stream. If client sends a longer line - connection will be closed and message (if any) will be rejected @@ -157,26 +173,31 @@ to handle longer lines correctly but some senders may produce them. Unless BDAT extension is used by the sender, this limitation also applies to the message body. -**Syntax**: dmarc _boolean_
-**Default**: yes +--- + +### dmarc _boolean_ +Default: `yes` Enforce sender's DMARC policy. Due to implementation limitations, it is not a check module. -**NOTE**: Report generation is not implemented now. +**Note**: Report generation is not implemented now. -**NOTE**: DMARC needs SPF and DKIM checks to function correctly. +**Note**: DMARC needs SPF and DKIM checks to function correctly. Without these, DMARC check will not run. +--- + ## Rate & concurrency limiting -**Syntax**: limits _config block_
-**Default**: no limits +### limits { ... } +Default: no limits This allows configuring a set of message flow restrictions including max. concurrency and rate per-endpoint, per-source, per-destination. Limits are specified as directives inside the block: + ``` limits { all rate 20 @@ -186,16 +207,14 @@ limits { Supported limits: -- Rate limit - -**Syntax**: _scope_ rate _burst_ _[period]_
-Restrict the amount of messages processed in _period_ to _burst_ messages. -If period is not specified, 1 second is used. +### _scope_ rate _burst_ _period_ -- Concurrency limit +Rate limit. Restrict the amount of messages processed in _period_ to +_burst_ messages. If period is not specified, 1 second is used. -**Syntax**: _scope_ concurrency _max_
-Restrict the amount of messages processed in parallel to _max\_. +### _scope_ concurrency _max_ +Concurrency limit. Restrict the amount of messages processed in parallel +to _max_. For each supported limitation, _scope_ determines whether it should be applied for all messages ("all"), per-sender IP ("ip"), per-sender domain ("source") or @@ -212,6 +231,7 @@ on outbound messages, do so using 'limits' directive for the 'table.remote' modu It is possible to share limit counters between multiple endpoints (or any other modules). To do so define a top-level configuration block for module "limits" and reference it where needed using standard & syntax. E.g. + ``` limits inbound_limits { all rate 20 @@ -227,6 +247,7 @@ submission tls://0.0.0.0:465 { ... } ``` + Using an "all rate" restriction in such way means that no more than 20 messages can enter the server through both endpoints in one second. @@ -259,7 +280,6 @@ lmtp unix://lmtp.sock { ## Limitations of LMTP implementation - Can't be used with TCP. - - Delivery to 'sql' module storage is always atomic, either all recipients will succeed or none of them will. diff --git a/docs/reference/global-config.md b/docs/reference/global-config.md index db477bf5..db0ec1a3 100644 --- a/docs/reference/global-config.md +++ b/docs/reference/global-config.md @@ -5,26 +5,32 @@ configuration blocks and they are applied to all modules. Some directives can be overridden on per-module basis (e.g. hostname). -**Syntax**: state\_dir _path_
-**Default**: /var/lib/maddy +### state_dir _path_ +Default: `/var/lib/maddy` The path to the state directory. This directory will be used to store all persistent data and should be writable. -**Syntax**: runtime\_dir _path_
-**Default**: /run/maddy +--- + +### runtime_dir _path_ +Default: `/run/maddy` The path to the runtime directory. Used for Unix sockets and other temporary objects. Should be writable. -**Syntax**: hostname _domain_
-**Default**: not specified +--- + +### hostname _domain_ +Default: not specified Internet hostname of this mail server. Typicall FQDN is used. It is recommended to make sure domain specified here resolved to the public IP of the server. -**Syntax**: auth\_map _module\_reference_
-**Default**: identity +--- + +### auth_map _module-reference_ +Default: `identity` Use the specified table to translate SASL usernames before passing it to the authentication provider. @@ -38,9 +44,11 @@ should also use `storage_map` in IMAP config block to handle this. This directive is useful if used authentication provider does not support using emails as usernames but you still want users to have separate mailboxes on separate domains. In this case, use it with `email_localpart` table: + ``` auth_map email_localpart ``` + With this configuration, `user@example.org` and `user@example.com` will use `user` credentials when authenticating, but will access `user@example.org` and `user@example.com` mailboxes correspondingly. If you want to also accept @@ -49,17 +57,22 @@ With this configuration, `user@example.org` and `user@example.com` will use If you want `user@example.org` and `user@example.com` to have the same mailbox, also set `storage_map` in IMAP config block to use `email_localpart` (or `email_localpart_optional` if you want to also accept just "user"): + ``` storage_map email_localpart ``` + In this case you will need to create storage accounts without domain part in the name: + ``` maddy imap-acct create user # instead of user@example.org ``` -**Syntax**: auth\_map_normalize _function_
-**Default**: auto +--- + +### auth_map_normalize _function_ +Default: `auto` Normalization function to apply to SASL usernames before mapping them to storage accounts. @@ -74,17 +87,18 @@ Available options: - `casefold` Convert to lower case - `noop` Nothing -**Syntax**: autogenerated\_msg\_domain _domain_
-**Default**: not specified +--- + +### autogenerated_msg_domain _domain_ +Default: not specified Domain that is used in From field for auto-generated messages (such as Delivery Status Notifications). -**Syntax**:
-tls file _cert\_file_ _pkey\_file_
-tls _module reference_
-tls off
-**Default**: not specified +--- + +### tls `file` _cert-file_ _pkey-file_ | _module-reference_ | `off` +Default: not specified Default TLS certificate to use for all endpoints. @@ -96,40 +110,32 @@ version. See maddy-tls(5) for details. maddy uses reasonable cipher suites and TLS versions by default so you generally don't have to worry about it. -**Syntax**: tls\_client { ... }
-**Default**: not specified +--- + +### tls_client { ... } +Default: not specified This is optional block that specifies various TLS-related options to use when making outbound connections. See TLS client configuration for details on directives that can be used in it. maddy uses reasonable cipher suites and TLS versions by default so you generally don't have to worry about it. -**Syntax**:
-log _targets..._
-log off
-**Default**: stderr +--- + +### log _targets..._ | `off` +Default: `stderr` Write log to one of more "targets". The target can be one or the following: -- stderr - - Write logs to stderr. - -- stderr\_ts - - Write logs to stderr with timestamps. - -- syslog - - Send logs to the local syslog daemon. - -- _file path_ - - Write (append) logs to file. +- `stderr` – Write logs to stderr. +- `stderr_ts` – Write logs to stderr with timestamps. +- `syslog` – Send logs to the local syslog daemon. +- _file path_ – Write (append) logs to file. Example: + ``` log syslog /var/log/maddy.log ``` @@ -137,8 +143,10 @@ log syslog /var/log/maddy.log **Note:** Maddy does not perform log files rotation, this is the job of the logrotate daemon. Send SIGUSR1 to maddy process to make it reopen log files. -**Syntax**: debug _boolean_
-**Default**: no +--- + +### debug _boolean_ +Default: `no` Enable verbose logging for all modules. You don't need that unless you are reporting a bug. diff --git a/docs/reference/modifiers/dkim.md b/docs/reference/modifiers/dkim.md index 44e212ee..5672a7d4 100644 --- a/docs/reference/modifiers/dkim.md +++ b/docs/reference/modifiers/dkim.md @@ -13,10 +13,10 @@ key for the first domain will be used. If domain in envelope sender does not match any of loaded keys, message will not be signed. Additionally, for each messages From header is checked to match MAIL FROM and authorization identity (username sender is logged in as). -This can be controlled using require\_sender\_match directive. +This can be controlled using require_sender_match directive. Generated private keys are stored in unencrypted PKCS#8 format -in state_directory/dkim_keys (/var/lib/maddy/dkim_keys). +in state_directory/dkim_keys (`/var/lib/maddy/dkim_keys`). In the same directory .dns files are generated that contain public key for each domain formatted in the form of a DNS record. @@ -24,6 +24,7 @@ public key for each domain formatted in the form of a DNS record. domains and selector can be specified in arguments, so actual modify.dkim use can be shortened to the following: + ``` modify { dkim example.org selector @@ -48,34 +49,39 @@ modify.dkim { } ``` -**Syntax**: debug _boolean_
-**Default**: global directive value +### debug _boolean_ +Default: global directive value Enable verbose logging. -**Syntax**: domains _string list_
-**Default**: not specified +--- + +### domains _string-list_ +**Required**.
+Default: not specified -**REQUIRED.** ADministrative Management Domains (ADMDs) taking responsibility for messages. Should be specified either as a directive or as an argument. -**Syntax**: selector _string_
-**Default**: not specified +--- -**REQUIRED.** +### selector _string_ +**Required**.
+Default: not specified Identifier of used key within the ADMD. Should be specified either as a directive or as an argument. -**Syntax**: key\_path _string_
-**Default**: dkim\_keys/{domain}\\_{selector}.key +--- + +### key_path _string_ +Default: `dkim_keys/{domain}_{selector}.key` Path to private key. It should be in PKCS#8 format wrapped in PAM encoding. If key does not exist, it will be generated using algorithm specified -in newkey\_algo. +in newkey_algo. Placeholders '{domain}' and '{selector}' will be replaced with corresponding values from domain and selector directives. @@ -84,16 +90,19 @@ Additionally, keys in PKCS#1 ("RSA PRIVATE KEY") and RFC 5915 ("EC PRIVATE KEY") can be read by modify.dkim. Note, however that newly generated keys are always in PKCS#8. -**Syntax**: oversign\_fields _list..._
-**Default**: see below +--- + +### oversign_fields _list..._ +Default: see below Header fields that should be signed n+1 times where n is times they are present in the message. This makes it impossible to replace field value by prepending another field with the same name to the message. -Fields specified here don't have to be also specified in sign\_fields. +Fields specified here don't have to be also specified in `sign_fields`. Default set of oversigned fields: + - Subject - To - From @@ -107,14 +116,17 @@ Default set of oversigned fields: - Autocrypt - Openpgp -**Syntax**: sign\_fields _list..._
-**Default**: see below +--- + +### sign_fields _list..._ +Default: see below Header fields that should be signed n+1 times where n is times they are present in the message. For these fields, additional values can be prepended by intermediate relays, but existing values can't be changed. Default set of signed fields: + - List-Id - List-Help - List-Unsubscribe @@ -128,72 +140,86 @@ Default set of signed fields: - Resent-From - Resent-Cc -**Syntax**: header\_canon relaxed|simple
-**Default**: relaxed +--- + +### header_canon `relaxed` | `simple` +Default: `relaxed` -Canonicalization algorithm to use for header fields. With 'relaxed', whitespace within -fields can be modified without breaking the signature, with 'simple' no +Canonicalization algorithm to use for header fields. With `relaxed`, whitespace within +fields can be modified without breaking the signature, with `simple` no modifications are allowed. -**Syntax**: body\_canon relaxed|simple
-**Default**: relaxed +--- -Canonicalization algorithm to use for message body. With 'relaxed', whitespace within -can be modified without breaking the signature, with 'simple' no +### body_canon `relaxed` | `simple` +Default: `relaxed` + +Canonicalization algorithm to use for message body. With `relaxed`, whitespace within +can be modified without breaking the signature, with `simple` no modifications are allowed. -**Syntax**: sig\_expiry _duration_
-**Default**: 120h +--- + +### sig_expiry _duration_ +Default: `120h` Time for which signature should be considered valid. Mainly used to prevent unauthorized resending of old messages. -**Syntax**: hash _hash_
-**Default**: sha256 +--- + +### hash _hash_ +Default: `sha256` Hash algorithm to use when computing body hash. sha256 is the only supported algorithm now. -**Syntax**: newkey\_algo rsa4096|rsa2048|ed25519
-**Default**: rsa2048 +--- + +### newkey_algo `rsa4096` | `rsa2048` | `ed25519` +Default: `rsa2048` Algorithm to use when generating a new key. -Currently ed25519 is NOT supported by most platforms. +Currently ed25519 is **not** supported by most platforms. -**Syntax**: require\_sender\_match _ids..._
-**Default**: envelope auth +--- + +### require_sender_match _ids..._ +Default: `envelope auth` Require specified identifiers to match From header field and key domain, otherwise - don't sign the message. If From field contains multiple addresses, message will not be -signed unless allow\_multiple\_from is also specified. In that +signed unless `allow_multiple_from` is also specified. In that case only first address will be compared. Matching is done in a case-insensitive way. Valid values: -- off - Disable check, always sign. -- envelope - Require MAIL FROM address to match From header. -- auth - If authorization identity contains @ - then require it to + +- `off` – Disable check, always sign. +- `envelope` – Require MAIL FROM address to match From header. +- `auth` – If authorization identity contains @ - then require it to fully match From header. Otherwise, check only local-part (username). -**Syntax**: allow\_multiple\_from _boolean_
-**Default**: no +--- + +### allow_multiple_from _boolean_ +Default: `no` Allow multiple addresses in From header field for purposes of -require\_sender\_match checks. Only first address will be checked, however. +`require_sender_match` checks. Only first address will be checked, however. + +--- -**Syntax**: sign\_subdomains _boolean_
-**Default**: no +### sign_subdomains _boolean_ +Default: `no` Sign emails from subdomains using a top domain key. -Allows only one domain to be specified (can be worked around by using modify.dkim +Allows only one domain to be specified (can be worked around by using `modify.dkim` multiple times). diff --git a/docs/reference/modifiers/envelope.md b/docs/reference/modifiers/envelope.md index 6615a71b..0e101cf6 100644 --- a/docs/reference/modifiers/envelope.md +++ b/docs/reference/modifiers/envelope.md @@ -1,6 +1,6 @@ # Envelope sender / recipient rewriting -'replace\_sender' and 'replace\_rcpt' modules replace SMTP envelope addresses +`replace_sender` and `replace_rcpt` modules replace SMTP envelope addresses based on the mapping defined by the table module (maddy-tables(5)). It is possible to specify 1:N mappings. This allows, for example, implementing mailing lists. @@ -17,6 +17,7 @@ multiple times to a single recipient. However, used delivery target can apply such deduplication (imapsql storage does it). Definition: + ``` replace_rcpt [table arguments] { [extended table config] @@ -27,6 +28,7 @@ replace_sender
[table arguments] { ``` Use examples: + ``` modify { replace_rcpt file /etc/maddy/aliases @@ -40,6 +42,7 @@ modify { ``` Possible contents of /etc/maddy/aliases in the example above: + ``` # Replace 'cat' with any domain to 'dog'. # E.g. cat@example.net -> dog@example.net diff --git a/docs/reference/smtp-pipeline.md b/docs/reference/smtp-pipeline.md index 728bab1e..a41deb80 100644 --- a/docs/reference/smtp-pipeline.md +++ b/docs/reference/smtp-pipeline.md @@ -16,40 +16,41 @@ The pipeline is responsible for message. Message handling flow is as follows: -- Execute checks referenced in top-level 'check' blocks (if any) +- Execute checks referenced in top-level `check` blocks (if any) -- Execute modifiers referenced in top-level 'modify' blocks (if any) +- Execute modifiers referenced in top-level `modify` blocks (if any) -- If there are 'source' blocks - select one that matches message sender (as - specified in MAIL FROM). If there are no 'source' blocks - entire - configuration is assumed to be the 'default\_source' block. +- If there are `source` blocks - select one that matches message sender (as + specified in MAIL FROM). If there are no `source` blocks - entire + configuration is assumed to be the `default_source` block. - Execute checks referenced in 'check' blocks inside selected 'source' block (if any). -- Execute modifiers referenced in 'modify' blocks inside selected 'source' +- Execute modifiers referenced in `modify` blocks inside selected `source` block (if any). Then, for each recipient: -- Select 'destination' block that matches it. If there are - no 'destination' blocks - entire used 'source' block is interpreted as if it - was a 'default\_destination' block. +- Select `destination` block that matches it. If there are + no `destination` blocks - entire used `source` block is interpreted as if it + was a `default_destination` block. -- Execute checks referenced in 'check' block inside selected 'destination' block +- Execute checks referenced in `check` block inside selected `destination` block (if any). -- Execute modifiers referenced in 'modify' block inside selected 'destination' +- Execute modifiers referenced in `modify` block inside selected `destination` block (if any). -- If used block contains 'reject' directive - reject the recipient with +- If used block contains `reject` directive - reject the recipient with specified SMTP status code. -- If used block contains 'deliver\_to' directive - pass the message to the +- If used block contains `deliver_to` directive - pass the message to the specified target module. Only recipients that are handled by used block are visible to the target. -Each recipient is handled only by a single 'destination' block, in case of -overlapping 'destination' - first one takes priority. +Each recipient is handled only by a single `destination` block, in case of +overlapping `destination` - first one takes priority. + ``` destination example.org { deliver_to targetA @@ -58,30 +59,34 @@ destination example.org { # ambiguous and thus not allowed deliver_to targetB } ``` -Same goes for 'source' blocks, each message is handled only by a single block. -Each recipient block should contain at least one 'deliver\_to' directive or -'reject' directive. If 'destination' blocks are used, then -'default\_destination' block should also be used to specify behavior for -unmatched recipients. Same goes for source blocks, 'default\_source' should be -used if 'source' is used. +Same goes for `source` blocks, each message is handled only by a single block. + +Each recipient block should contain at least one `deliver_to` directive or +`reject` directive. If `destination` blocks are used, then +`default_destination` block should also be used to specify behavior for +unmatched recipients. Same goes for source blocks, `default_source` should be +used if `source` is used. That is, pipeline configuration should explicitly specify behavior for each possible sender/recipient combination. -Additionally, directives that specify final handling decision ('deliver\_to', -'reject') can't be used at the same level as source/destination rules. +Additionally, directives that specify final handling decision (`deliver_to`, +`reject`) can't be used at the same level as source/destination rules. Consider example: + ``` destination example.org { deliver_to local_mboxes } reject ``` -It is not obvious whether 'reject' applies to all recipients or + +It is not obvious whether `reject` applies to all recipients or just for non-example.org ones, hence this is not allowed. Complete configuration example using all of the mentioned directives: + ``` check { # Run a check to make sure source SMTP server identification @@ -114,8 +119,9 @@ default_source { ## Directives -**Syntax**: check _block name_ { ... }
-**Context**: pipeline configuration, source block, destination block + +### check _block name_ { ... } +Context: pipeline configuration, source block, destination block List of the module references for checks that should be executed on messages handled by block where 'check' is placed in. @@ -126,6 +132,7 @@ be rejected for all recipients which is not what you usually want when using such configurations. Example: + ``` check { # Reference implicitly defined default configuration for check. @@ -141,6 +148,7 @@ check { It is also possible to define the block of checks at the top level as "checks" module and reference it using & syntax. Example: + ``` checks inbound_checks { spf @@ -154,9 +162,11 @@ checks inbound_checks { } ``` -**Syntax**: modify { ... }
-**Default**: not specified
-**Context**: pipeline configuration, source block, destination block +--- + +### modify { ... } +Default: not specified
+Context: pipeline configuration, source block, destination block List of the module references for modifiers that should be executed on messages handled by block where 'modify' is placed in. @@ -177,6 +187,7 @@ affect the message header will affect it for all recipients. It is also possible to define the block of modifiers at the top level as "modiifers" module and reference it using & syntax. Example: + ``` modifiers local_modifiers { replace_rcpt file /etc/maddy/aliases @@ -189,12 +200,10 @@ modifiers local_modifiers { } ``` -**Syntax**:
-reject _smtp\_code_ _smtp\_enhanced\_code_ _error\_description_
-reject _smtp\_code_ _smtp\_enhanced\_code_
-reject _smtp\_code_
-reject
-**Context**: destination block +--- + +### reject _smtp-code_ _smtp-enhanced-code_ _error-description_
reject _smtp-code_ _smtp-enhanced-code_
reject _smtp-code_
reject +Context: destination block Messages handled by the configuration block with this directive will be rejected with the specified SMTP error. @@ -203,30 +212,36 @@ If you aren't sure which codes to use, use 541 and 5.4.0 with your message or just leave all arguments out, the error description will say "message is rejected due to policy reasons" which is usually what you want to mean. -'reject' can't be used in the same block with 'deliver\_to' or -'destination/source' directives. +`reject` can't be used in the same block with `deliver_to` or +`destination`/`source` directives. Example: + ``` reject 541 5.4.0 "We don't like example.org, go away" ``` -**Syntax**: deliver\_to _target-config-block_
-**Context**: pipeline configuration, source block, destination block +--- + +### deliver_to _target-config-block_ +Context: pipeline configuration, source block, destination block Deliver the message to the referenced delivery target. What happens next is -defined solely by used target. If deliver\_to is used inside 'destination' +defined solely by used target. If `deliver_to` is used inside `destination` block, only matching recipients will be passed to the target. -**Syntax**: source\_in _table reference_ { ... }
-**Context**: pipeline configuration +--- + +### source_in _table-reference_ { ... } +Context: pipeline configuration Handle messages with envelope senders present in the specified table in accordance with the specified configuration block. -Takes precedence over all 'sender' directives. +Takes precedence over all `sender` directives. Example: + ``` source_in file /etc/maddy/banned_addrs { reject 550 5.7.0 "You are not welcome here" @@ -237,10 +252,12 @@ source example.org { ... ``` -See 'destination\_in' documentation for note about table configuration. +See `destination_in` documentation for note about table configuration. -**Syntax**: source _rules..._ { ... }
-**Context**: pipeline configuration +--- + +### source _rules..._ { ... } +Context: pipeline configuration Handle messages with MAIL FROM value (sender address) matching any of the rules in accordance with the specified configuration block. @@ -249,6 +266,7 @@ in accordance with the specified configuration block. 'rules', first one takes priority. Matching is case-insensitive. Example: + ``` # All messages coming from example.org domain will be delivered # to local_mailboxes. @@ -261,8 +279,10 @@ default_source { } ``` -**Syntax**: reroute { ... }
-**Context**: pipeline configuration, source block, destination block +--- + +### reroute { ... } +Context: pipeline configuration, source block, destination block This directive allows to make message routing decisions based on the result of modifiers. The block can contain all pipeline directives and they @@ -271,6 +291,7 @@ will use the final recipient and sender values (e.g. after all modifiers are applied). Here is the concrete example how it can be useful: + ``` destination example.org { modify { @@ -288,15 +309,17 @@ destination example.org { ``` This configuration allows to specify alias local addresses to remote ones -without being an open relay, since remote\_queue can be used only if remote +without being an open relay, since remote_queue can be used only if remote address was introduced as a result of rewrite of local address. -**WARNING**: If you have DMARC enabled (default), results generated by SPF +**Warning**: If you have DMARC enabled (default), results generated by SPF and DKIM checks inside a reroute block **will not** be considered in DMARC evaluation. -**Syntax**: destination\_in _table reference_ { ... }
-**Context**: pipeline configuration, source block +--- + +### destination_in _table-reference_ { ... } +Context: pipeline configuration, source block Handle messages with envelope recipients present in the specified table in accordance with the specified configuration block. @@ -304,6 +327,7 @@ accordance with the specified configuration block. Takes precedence over all 'destination' directives. Example: + ``` destination_in file /etc/maddy/remote_addrs { deliver_to smtp tcp://10.0.0.7:25 @@ -316,6 +340,7 @@ destination example.com { Note that due to the syntax restrictions, it is not possible to specify extended configuration for table module. E.g. this is not valid: + ``` destination_in sql_table { dsn ... @@ -327,6 +352,7 @@ destination_in sql_table { In this case, configuration should be specified separately and be referneced using '&' syntax: + ``` table.sql_table remote_addrs { dsn ... @@ -340,8 +366,10 @@ whatever { } ``` -**Syntax**: destination _rule..._ { ... }
-**Context**: pipeline configuration, source block +--- + +### destination _rule..._ { ... } +Context: pipeline configuration, source block Handle messages with RCPT TO value (recipient address) matching any of the rules in accordance with the specified configuration block. @@ -354,6 +382,7 @@ they have recipients matched by multiple blocks. Each block will see the message only with recipients matched by its rules. Example: + ``` # Messages with recipients at example.com domain will be # delivered to local_mailboxes target. @@ -370,9 +399,10 @@ default_destination { ## Reusable pipeline snippets (msgpipeline module) The message pipeline can be used independently of the SMTP module in other -contexts that require a delivery target via "msgpipeline" module. +contexts that require a delivery target via `msgpipeline` module. Example: + ``` msgpipeline local_routing { destination whatever.com { diff --git a/docs/reference/storage/imapsql.md b/docs/reference/storage/imapsql.md index 871be614..f1abbb37 100644 --- a/docs/reference/storage/imapsql.md +++ b/docs/reference/storage/imapsql.md @@ -3,7 +3,7 @@ The imapsql module implements database for IMAP index and message metadata using SQL-based relational database. -Message contents are stored in an "blob store" defined by msg\_store +Message contents are stored in an "blob store" defined by msg_store directive. By default this is a file system directory under /var/lib/maddy. Supported RDBMS: @@ -25,7 +25,7 @@ storage.imapsql { imapsql module also can be used as a lookup table. It returns empty string values for existing usernames. This might be useful -with destination\_in directive e.g. to implement catch-all +with `destination_in` directive e.g. to implement catch-all addresses (this is a bad idea to do so, this is just an example): ``` destination_in &local_mailboxes { @@ -46,20 +46,20 @@ Specify the driver and DSN. ## Configuration directives -**Syntax**: driver _string_
-**Default**: not specified - -REQUIRED. +### driver _string_ +**Required.**
+Default: not specified Use a specified driver to communicate with the database. Supported values: sqlite3, postgres. Should be specified either via an argument or via this directive. -**Syntax**: dsn _string_
-**Default**: not specified +--- -REQUIRED. +### dsn _string_ +**Required.**
+Default: not specified Data Source Name, the driver-specific value that specifies the database to use. @@ -68,118 +68,141 @@ For PostgreSQL: [https://godoc.org/github.com/lib/pq#hdr-Connection\_String\_Par Should be specified either via an argument or via this directive. -**Syntax**: msg\_store _store_
-**Default**: fs messages/ +--- + +### msg_store _store_ +Default: `fs messages/` Module to use for message bodies storage. See "Blob storage" section for what you can use here. -**Syntax**:
-compression off
-compression _algorithm_
-compression _algorithm_ _level_
-**Default**: off +--- + +### compression `off`
compression _algorithm_
compression _algorithm_ _level_ +Default: `off` Apply compression to message contents. -Supported algorithms: lz4, zstd. +Supported algorithms: `lz4`, `zstd`. + +--- -**Syntax**: appendlimit _size_
-**Default**: 32M +### appendlimit _size_ +Default: `32M` Don't allow users to add new messages larger than 'size'. This does not affect messages added when using module as a delivery target. -Use 'max\_message\_size' directive in SMTP endpoint module to restrict it too. +Use `max_message_size` directive in SMTP endpoint module to restrict it too. -**Syntax**: debug _boolean_
-**Default**: global directive value +--- + +### debug _boolean_ +Default: global directive value Enable verbose logging. -**Syntax**: junk\_mailbox _name_
-**Default**: Junk +--- + +### junk_mailbox _name_ +Default: `Junk` The folder to put quarantined messages in. Thishis setting is not used if user does have a folder with "Junk" special-use attribute. -**Syntax**: disable\_recent _boolean_
-*Default: true +--- + +### disable_recent _boolean_ +Default: `true` Disable RFC 3501-conforming handling of \Recent flag. This significantly improves storage performance when SQLite3 or CockroackDB is used at the cost of confusing clients that use this flag. -**Syntax**: sqlite\_cache\_size _integer_
-**Default**: defined by SQLite +--- + +### sqlite_cache_size _integer_ +Default: defined by SQLite SQLite page cache size. If positive - specifies amount of pages (1 page - 4 KiB) to keep in cache. If negative - specifies approximate upper bound of cache size in KiB. -**Syntax**: sqlite\_busy\_timeout _integer_
-**Default**: 5000000 +--- + +### sqlite_busy_timeout _integer_ +Default: `5000000` SQLite-specific performance tuning option. Amount of milliseconds to wait before giving up on DB lock. -**Syntax**: imap\_filter { ... }
-**Default**: not set +--- + +### imap_filter { ... } +Default: not set Specifies IMAP filters to apply for messages delivered from SMTP pipeline. Ex. + ``` imap_filter { command /etc/maddy/sieve.sh {account_name} } ``` -**Syntax:** delivery\_map **table**
-**Default:** identity +--- + +### delivery_map _table_ +Default: `identity` Use specified table module to map recipient addresses from incoming messages to mailbox names. -Normalization algorithm specified in delivery\_normalize is appied before -delivery\_map. +Normalization algorithm specified in `delivery_normalize` is appied before +`delivery_map`. + +--- -**Syntax:** delivery\_normalize _name_
-**Default:** precis\_casefold\_email +### delivery_normalize _name_ +Default: `precis_casefold_email` Normalization function to apply to email addresses before mapping them to mailboxes. -See auth\_normalize. +See `auth_normalize`. -**Syntax**: auth\_map **table**
-**Default**: identity +--- -**DEPRECATED:** Use `storage_map` in imap config instead. +### auth_map _table_ +**Deprecated:** Use `storage_map` in imap config instead.
+Default: `identity` Use specified table module to map authentication usernames to mailbox names. -Normalization algorithm specified in auth\_normalize is applied before -auth\_map. +Normalization algorithm specified in auth_normalize is applied before +auth_map. -**Syntax**: auth\_normalize _name_
-**Default**: precis\_casefold\_email +--- -**DEPRECATED:** Use `storage_map_normalize` in imap config instead. +### auth_normalize _name_ +**Deprecated:** Use `storage_map_normalize` in imap config instead.
+**Default**: `precis_casefold_email` Normalization function to apply to authentication usernames before mapping them to mailboxes. Available options: -- precis\_casefold\_email PRECIS UsernameCaseMapped profile + U-labels form for domain -- precis\_casefold PRECIS UsernameCaseMapped profile for the entire string -- precis\_email PRECIS UsernameCasePreserved profile + U-labels form for domain -- precis PRECIS UsernameCasePreserved profile for the entire string -- casefold Convert to lower case -- noop Nothing + +- `precis_casefold_email` PRECIS UsernameCaseMapped profile + U-labels form for domain +- `precis_casefold` PRECIS UsernameCaseMapped profile for the entire string +- `precis_email` PRECIS UsernameCasePreserved profile + U-labels form for domain +- `precis` PRECIS UsernameCasePreserved profile for the entire string +- `casefold` Convert to lower case +- `noop` Nothing Note: On message delivery, recipient address is unconditionally normalized -using precis\_casefold\_email function. +using `precis_casefold_email` function. diff --git a/docs/reference/table/chain.md b/docs/reference/table/chain.md index 12ef3be0..1cbc24c1 100644 --- a/docs/reference/table/chain.md +++ b/docs/reference/table/chain.md @@ -16,12 +16,14 @@ in /etc/maddy/emails list. ## Configuration directives -**Syntax**: step _table\_ +### step _table_ Adds a table module to the chain. If input value is not in the table (e.g. file) - return "not exists" error. -**Syntax**: optional\_step _table\_ +--- + +### optional_step _table_ Same as step but if input value is not in the table - it is passed to the next step without changes. @@ -29,6 +31,7 @@ next step without changes. Example: Something like this can be used to map emails to usernames after translating them via aliases map: + ``` table.chain { optional_step file /etc/maddy/aliases diff --git a/docs/reference/table/email_localpart.md b/docs/reference/table/email_localpart.md index a5fc81f2..19b90f19 100644 --- a/docs/reference/table/email_localpart.md +++ b/docs/reference/table/email_localpart.md @@ -1,11 +1,12 @@ # Email local part -The module 'table.email\_localpart' extracts and unescapes local ("username") part +The module `table.email_localpart` extracts and unescapes local ("username") part of the email address. E.g. -test@example.org => test -"test @ a"@example.org => test @ a + +* `test@example.org` => `test` +* `"test @ a"@example.org` => `test @ a` Mappings for invalid emails are not defined (will be treated as non-existing values). diff --git a/docs/reference/table/email_with_domains.md b/docs/reference/table/email_with_domains.md index 175e4511..c9a56b68 100644 --- a/docs/reference/table/email_with_domains.md +++ b/docs/reference/table/email_with_domains.md @@ -1,6 +1,6 @@ # Email with domain -The table module 'table.email\_with\_domain' appends one or more +The table module `table.email_with_domain` appends one or more domains (allowing 1:N expansion) to the specified value. ``` @@ -9,6 +9,7 @@ table.email_with_domains DOMAIN DOMAIN... { } It can be used to implement domain-level expansion for aliases if used together with `table.chain`. Example: + ``` modify { replace_rcpt chain { @@ -17,17 +18,20 @@ modify { } } ``` + This configuration will alias `anything@anydomain` to `anything@example.org` and `anything@example.com`. It is also useful with `authorize_sender` to authorize sending using multiple addresses under different domains if non-email usernames are used for authentication: + ``` check.authorize_sender { ... user_to_email email_with_domain example.org example.com } ``` + This way, user authenticated as `user` will be allowed to use `user@example.org` or `user@example.com` as a sender address. diff --git a/docs/reference/table/regexp.md b/docs/reference/table/regexp.md index 9a39b6fd..39e873db 100644 --- a/docs/reference/table/regexp.md +++ b/docs/reference/table/regexp.md @@ -18,8 +18,9 @@ table.regexp [replacement] { Note that [replacement] is optional. If it is not included - table.regexp will return the original string, therefore acting as a regexp match check. -This can be useful in combination in destination\_in for +This can be useful in combination in `destination_in` for advanced matching: + ``` destination_in regexp ".*-bounce+.*@example.com" { ... @@ -28,27 +29,31 @@ destination_in regexp ".*-bounce+.*@example.com" { ## Configuration directives -***Syntax***: full\_match _boolean_
-***Default***: yes +### full_match _boolean_ +Default: `yes` Whether to implicitly add start/end anchors to the regular expression. -That is, if 'full\_match' is yes, then the provided regular expression should -match the whole string. With no - partial match is enough. +That is, if `full_match` is `yes`, then the provided regular expression should +match the whole string. With `no` - partial match is enough. + +--- -***Syntax***: case\_insensitive _boolean_
-***Default***: yes +### case_insensitive _boolean_ +Default: `yes` Whether to make matching case-insensitive. -***Syntax***: expand\_placeholders _boolean_
-***Default***: yes +--- + +### expand_placeholders _boolean_ +Default: `yes` Replace '$name' and '${name}' in the replacement string with contents of corresponding capture groups from the match. To insert a literal $ in the output, use $$ in the template. -# Identity table (table.identity) +## Identity table (table.identity) The module 'identity' is a table module that just returns the key looked up. diff --git a/docs/reference/table/sql_query.md b/docs/reference/table/sql_query.md index c6eb3548..9b3b9ebf 100644 --- a/docs/reference/table/sql_query.md +++ b/docs/reference/table/sql_query.md @@ -1,8 +1,9 @@ # SQL query mapping -The table.sql\_query module implements table interface using SQL queries. +The table.sql_query module implements table interface using SQL queries. Definition: + ``` table.sql_query { driver @@ -19,6 +20,7 @@ table.sql_query { ``` Usage example: + ``` # Resolve SMTP address aliases using PostgreSQL DB. modify { @@ -32,22 +34,26 @@ modify { ## Configuration directives -***Syntax***: driver _driver name_
-***REQUIRED*** +### driver _driver name_ +**Required.** Driver to use to access the database. -Supported drivers: postgres, sqlite3 (if compiled with C support) +Supported drivers: `postgres`, `sqlite3` (if compiled with C support) -***Syntax***: dsn _data source name_
-***REQUIRED*** +--- + +### dsn _data source name_ +**Required.** Data Source Name to pass to the driver. For SQLite3 this is just a path to DB file. For Postgres, see [https://pkg.go.dev/github.com/lib/pq?tab=doc#hdr-Connection\_String\_Parameters](https://pkg.go.dev/github.com/lib/pq?tab=doc#hdr-Connection\_String\_Parameters) -***Syntax***: lookup _query_
-***REQUIRED*** +--- + +### lookup _query_ +**Required.** SQL query to use to obtain the lookup result. @@ -58,12 +64,15 @@ rows, they will be ignored. If there are more columns, lookup will fail. If there are no rows, lookup returns "no results". If there are any error - lookup will fail. -***Syntax***: init _queries..._
-***Default***: empty +--- + +### init _queries..._ +Default: empty List of queries to execute on initialization. Can be used to configure RDBMS. Example, to improve SQLite3 performance: + ``` table.sql_query { driver sqlite3 @@ -74,8 +83,10 @@ table.sql_query { } ``` -**Syntax:** named\_args _boolean_
-**Default:** yes +--- + +### named_args _boolean_ +Default: `yes` Whether to use named parameters binding when executing SQL queries or not. @@ -84,11 +95,10 @@ Note that maddy's PostgreSQL driver does not support named parameters and SQLite3 driver has issues handling numbered parameters: [https://github.com/mattn/go-sqlite3/issues/472](https://github.com/mattn/go-sqlite3/issues/472) -***Syntax:*** add _query_
-***Syntax:*** list _query_
-***Syntax:*** set _query_
-***Syntax:*** del _query_
-***Default:*** none +--- + +### add _query_
list _query_
set _query_
del _query_ +Default: none If queries are set to implement corresponding table operations - table becomes "mutable" and can be used in contexts that require writable key-value store. @@ -105,6 +115,6 @@ entry in the database. 'del' query gets :key argument - key and should remove it from the database. -If named\_args is set to "no" - key is passed as the first numbered parameter +If `named_args` is set to `no` - key is passed as the first numbered parameter ($1), value is passed as the second numbered parameter ($2). diff --git a/docs/reference/table/static.md b/docs/reference/table/static.md index ccee1d2e..e71b448f 100644 --- a/docs/reference/table/static.md +++ b/docs/reference/table/static.md @@ -13,7 +13,7 @@ table.static { ## Configuration directives -***Syntax***: entry _key_ _value\_ +### entry _key_ _value_ Add an entry to the table. diff --git a/docs/reference/targets/queue.md b/docs/reference/targets/queue.md index cc25db1a..373ff1a4 100644 --- a/docs/reference/targets/queue.md +++ b/docs/reference/targets/queue.md @@ -33,38 +33,45 @@ target.queue { } ``` -**Syntax**: target _block\_name_
-**Default**: not specified - -REQUIRED. +### target _block_name_ +**Required.**
+Default: not specified Delivery target to use for final delivery. -**Syntax**: location _directory_
-**Default**: StateDirectory/configuration\_block\_name +--- + +### location _directory_ +Default: `StateDirectory/configuration_block_name` File system directory to use to store queued messages. Relative paths are relative to the StateDirectory. -**Syntax**: max\_parallelism _integer_
-**Default**: 16 +--- + +### max_parallelism _integer_ +Default: `16` Start up to _integer_ goroutines for message processing. Basically, this option limits amount of messages tried to be delivered concurrently. -**Syntax**: max\_tries _integer_
-**Default**: 20 +--- + +### max_tries _integer_ +Default: `20` Attempt delivery up to _integer_ times. Note that no more attempts will be done is permanent error occurred during previous attempt. Delay before the next attempt will be increased exponentially using the -following formula: 15mins \* 1.2 ^ (n - 1) where n is the attempt number. +following formula: 15mins * 1.2 ^ (n - 1) where n is the attempt number. This gives you approximately the following sequence of delays: 18mins, 21mins, 25mins, 31mins, 37mins, 44mins, 53mins, 64mins, ... -**Syntax**: bounce { ... }
-**Default**: not specified +--- + +### bounce { ... } +Default: not specified This configuration contains pipeline configuration to be used for generated DSN (Delivery Status Notification) messages. @@ -72,13 +79,17 @@ This configuration contains pipeline configuration to be used for generated DSN If this is block is not present in configuration, DSNs will not be generated. Note, however, this is not what you want most of the time. -**Syntax**: autogenerated\_msg\_domain _domain_
-**Default**: global directive value +--- + +### autogenerated_msg_domain _domain_ +Default: global directive value Domain to use in sender address for DSNs. Should be specified too if 'bounce' block is specified. -**Syntax**: debug _boolean_
-**Default**: no +--- + +### debug _boolean_ +Default: `no` Enable verbose logging. \ No newline at end of file diff --git a/docs/reference/targets/remote.md b/docs/reference/targets/remote.md index f69a6de2..ea58d153 100644 --- a/docs/reference/targets/remote.md +++ b/docs/reference/targets/remote.md @@ -15,27 +15,33 @@ target.remote { } ``` -**Syntax**: hostname _domain_
-**Default**: global directive value +### hostname _domain_ +Default: global directive value Hostname to use client greeting (EHLO/HELO command). Some servers require it to be FQDN, SPF-capable servers check whether it corresponds to the server IP address, so it is better to set it to a domain that resolves to the server IP. -**Syntax**: limits _config block_
-**Default**: no limits +--- + +### limits { ... } +Default: no limits See ['limits' directive for SMTP endpoint](/reference/endpoints/smtp/#rate-concurrency-limiting). It works the same except for address domains used for per-source/per-destination are as observed when message exits the server. -**Syntax**: local\_ip _IP address_
-**Default**: empty +--- + +### local_ip _ip-address_ +Default: empty Choose the local IP to bind for outbound SMTP connections. -**Syntax**: force\_ipv4 _boolean_
-**Default**: false +--- + +### force_ipv4 _boolean_ +Default: `false` Force resolving outbound SMTP domains to IPv4 addresses. Some server providers do not offer a way to properly set reverse PTR domains for IPv6 addresses; this @@ -45,8 +51,10 @@ its IPv4 address. Warning: this may break sending outgoing mail to IPv6-only SMTP servers. -**Syntax**: connect\_timeout _duration_
-**Default**: 5m +--- + +### connect_timeout _duration_ +Default: `5m` Timeout for TCP connection establishment. @@ -56,8 +64,10 @@ lookup + TCP handshake) and another for "initial greeting". This directive configures the former. The latter is not configurable and is hardcoded to be 5 minutes. -**Syntax**: command\_timeout _duration_
-**Default**: 5m +--- + +### command_timeout _duration_ +Default: `5m` Timeout for any SMTP command (EHLO, MAIL, RCPT, DATA, etc). @@ -66,28 +76,36 @@ If STARTTLS is used this timeout also applies to TLS handshake. RFC 5321 recommends 5 minutes for MAIL/RCPT and 3 minutes for DATA. -**Syntax**: submission\_timeout _duration_
-**Default**: 12m +--- + +### submission_timeout _duration_ +Default: `12m` Time to wait after the entire message is sent (after "final dot"). RFC 5321 recommends 10 minutes. -**Syntax**: debug _boolean_
-**Default**: global directive value +--- + +### debug _boolean_ +Default: global directive value Enable verbose logging. -**Syntax**: requiretls\_override _boolean_
-**Default**: true +--- + +### requiretls_override _boolean_ +Default: `true` Allow local security policy to be disabled using 'TLS-Required' header field in sent messages. Note that the field has no effect if transparent forwarding is used, message body should be processed before outbound delivery starts for it to take effect (e.g. message should be queued using 'queue' module). -**Syntax**: relaxed\_requiretls _boolean_
-**Default**: true +--- + +### relaxed_requiretls _boolean_ +Default: `true` This option disables strict conformance with REQUIRETLS specification and allows forwarding of messages 'tagged' with REQUIRETLS to MXes that are not @@ -96,54 +114,66 @@ need to have support from all servers. It is based on the assumption that server referenced by MX record is likely the final destination and therefore there is only need to secure communication towards it and not beyond. -**Syntax**: conn\_reuse\_limit _integer_
-**Default**: 10 +--- + +### conn_reuse_limit _integer_ +Default: `10` Amount of times the same SMTP connection can be used. Connections are never reused if the previous DATA command failed. -**Syntax**: conn\_max\_idle\_count _integer_
-**Default**: 10 +--- + +### conn_max_idle_count _integer_ +Default: `10` Max. amount of idle connections per recipient domains to keep in cache. -**Syntax**: conn\_max\_idle\_time _integer_
-**Default**: 150 (2.5 min) +--- + +### conn_max_idle_time _integer_ +Default: `150` (2.5 min) Amount of time the idle connection is still considered potentially usable. +--- + ## Security policies -**Syntax**: mx\_auth _config block_
-**Default**: no policies +### mx_auth { ... } +Default: no policies 'remote' module implements a number of of schemes and protocols necessary to ensure security of message delivery. Most of these schemes are concerned with authentication of recipient server and TLS enforcement. -To enable mechanism, specify its name in the mx\_auth directive block: +To enable mechanism, specify its name in the `mx_auth` directive block: + ``` mx_auth { dane mtasts } ``` + Additional configuration is possible if supported by the mechanism by specifying additional options as a block for the corresponding mechanism. E.g. + ``` mtasts { cache ram } ``` -If the mx\_auth directive is not specified, no mechanisms are enabled. Note +If the `mx_auth` directive is not specified, no mechanisms are enabled. Note that, however, this makes outbound SMTP vulnerable to a numerous downgrade attacks and hence not recommended. It is possible to share the same set of policies for multiple 'remote' module -instances by defining it at the top-level using 'mx\_auth' module and then +instances by defining it at the top-level using `mx_auth` module and then referencing it using standard & syntax: + ``` mx_auth outbound_policy { dane @@ -166,6 +196,8 @@ deliver_to remote { } ``` +--- + ### MTA-STS Checks MTA-STS policy of the recipient domain. Provides proper authentication @@ -182,8 +214,8 @@ mtasts { } ``` -**Syntax**: cache fs|ram
-**Default**: fs +### cache `fs` | `ram` +Default: `fs` Storage to use for MTA-STS cache. 'fs' is to use a filesystem directory, 'ram' to store the cache in memory. @@ -192,11 +224,13 @@ It is recommended to use 'fs' since that will not discard the cache (and thus cause MTA-STS security to disappear) on server restart. However, using the RAM cache can make sense for high-load configurations with good uptime. -**Syntax**: fs\_dir _directory_
-**Default**: StateDirectory/mtasts\_cache +### fs_dir _directory_ +Default: `StateDirectory/mtasts_cache` Filesystem directory to use for policies caching if 'cache' is set to 'fs'. +--- + ### DNSSEC Checks whether MX records are signed. Sets MX level to "dnssec" is they are. @@ -213,6 +247,8 @@ have the /etc/resolv.conf file in the standard format. dnssec { } ``` +--- + ### DANE Checks TLSA records for the recipient MX. Provides downgrade-resistant TLS @@ -227,6 +263,8 @@ See above for notes on DNSSEC. DNSSEC support is required for DANE to work. dane { } ``` +--- + ### Local policy Checks effective TLS and MX levels (as set by other policies) against local @@ -239,17 +277,17 @@ local_policy { } ``` -Using 'local\_policy off' is equivalent to setting both directives to 'none'. +Using `local_policy off` is equivalent to setting both directives to `none`. -**Syntax**: min\_tls\_level none|encrypted|authenticated
-**Default**: none +### min_tls_level `none` | `encrypted` | `authenticated` +Default: `none` Set the minimal TLS security level required for all outbound messages. See [Security levels](../../seclevels) page for details. -**Syntax**: min\_mx\_level: none|mtasts|dnssec
-**Default**: none +### min_mx_level `none` | `mtasts` | `dnssec` +Default: `none` Set the minimal MX security level required for all outbound messages. diff --git a/docs/reference/targets/smtp.md b/docs/reference/targets/smtp.md index a7dec171..7ee56abd 100644 --- a/docs/reference/targets/smtp.md +++ b/docs/reference/targets/smtp.md @@ -3,6 +3,7 @@ Module that implements transparent forwarding of messages over SMTP. Use in pipeline configuration: + ``` deliver_to smtp tcp://127.0.0.1:5353 # or @@ -34,81 +35,81 @@ target.smtp { } ``` -**Syntax**: debug _boolean_
-**Default**: global directive value +### debug _boolean_ +Default: global directive value Enable verbose logging. -**Syntax**: tls\_client { ... }
-**Default**: not specified +--- + +### tls_client { ... } +Default: not specified Advanced TLS client configuration options. See [TLS configuration / Client](/reference/tls/#client) for details. -**Syntax**: attempt\_starttls _boolean_
-**Default**: yes (no for target.lmtp) +--- + +### attempt_starttls _boolean_ +Default: `yes` (`no` for `target.lmtp`) Attempt to use STARTTLS if it is supported by the remote server. If TLS handshake fails, connection will be retried without STARTTLS -unless 'require\_tls' is also specified. +unless `require_tls` is also specified. + +--- -**Syntax**: require\_tls _boolean_
-**Default**: no +### require_tls _boolean_ +Default: `no` Refuse to pass messages over plain-text connections. -**Syntax**:
-auth off
-plain _username_ _password_
-forward
-external
-**Default**: off +--- + +### auth `off` | `plain` _username_ _password_ | `forward` | `external` +Default: `off` Specify the way to authenticate to the remote server. Valid values: -- off - - No authentication. - -- plain - - Authenticate using specified username-password pair. - **Don't use** this without enforced TLS ('require\_tls'). - -- forward - - Forward credentials specified by the client. - **Don't use** this without enforced TLS ('require\_tls'). - -- external - - Request "external" SASL authentication. This is usually used for +- `off` – No authentication. +- `plain` – Authenticate using specified username-password pair. + **Don't use** this without enforced TLS (`require_tls`). +- `forward` – Forward credentials specified by the client. + **Don't use** this without enforced TLS (`require_tls`). +- `external` – Request "external" SASL authentication. This is usually used for authentication using TLS client certificates. See [TLS configuration / Client](/reference/tls/#client) for details. -**Syntax**: targets _endpoints..._
-**Default:** not specified +--- -REQUIRED. +### targets _endpoints..._ +**Required.**
+Default: not specified List of remote server addresses to use. See [Address definitions](/reference/config-syntax/#address-definitions) -for syntax to use. Basically, it is 'tcp://ADDRESS:PORT' -for plain SMTP and 'tls://ADDRESS:PORT' for SMTPS (aka SMTP with Implicit +for syntax to use. Basically, it is `tcp://ADDRESS:PORT` +for plain SMTP and `tls://ADDRESS:PORT` for SMTPS (aka SMTP with Implicit TLS). Multiple addresses can be specified, they will be tried in order until connection to one succeeds (including TLS handshake if TLS is required). -**Syntax**: connect\_timeout _duration_
-**Default**: 5m +--- + +### connect_timeout _duration_ +Default: `5m` Same as for target.remote. -**Syntax**: command\_timeout _duration_
-**Default**: 5m +--- + +### command_timeout _duration_ +Default: `5m` Same as for target.remote. -**Syntax**: submission\_timeout _duration_
-**Default**: 12m +--- + +### submission_timeout _duration_ +Default: `12m` Same as for target.remote. \ No newline at end of file diff --git a/docs/reference/tls-acme.md b/docs/reference/tls-acme.md index 3dc803a5..930e390c 100644 --- a/docs/reference/tls-acme.md +++ b/docs/reference/tls-acme.md @@ -2,9 +2,10 @@ Maddy supports obtaining certificates using ACME protocol. -To use it, create a configuration name for tls.loader.acme +To use it, create a configuration name for `tls.loader.acme` and reference it from endpoints that should use automatically configured certificates: + ``` tls.loader.acme local_tls { email put-your-email-here@example.org @@ -17,8 +18,10 @@ smtp tcp://127.0.0.1:25 { ... } ``` + You can also use a global `tls` directive to use automatically obtained certificates for all endpoints: + ``` tls { loader acme { @@ -29,8 +32,9 @@ tls { } ``` -Currently the only supported challenge is dns-01 one therefore +Currently the only supported challenge is `dns-01` one therefore you also need to configure the DNS provider: + ``` tls.loader.acme local_tls { email maddy-acme@example.org @@ -41,6 +45,7 @@ tls.loader.acme local_tls { } } ``` + See below for supported providers and necessary configuration for each. @@ -60,41 +65,52 @@ tls.loader.acme { } ``` -**Syntax:** debug _boolean_
-**Default:** global directive value +### debug _boolean_ +Default: global directive value Enable debug logging. -**Syntax:** hostname _str_
-**Default:** global directive value +--- + +### hostname _str_ +**Required.**
+Default: global directive value + +Domain name to issue certificate for. -Domain name to issue certificate for. Required. +--- -**Syntax:** store\_path _path_
-**Default:** state\_dir/acme +### store_path _path_ +Default: `state_dir/acme` Where to store issued certificates and associated metadata. Currently only filesystem-based store is supported. -**Syntax:** ca _url_
-**Default:** Let's Encrypt production CA +--- + +### ca _url_ +Default: Let's Encrypt production CA URL of ACME directory to use. -**Syntax:** test\_ca _url_
-**Default:** Let's Encrypt staging CA +--- + +### test_ca _url_ +Default: Let's Encrypt staging CA URL of ACME directory to use for retries should primary CA fail. maddy will keep attempting to issues certificates -using test\_ca until it succeeds then it will switch +using `test_ca` until it succeeds then it will switch back to the one configured via 'ca' option. This avoids rate limit issues with production CA. -**Syntax:** override\_domain _domain_
-**Default:** not set +--- + +### override_domain _domain_ +Default: not set Override the domain to set the TXT record on for DNS-01 challenge. This is to delegate the challenge to a different domain. @@ -102,18 +118,24 @@ This is to delegate the challenge to a different domain. See https://www.eff.org/deeplinks/2018/02/technical-deep-dive-securing-automation-acme-dns-challenge-validation for explanation why this might be useful. -**Syntax:** email _str_
-**Default:** not set +--- + +### email _str_ +Default: not set Email to pass while registering an ACME account. -**Syntax:** agreed _boolean_
-**Default:** false +--- + +### agreed _boolean_ +Default: false Whether you agreed to ToS of the CA service you are using. -**Syntax:** challenge dns-01
-**Default:** not set +--- + +### challenge `dns-01` +Default: not set Challenge(s) to use while performing domain verification. @@ -121,7 +143,7 @@ Challenge(s) to use while performing domain verification. Support for some providers is not provided by standard builds. To be able to use these, you need to compile maddy -with "libdns\_PROVIDER" build tag. +with "libdns_PROVIDER" build tag. E.g. ``` ./build.sh -tags 'libdns_googleclouddns' diff --git a/docs/reference/tls.md b/docs/reference/tls.md index 7f57820c..954b0e06 100644 --- a/docs/reference/tls.md +++ b/docs/reference/tls.md @@ -26,79 +26,73 @@ tls { ### Available certificate loaders -- file - - Accepts argument pairs specifying certificate and then key. - E.g. 'tls file certA.pem keyA.pem certB.pem keyB.pem' - +- `file` – Accepts argument pairs specifying certificate and then key. + E.g. `tls file certA.pem keyA.pem certB.pem keyB.pem`. If multiple certificates are listed, SNI will be used. - -- acme - - Automatically obtains a certificate using ACME protocol (Let's Encrypt) - -- off - - Not really a loader but a special value for tls directive, explicitly disables TLS for - endpoint(s). +- `acme` – Automatically obtains a certificate using ACME protocol (Let's Encrypt) +- `off` – Not really a loader but a special value for tls directive, + explicitly disables TLS for endpoint(s). ## Advanced TLS configuration -**Note: maddy uses secure defaults and TLS handshake is resistant to active downgrade attacks.** -**There is no need to change anything in most cases.** +**Note: maddy uses secure defaults and TLS handshake is resistant to active downgrade attacks. There is no need to change anything in most cases.** + +--- -**Syntax**:
-protocols _min\_version_ _max\_version_
-protocols _version_
-**Default**: tls1.0 tls1.3 +### protocols _min-version_ _max-version_ | _version_ +Default: `tls1.0 tls1.3` Minimum/maximum accepted TLS version. If only one value is specified, it will be the only one usable version. -Valid values are: tls1.0, tls1.1, tls1.2, tls1.3 +Valid values are: `tls1.0`, `tls1.1`, `tls1.2`, `tls1.3` -**Syntax**: ciphers _ciphers..._
-**Default**: Go version-defined set of 'secure ciphers', ordered by hardware +--- + +### ciphers _ciphers..._ +Default: Go version-defined set of 'secure ciphers', ordered by hardware performance List of supported cipher suites, in preference order. Not used with TLS 1.3. Valid values: -- RSA-WITH-RC4128-SHA -- RSA-WITH-3DES-EDE-CBC-SHA -- RSA-WITH-AES128-CBC-SHA -- RSA-WITH-AES256-CBC-SHA -- RSA-WITH-AES128-CBC-SHA256 -- RSA-WITH-AES128-GCM-SHA256 -- RSA-WITH-AES256-GCM-SHA384 -- ECDHE-ECDSA-WITH-RC4128-SHA -- ECDHE-ECDSA-WITH-AES128-CBC-SHA -- ECDHE-ECDSA-WITH-AES256-CBC-SHA -- ECDHE-RSA-WITH-RC4128-SHA -- ECDHE-RSA-WITH-3DES-EDE-CBC-SHA -- ECDHE-RSA-WITH-AES128-CBC-SHA -- ECDHE-RSA-WITH-AES256-CBC-SHA -- ECDHE-ECDSA-WITH-AES128-CBC-SHA256 -- ECDHE-RSA-WITH-AES128-CBC-SHA256 -- ECDHE-RSA-WITH-AES128-GCM-SHA256 -- ECDHE-ECDSA-WITH-AES128-GCM-SHA256 -- ECDHE-RSA-WITH-AES256-GCM-SHA384 -- ECDHE-ECDSA-WITH-AES256-GCM-SHA384 -- ECDHE-RSA-WITH-CHACHA20-POLY1305 -- ECDHE-ECDSA-WITH-CHACHA20-POLY1305 - -**Syntax**: curves _curves..._
-**Default**: defined by Go version +- `RSA-WITH-RC4128-SHA` +- `RSA-WITH-3DES-EDE-CBC-SHA` +- `RSA-WITH-AES128-CBC-SHA` +- `RSA-WITH-AES256-CBC-SHA` +- `RSA-WITH-AES128-CBC-SHA256` +- `RSA-WITH-AES128-GCM-SHA256` +- `RSA-WITH-AES256-GCM-SHA384` +- `ECDHE-ECDSA-WITH-RC4128-SHA` +- `ECDHE-ECDSA-WITH-AES128-CBC-SHA` +- `ECDHE-ECDSA-WITH-AES256-CBC-SHA` +- `ECDHE-RSA-WITH-RC4128-SHA` +- `ECDHE-RSA-WITH-3DES-EDE-CBC-SHA` +- `ECDHE-RSA-WITH-AES128-CBC-SHA` +- `ECDHE-RSA-WITH-AES256-CBC-SHA` +- `ECDHE-ECDSA-WITH-AES128-CBC-SHA256` +- `ECDHE-RSA-WITH-AES128-CBC-SHA256` +- `ECDHE-RSA-WITH-AES128-GCM-SHA256` +- `ECDHE-ECDSA-WITH-AES128-GCM-SHA256` +- `ECDHE-RSA-WITH-AES256-GCM-SHA384` +- `ECDHE-ECDSA-WITH-AES256-GCM-SHA384` +- `ECDHE-RSA-WITH-CHACHA20-POLY1305` +- `ECDHE-ECDSA-WITH-CHACHA20-POLY1305` + +--- + +### curves _curves..._ +Default: defined by Go version The elliptic curves that will be used in an ECDHE handshake, in preference order. -Valid values: p256, p384, p521, X25519. +Valid values: `p256`, `p384`, `p521`, `X25519`. ## Client -tls\_client directive allows to customize behavior of TLS client implementation, +`tls_client` directive allows to customize behavior of TLS client implementation, notably adjusting minimal and maximal TLS versions and allowed cipher suites, enabling TLS client authentication. @@ -114,42 +108,48 @@ tls_client { } ``` -**Syntax**:
-protocols _min\_version_ _max\_version_
-protocols _version_
-**Default**: tls1.0 tls1.3 +--- + +### protocols _min-version_ _max-version_ | _version_ +Default: `tls1.0 tls1.3` Minimum/maximum accepted TLS version. If only one value is specified, it will be the only one usable version. -Valid values are: tls1.0, tls1.1, tls1.2, tls1.3 +Valid values are: `tls1.0`, `tls1.1`, `tls1.2`, `tls1.3` + +--- -**Syntax**: ciphers _ciphers..._
-**Default**: Go version-defined set of 'secure ciphers', ordered by hardware +### ciphers _ciphers..._ +Default: Go version-defined set of 'secure ciphers', ordered by hardware performance List of supported cipher suites, in preference order. Not used with TLS 1.3. See TLS server configuration for list of supported values. -**Syntax**: curves _curves..._
-**Default**: defined by Go version +--- + +### curves _curves..._ +Default: defined by Go version The elliptic curves that will be used in an ECDHE handshake, in preference order. -Valid values: p256, p384, p521, X25519. +Valid values: `p256`, `p384`, `p521`, `X25519`. + +--- -**Syntax**: root\_ca _paths..._
-**Default**: system CA pool +### root_ca _paths..._ +Default: system CA pool List of files with PEM-encoded CA certificates to use when verifying server certificates. -**Syntax**:
-cert _cert\_path_
-key _key\_path_
-**Default**: not specified +--- + +### cert _cert-path_
key _key-path_ +Default: not specified Present the specified certificate when server requests a client certificate. Files should use PEM format. Both directives should be specified.