1# Automatic certificate management via ACME23Maddy supports obtaining certificates using ACME protocol.45To use it, create a configuration name for `tls.loader.acme`6and reference it from endpoints that should use automatically7configured certificates:89```10tls.loader.acme local_tls {11 email put-your-email-here@example.org12 agreed # indicate your agreement with Let's Encrypt ToS13 challenge dns-0114}1516smtp tcp://127.0.0.1:25 {17 tls &local_tls18 ...19}20```2122You can also use a global `tls` directive to use automatically23obtained certificates for all endpoints:2425```26tls {27 loader acme {28 email maddy-acme@example.org29 agreed30 challenge dns-0131 }32}33```3435Note: `tls &local_tls` as a global directive won't work because36global directives are initialized before other configuration blocks.3738Currently the only supported challenge is `dns-01` one therefore39you also need to configure the DNS provider:4041```42tls.loader.acme local_tls {43 email maddy-acme@example.org44 agreed45 challenge dns-0146 dns PROVIDER_NAME {47 ...48 }49}50```5152See below for supported providers and necessary configuration53for each.5455## Configuration directives5657```58tls.loader.acme {59 debug off60 hostname example.maddy.invalid61 store_path /var/lib/maddy/acme62 ca https://acme-v02.api.letsencrypt.org/directory63 test_ca https://acme-staging-v02.api.letsencrypt.org/directory64 email test@maddy.invalid65 agreed off66 challenge dns-0167 dns ...68}69```7071### debug _boolean_72Default: global directive value7374Enable debug logging.7576---7778### hostname _str_79**Required.**<br>80Default: global directive value8182Domain name to issue certificate for.8384---8586### store_path _path_87Default: `state_dir/acme`8889Where to store issued certificates and associated metadata.90Currently only filesystem-based store is supported.9192---9394### ca _url_95Default: Let's Encrypt production CA9697URL of ACME directory to use.9899---100101### test_ca _url_102Default: Let's Encrypt staging CA103104URL of ACME directory to use for retries should105primary CA fail.106107maddy will keep attempting to issues certificates108using `test_ca` until it succeeds then it will switch109back to the one configured via 'ca' option.110111This avoids rate limit issues with production CA.112113---114115### override_domain _domain_116Default: not set117118Override the domain to set the TXT record on for DNS-01 challenge.119This is to delegate the challenge to a different domain.120121See https://www.eff.org/deeplinks/2018/02/technical-deep-dive-securing-automation-acme-dns-challenge-validation122for explanation why this might be useful.123124---125126### email _str_127Default: not set128129Email to pass while registering an ACME account.130131---132133### agreed _boolean_134Default: false135136Whether you agreed to ToS of the CA service you are using.137138---139140### challenge `dns-01`141Default: not set142143Challenge(s) to use while performing domain verification.144145## DNS providers146147Support for some providers is not provided by standard builds.148To be able to use these, you need to compile maddy149with "libdns_PROVIDER" build tag.150E.g.151```152./build.sh --tags 'libdns_googleclouddns'153```154155- gandi156157```158dns gandi {159 api_token "token"160}161```162163- digitalocean164165```166dns digitalocean {167 api_token "..."168}169```170171- cloudflare172173See [https://github.com/libdns/cloudflare#authenticating](https://github.com/libdns/cloudflare#authenticating)174175```176dns cloudflare {177 api_token "..."178}179```180181- vultr182183```184dns vultr {185 api_token "..."186}187```188189- hetzner190191```192dns hetzner {193 api_token "..."194}195```196197- namecheap198199```200dns namecheap {201 api_key "..."202 api_username "..."203204 # optional: API endpoint, production one is used if not set.205 endpoint "https://api.namecheap.com/xml.response"206207 # optional: your public IP, discovered using icanhazip.com if not set208 client_ip 1.2.3.4209}210```211212- googleclouddns (non-default)213214```215dns googleclouddns {216 project "project_id"217 service_account_json "path"218}219```220221- route53 (non-default)222223```224dns route53 {225 secret_access_key "..."226 access_key_id "..."227 # or use environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY228}229```230231- leaseweb (non-default)232233```234dns leaseweb {235 api_key "key"236}237```238239- metaname (non-default)240241```242dns metaname {243 api_key "key"244 account_ref "reference"245}246```247248- alidns (non-default)249250```251dns alidns {252 key_id "..."253 key_secret "..."254}255```256257- namedotcom (non-default)258259```260dns namedotcom {261 user "..."262 token "..."263}264```265266- rfc2136 (non-default)267268```269dns rfc2136 {270 key_name "..."271 # Secret272 key "..."273 # HMAC algorithm used to generate the key, lowercase, e.g. hmac-sha512274 key_alg "..."275 # server to which the dynamic update will be sent, e.g. 127.0.0.1276 # you can also specify the port: 127.0.0.1:53277 server "..."278}279```280281- acmedns (non-default)282283```284dns acmedns {285 username "..."286 password "..."287 subdomain "..."288 server_url "..."289}290```