Skip to main content
Caddy’s TLS automation handles certificate lifecycle management including obtaining, renewing, and revoking certificates automatically.

AutomationConfig

The top-level automation configuration controls certificate management policies and intervals.
policies
array
List of automation policies. The first policy matching a certificate or subject name will be applied.Each policy can specify which subjects it applies to and which issuers to use for certificate management.
on_demand
object
On-Demand TLS configuration. Defers certificate operations to the moment they are needed (during TLS handshake).
Caddy was the first web server to implement this experimental technology in 2015.
This field only configures on-demand TLS, it does not enable it. To enable, create an automation policy with on_demand: true.
ocsp_interval
duration
default:"1h"
How often to scan OCSP responses for freshness and update them if getting stale.Caddy staples OCSP and caches the response for all qualifying certificates by default.
renew_interval
duration
default:"10m"
How frequently to scan all loaded, managed certificates for expiration.
storage_clean_interval
duration
default:"24h"
How often to scan storage units for old or expired assets and remove them.
These scans exert lots of reads and list operations on storage. Choose a longer interval for large deployments.
Storage is always cleaned when the process first starts. A new cleaning starts this duration after the previous one started, but only if the previous cleaning finished in less than half this interval.

Automation Policy

An automation policy designates how to automate the management (obtaining, renewal, and revocation) of TLS certificates.

Policy Configuration

subjects
array of strings
Which subjects (hostnames or IP addresses) this policy applies to.
This is a filter, not a command. It’s used only to determine whether this policy should apply to a subject that needs a certificate. To have Caddy automate certificates for specific subjects, use the “automate” certificate loader module.
issuers
array
Modules that may issue certificates.Default: internal if all subjects do not qualify for public certificates; otherwise acme and zerossl.Available issuers:
  • acme - ACME protocol (Let’s Encrypt, ZeroSSL, etc.)
  • zerossl - ZeroSSL API (distinct from ACME)
  • internal - Internal CA using PKI app
get_certificate
array
Modules that can get a custom certificate for any given TLS handshake at handshake-time.
EXPERIMENTAL: Subject to change or removal.
Enables on-demand TLS as a side-effect. Useful when another entity is managing certificates and Caddy only needs to retrieve and serve them.
must_staple
boolean
default:"false"
If true, certificates will be requested with MustStaple.
Not all CAs support this. There are potentially serious consequences of enabling this without proper threat modeling.
renewal_window_ratio
number
default:"0.33"
How long before expiration to try renewing a certificate, as a function of its total lifetime.
As a conservative rule, it’s good to renew when about 1/3 of lifetime remains. This uses the majority of the certificate’s lifetime while saving time to troubleshoot. For extremely short-lived certs, you may want to increase to ~0.5.
key_type
string
The type of key to generate for certificates.Supported values:
  • ed25519
  • p256
  • p384
  • rsa2048
  • rsa4096
storage
object
Optionally configure a separate storage module associated with this policy, instead of using Caddy’s global/default-configured storage.
on_demand
boolean
default:"false"
If true, certificates will be managed “on demand” - during TLS handshakes or when needed, rather than at startup or config load.This enables On-Demand TLS for this policy.
reuse_private_keys
boolean
default:"false"
If true, private keys already existing in storage will be reused.
TEMPORARY: Key pinning is against industry best practices. This property will likely be removed in the future. Do not rely on it; watch the release notes.
Otherwise, a new key will be created for every new certificate to mitigate pinning and reduce the scope of key compromise.
disable_ocsp_stapling
boolean
default:"false"
Disables OCSP stapling.
Disabling OCSP stapling puts clients at greater risk, reduces their privacy, and usually lowers client performance. NOT recommended unless you can justify the costs.
EXPERIMENTAL: Subject to change.
ocsp_overrides
object
Overrides the URLs of OCSP responders embedded in certificates.Each key is an OCSP server URL to override, and its value is the replacement. An empty value disables querying of that server.
EXPERIMENTAL: Subject to change.

Configuration Examples

Basic Automation Policy

{
  "apps": {
    "tls": {
      "automation": {
        "policies": [
          {
            "subjects": ["example.com", "*.example.com"],
            "issuers": [
              {
                "module": "acme",
                "email": "[email protected]"
              }
            ]
          }
        ]
      }
    }
  }
}

On-Demand TLS with Permission Module

{
  "apps": {
    "tls": {
      "automation": {
        "policies": [
          {
            "on_demand": true
          }
        ],
        "on_demand": {
          "permission": {
            "module": "http",
            "endpoint": "https://api.example.com/check-domain"
          }
        }
      }
    }
  }
}

Custom Renewal and Storage Settings

{
  "apps": {
    "tls": {
      "automation": {
        "ocsp_interval": "2h",
        "renew_interval": "5m",
        "storage_clean_interval": "48h",
        "policies": [
          {
            "subjects": ["example.com"],
            "renewal_window_ratio": 0.5,
            "key_type": "p256"
          }
        ]
      }
    }
  }
}

Internal CA for Development

{
  "apps": {
    "tls": {
      "automation": {
        "policies": [
          {
            "subjects": ["localhost", "*.local"],
            "issuers": [
              {
                "module": "internal",
                "ca": "local",
                "lifetime": "24h"
              }
            ]
          }
        ]
      }
    }
  }
}

Default Issuers

When no issuers are explicitly configured, Caddy uses sensible defaults:
  1. For public certificates (domains qualifying for public trust):
    • ACME issuer (Let’s Encrypt)
    • ZeroSSL ACME issuer (if email is provided)
  2. For internal certificates (localhost, .local, IP addresses):
    • Internal issuer using Caddy’s PKI app

On-Demand TLS

On-Demand TLS allows Caddy to obtain certificates during the TLS handshake, when the certificate is first needed.
On-demand TLS requires a permission module to prevent abuse. Without it, your server may be vulnerable to attackers who could exhaust rate limits or storage.

Permission Module

The permission module (typically http) makes a request to your application to determine if a certificate should be allowed:
endpoint
string
required
Full URL to the permission endpoint. A query parameter ?domain=example.com will be added.The endpoint must return HTTP 200 OK to allow the certificate; anything else denies it. Redirects are not followed.

Example Permission Endpoint

// Express.js example
app.get('/check-domain', (req, res) => {
  const domain = req.query.domain;
  
  // Check if domain is allowed in your database
  if (isAllowedDomain(domain)) {
    res.status(200).send('OK');
  } else {
    res.status(403).send('Forbidden');
  }
});

Caddyfile Configuration

{
  email [email protected]
  
  # Custom automation policy
  cert_issuer acme {
    dir https://acme-v02.api.letsencrypt.org/directory
    email [email protected]
  }
  
  # On-demand TLS
  on_demand_tls {
    ask https://api.example.com/check-domain
  }
  
  # Renewal settings
  renew_interval 5m
  ocsp_interval 1h
}

example.com {
  tls {
    on_demand
  }
}

Best Practices

Renewal Window: The default 1/3 lifetime ratio means a 90-day Let’s Encrypt certificate renews around 30 days before expiration, leaving ample time for troubleshooting.
On-Demand Security: Always use a permission module with on-demand TLS. Publicly accessible “ask” endpoints should be avoided to prevent information leaks.
Key Types: Ed25519 offers the best performance and security for most use cases. RSA keys are larger and slower but may be required for compatibility with older clients.

Build docs developers (and LLMs) love