Global options
The Caddyfile has a way for you to specify options that apply globally. Some options act as default values; others customize HTTP servers and don't apply to just one particular site; while yet others customize the behavior of the Caddyfile
adapter
.
The very top of your Caddyfile can be a
global options block
. This is a block that has no keys:
There can only be one at most, and it must be the first block of the Caddyfile.
Possible options are (click on each option to jump to its documentation):
# General Options
debug
http_port
<port>
https_port
<port>
default_bind
<hosts...>
order
<dir1>
first
|
last
|[
before
|
after
<dir2>
]
storage
<module_name>
{
<options...>
storage_clean_interval
<duration>
renew_interval
<duration>
ocsp_interval
<duration>
admin
off
|
<addr>
{
origins
<origins...>
enforce_origin
persist_config
off
log
[
name
]
{
output
<writer_module>
...
format
<encoder_module>
...
level
<level>
include
<namespaces...>
exclude
<namespaces...>
grace_period
<duration>
shutdown_delay
<duration>
# TLS Options
auto_https
off
|
disable_redirects|ignore_loaded_certs|disable_certs
email
<yours>
default_sni
<name>
fallback_sni
<name>
local_certs
skip_install_trust
acme_ca
<directory_url>
acme_ca_root
<pem_file>
acme_eab
<key_id>
<mac_key>
acme_dns
<provider>
...
on_demand_tls
{
ask
<endpoint>
interval
<duration>
burst
<n>
key_type
ed25519|p256|p384|rsa2048|rsa4096
cert_issuer
<name>
...
ocsp_stapling
off
preferred_chains
[
smallest
]
{
root_common_name
<common_names...>
any_common_name
<common_names...>
# Server Options
servers
[
<listener_address>
]
{
name
<name>
listener_wrappers
{
<listener_wrappers...>
timeouts
{
read_body
<duration>
read_header
<duration>
write
<duration>
idle
<duration>
trusted_proxies
<module>
...
client_ip_headers
<headers...>
metrics
max_header_size
<size>
enable_full_duplex
log_credentials
protocols
[
h1|h2|h2c|h3
]
strict_sni_host
[
on
|
insecure_off
]
# PKI Options
pki
{
ca
[
<id>
]
{
name
<name>
root_cn
<name>
intermediate_cn
<name>
intermediate_lifetime
<duration>
root
{
format
<format>
cert
<path>
key
<path>
intermediate
{
format
<format>
cert
<path>
key
<path>
# Event options
events
{
on
<event>
<handler...>
General Options
debug
Enables debug mode, which sets the log level to
DEBUG
for the
default logger
. This reveals more details that can be useful when troubleshooting (and is very verbose in production). We ask that you enable this before asking for help on the
community forums
. For example, at the top of your Caddyfile, if you have no other global options:
debug
http_port
The port for the server to use for HTTP. For internal use only; does not change the HTTP port for clients. Default:
80
https_port
The port for the server to use for HTTPS. For internal use only; does not change the HTTPS port for clients. Default:
443
default_bind
The default bind address(es) to be used for all sites, if the
bind
directive
is not used in the site. Default: empty, which binds to all interfaces.
Keep in mind that this will only apply to servers which are generated by the Caddyfile; this means that the HTTP server created by
Automatic HTTPS
for HTTP->HTTPS redirects will not inherit these bind addresses. To work around this, make sure to declare an
http://
site (it can be empty, with no directives) so that it exists when the Caddyfile is adapted, to receive the bind addresses.
order
Assigns an order to HTTP handler directive(s). As HTTP handlers execute in a sequential chain, it is necessary for the handlers to be executed in the right order. Standard directives have
a pre-defined order
, but if using third-party HTTP handler modules, you'll need to define the order explicitly by either using this option or placing the directive in a
route
block
. Ordering can be described absolutely (
first
or
last
), or relatively (
before
or
after
) to another directive.
For example, to use the
replace-response
plugin
, you'd want to make sure its directive is ordered after
encode
so that it can perform replacements before the response is encoded (because responses flow up the handler chain, not down):
order replace after encode
storage
Configures Caddy's storage mechanism. The default is
file_system
. There are many other available
storage modules
provided as plugins.
For example, to change the file system's storage location:
storage file_system /path/to/custom/location
Customizing the storage module is typically needed when syncing Caddy's storage across multiple instances of Caddy to make sure they all use the same certificates and keys. See the
Automatic HTTPS section on storage
for more details.
storage_clean_interval
How often to scan storage units for old or expired assets and remove them. These scans exert lots of reads (and list operations) on the storage module, so choose a longer interval for large deployments. The value is a
duration value
. Default:
24h
.
Storage will always be cleaned when the process first starts. Then, a new cleaning will be started this duration after the previous cleaning started if the previous cleaning finished in less than half the time of this interval (otherwise next start will be skipped).
renew_interval
How often to scan all loaded, managed certificates for expiration, and trigger renewal if expired. Default:
10m
.
ocsp_interval
How often to check if OCSP staples need updating. Default:
1h
.
admin
Customizes the
admin API endpoint
. Accepts placeholders. If
off
, then the admin endpoint will be disabled. If disabled, config changes will be impossible without stopping and starting the server. Remember to use the
--address
CLI flag to specify the current admin endpoint when changing this value if the currently-running admin endpoint is not at the default address.
origins
configures the list of remotes/origins that are allowed to connect to the endpoint.
enforce_origin
enables enforcement of the Origin header. (This is different from enforcing origins generally, which is always done.)
persist_config
Controls whether the current JSON config should be persisted to the
configuration directory
, to avoid losing config changes performed via the admin API. Currently, only the
off
option is supported. By default, the config is persisted.
Configures named loggers. The name can be passed to indicate a specific logger for which to customize the behavior. If no name is specified, the behavior of the
default
logger is modified. Multiple loggers with different names can be configured by using the
log
multiple times. You can read more about the
default
logger and an explanation of
how logging works in Caddy
.
The differs from the
log
directive
, which only configures HTTP request logging (also known as access logs). The
log
global option shares its configuration structure with the directive (except for
include
and
exclude
), and complete documentation can be found on the directive's page.
output
configures where to write the logs. See the
log
directive
for complete documentation.
format
describes how to encode, or format, the logs. See the
log
directive
for complete documentation.
level
is the minimum entry level to log. Default:
INFO
.
include
specifies the log names to be included in this logger. For example, to include only logs emitted by the admin API, you would include
admin.api
. By default, this list is empty (i.e. all logs are included).
exclude
specifies the log names to be excluded from this logger. For example, to exclude only HTTP access logs, you would exclude
http.log.access
. By default, this list is empty (i.e. no logs are excluded).
The logger names that
include
and
exclude
accept depend on the modules used, and easiest way to discover them is from prior logs.
Here is an example logging as json all http access logs and admin logs to stdout:
log default {
output stdout
format json
include http.log.access admin.api
grace_period
Defines the grace period for shutting down HTTP servers (i.e. during config changes or when Caddy is stopping). During the grace period, no new connections are accepted, idle connections are closed, and active connections are impatiently waited upon to finish their requests. If clients do not finish their requests within the grace period, the server will be forcefully terminated to allow the reload to complete and free up resources. Accepts
duration values
. By default, the grace period is eternal, which means connections are never forcefully closed.
shutdown_delay
Defines a duration before the grace period during which a server that is going to be stopped continues to operate normally, except the
{http.shutting_down}
placeholder evaluates to
true
and
{http.time_until_shutdown}
gives the time until the grace period begins. This causes a delay if any server is being shut down as part of a config change and effectively schedules the change for a later time. It is useful for announcing to health checkers of this server's impending doom and to give time for a load balancer to move it out of the rotation; for example:
handle /health-check {
@goingDown vars {http.shutting_down} true
respond @goingDown "Bye-bye in {http.time_until_shutdown}" 503
respond 200
TLS Options
auto_https
Configure automatic HTTPS. There are a few modes to choose from:
off
: Disabled entirely. No certificate management or redirects.
disable_redirects
: Disable only HTTP-to-HTTPS redirects.
disable_certs
: Disable only certificate automation.
ignore_loaded_certs
: Automate certificates even for names which appear on manually-loaded certificates
See the
Automatic HTTPS
page for more details.
email
Your email address. Mainly used when creating an ACME account with your CA, and is highly recommended in case there are problems with your certificates.
Keep in mind that Let's Encrypt may send you emails about your certificate nearing expiry, but this may be misleading because Caddy may have chosen to use a different issuer (e.g. ZeroSSL) when renewing. Check your logs and/or the certificate itself (in your browser for example) to see which issuer was used, and that its expiry is still valid; if so, you may safely ignore the email from Let's Encrypt.
default_sni
Sets a default TLS ServerName for when clients do not use SNI in their ClientHello.
fallback_sni
If configured, the fallback becomes the TLS ServerName in the ClientHello if the original ServerName doesn't match any certificates in the cache. The uses for this are very niche; typically if a client is a CDN and passes through the ServerName of the downstream handshake but can accept a certificate with the origin's hostname instead, then you would set this as your origin's hostname. Note that Caddy must be managing a certificate for this name.
⚠️ Experimental
local_certs
Causes all certificates to be issued internally by default, rather than through a (public) ACME CA such as Let's Encrypt. This is useful in development environments.
skip_install_trust
Skips the attempts to install the local CA's root into the system trust store, as well as into Java and Mozilla Firefox trust stores.
acme_ca
Specifies the URL to the ACME CA's directory. It is strongly recommended to set this to Let's Encrypt's
staging endpoint
for testing or development. Default: ZeroSSL and Let's Encrypt's production endpoints.
Note that a globally-configured ACME CA may not apply to all sites; see the
hostname requirements
for using the default ACME issuer(s).
acme_ca_root
Specifies a PEM file that contains a trusted root certificate for ACME CA endpoints, if not in the system trust store.
acme_eab
Specifies an External Account Binding to use for all ACME transactions.
acme_dns
Configures the ACME DNS challenge provider to use for all ACME transactions. The tokens following the name of the provider set up the provider the same as if specified in the
tls
directive's
acme
issuer
.
on_demand_tls
Configures
On-Demand TLS
where it is enabled, but does not enable it (to enable it, use the
on_demand
subdirective of the
tls
directive
). Required for use in production environments, to prevent abuse.
ask
will cause Caddy to make an HTTP request to the given URL with a query string of
?domain=
containing the value of the domain name. If the endpoint returns a
2xx
status code, Caddy will be authorized to obtain a certificate for that name. Any other status code will result in cancelling issuance of the certificate.
The ask endpoint should return
as fast as possible
, in a few milliseconds, ideally. Typically, your endpoint should do a constant-time lookup in an database with an index by domain name; avoid loops. Avoid making DNS queries or other network requests.
interval
and
burst
allows
<n>
certificate operations within
<duration>
interval.
key_type
Specifies the type of key to generate for TLS certificates; only change this if you have a specific need to customize it. The possible values are:
ed25519
,
p256
,
p384
,
rsa2048
,
rsa4096
.
cert_issuer
Defines the issuer (or source) of TLS certificates. The tokens following the name of the issuer set up the issuer the same as if specified in the
tls
directive
. May be repeated if you wish to configure more than one issuer to try. They will be tried in the order they are defined.
ocsp_stapling
Can be set to
off
to disable OCSP stapling. Useful in environments where responders are not reachable due to firewalls.
preferred_chains
If your CA provides multiple certificate chains, you can use this option to specify which chain Caddy should prefer. Set one of the following options:
smallest
will tell Caddy to prefer chains with the fewest amount of bytes.
root_common_name
is a list of one or more common names; Caddy will choose the first chain that has a root that matches with at least one of the specified common names.
any_common_name
is a list of one or more common names; Caddy will choose the first chain that has an issuer that matches with at least one of the specified common names.
Note that specifying
preferred_chains
as a global option will affect all issuers if there isn't any
overriding issuer level config
.
Server Options
Customizes
HTTP servers
with settings that potentially span multiple sites and thus can't be rightly configured in site blocks. These options affect the listener/socket or other facilities beneath the HTTP layer.
Can be specified more than once with different
listener_address
values to configure different options per server. For example,
servers :443
will only apply to the server that is bound to the listener address
:443
. Omitting the listener address will apply the options to any remaining server.
Use the
caddy adapt
command to find the listen address for the servers in your Caddyfile.
For example, to configure different options for the servers on ports
:80
and
:443
, you would specify two
servers
blocks:
servers
:443
{
listener_wrappers
{
http_redirect
servers
:80
{
protocols
h1
h2c
If you are using the
bind
directive
or the
default_bind
global option
, the
listener_address
MUST
match the bind address combined with the port of the site block, otherwise the settings won't be applied. For example:
# This will NOT match the server, bind address missing
servers
:8080
{
name
private
# This will work because it's an exact match
servers
192.168.1.2
:
8080
{
name
public
:8080
{
bind
127
.0.0.1
:8080
{
bind
192
.168.1.2
A custom name to assign to this server. Usually helpful to identify a server by its name in logs and metrics. If not set, Caddy will define it dynamically using a
srvX
pattern, where
X
starts with 0 and increments based on the number of servers in the config.
Keep in mind there's a caveat if you want to name your HTTP server and are using Auto-HTTPS. The server name config doesn't persist past adapting the config, and Auto-HTTPS happens at runtime, from the JSON config.
To overcome this, you'll need to create an empty
:80
or
http://
site block and set this option. With that Auto-HTTPS will add its redirect routes to that server. For example:
servers
:443
{
name
https
servers
:80
{
name
http
example.com
{
http://
{
listener_wrappers
Allows configuring
listener wrappers
, which can modify the behaviour of the socket listener. They are applied in the given order.
There is a special no-op
tls
listener wrapper provided as a standard module which marks where TLS should be handled in the chain of listener wrappers. It should only be used if another listener wrapper must be placed in front of the TLS handshake.
The standard distribution of Caddy includes the
http_redirect
listener wrapper, which can look at the first few bytes of an incoming request to determine if it's likely HTTP (instead of TLS), and trigger an HTTP->HTTPS redirect on the same port but using the
https://
scheme. It must be placed
before
the
tls
listener wrapper. For example:
listener_wrappers {
http_redirect
Also included is the
proxy_protocol
listener wrapper (prior to v2.7.0 it was only available via a plugin), which enables
PROXY protocol
parsing (popularized by HAProxy). This must be used
before
the
tls
listener wrapper since it parses plaintext data at the start of the connection:
listener_wrappers {
proxy_protocol {
timeout 2s
allow 192.168.86.1/24 192.168.86.1/24
timeouts
read_body
is a
duration value
that sets how long to allow a read from a client's upload. Setting this to a short, non-zero value can mitigate slowloris attacks, but may also affect legitimately slow clients. Defaults to no timeout.
read_header
is a
duration value
that sets how long to allow a read from a client's request headers. Defaults to no timeout.
write
is a
duration value
that sets how long to allow a write to a client. Note that setting this to a small value when serving large files may negatively affect legitimately slow clients. Defaults to no timeout.
idle
is a
duration value
that sets the maximum time to wait for the next request when keep-alives are enabled. Defaults to 5 minutes to help avoid resource exhaustion.
trusted_proxies
Allows configuring IP ranges (CIDRs) of proxy servers from which requests should be trusted. By default, no proxies are trusted.
Enabling this causes trusted requests to have the
real
client IP parsed from HTTP headers (by default,
X-Forwarded-For
; see
client_ip_headers
to configure other headers). If trusted, the client IP is added to
access logs
, is available as a
{client_ip}
placeholder
, and allows the use of the
client_ip
matcher
. If the request is not from a trusted proxy, then the client IP is set to the remote IP address of the direct incoming connection.
Some matchers or handlers may use the trust status of the request to make additional decisions. For example, if trusted, the
reverse_proxy
handler will proxy and augment the sensitive
X-Forwarded-*
request headers.
Currently, only the
static
IP source module
is included with the standard distribution of Caddy, but this can be
extended
with plugins to maintain a dynamic list of IP ranges.
static
Takes a static (unchanging) list of IP ranges (CIDRs) to trust.
As a shortcut,
private_ranges
can be used to match all private IPv4 and IPv6 ranges. It's the same as specifying all of these ranges:
192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 127.0.0.1/8 fd00::/8 ::1
trusted_proxies static [private_ranges] <ranges...>
Here's a complete example, trusting an example IPv4 range and an IPv6 range:
servers
{
trusted_proxies
static
12
.34.56.0/24
1200
:ab00::/32
Pairing with
trusted_proxies
, allows configuring which headers to use to determine the client's IP address. By default, only
X-Forwarded-For
is considered. Multiple header fields can be specified, in which case the first non-empty header value is used.
metrics
Enables Prometheus metrics collection; necessary before scraping metrics. Note that metrics reduce performance on really busy servers. (Our community is working on improving this. Please get involved!)
The maximum size to parse from a client's HTTP request headers. If the limit is exceeded, the server will respond with HTTP status
431 Request Header Fields Too Large
. It accepts all formats supported by
go-humanize
. By default, the limit is
1MB
.
enable_full_duplex
Enable full-duplex communication for HTTP/1 requests. Only has an effect if Caddy was built with Go 1.21 or later.
For HTTP/1 requests, the Go HTTP server by default consumes any unread portion of the request body before beginning to write the response, preventing handlers from concurrently reading from the request and writing the response. Enabling this option disables this behavior and permits handlers to continue to read from the request while concurrently writing the response.
For HTTP/2 requests, the Go HTTP server always permits concurrent reads and responses, so this option has no effect.
Test thoroughly with your HTTP clients, as some older clients may not support full-duplex HTTP/1 which can cause them to deadlock. See
golang/go#57786
for more info.
⚠️ This is an experimental feature. Subject to change or removal.
log_credentials
Since Caddy v2.5, by default, headers with potentially sensitive information (
Cookie
,
Set-Cookie
,
Authorization
and
Proxy-Authorization
) will be logged with empty values in access logs (see the
log
directive
).
If you wish to
not
have these headers redacted, you may enable the
log_credentials
option.
protocols
The space-separated list of HTTP protocols to support. Default:
h1 h2 h3
. Accepted values are:
h1
for HTTP/1.1
h2
For HTTP/2
h2c
for HTTP/2 over cleartext
h3
for HTTP/3
Currently, enabling HTTP/2 (including H2C) necessarily implies enabling HTTP/1.1 because the Go standard library does not let us disable HTTP/1.1 when using its HTTP server. However, either HTTP/1.1 or HTTP/3 can be enabled independently.
Note that H2C ("Cleartext HTTP/2" or "H2 over TCP") and HTTP/3 are not implemented by the Go standard library, so some functionality or features may be limited. We recommend against enabling H2C unless it is absolutely necessary for your application.
strict_sni_host
Enabling this requires that a request's
Host
header matches the value of the
ServerName
sent by the client's TLS ClientHello, a necessary safeguard when using TLS client authentication. If there's a mismatch, HTTP status
421 Misdirected Request
response is written to the client.
This option will automatically be turned on if
client authentication
is configured. This disallows TLS client auth bypass (domain fronting) which could otherwise be exploited by sending an unprotected SNI value during a TLS handshake, then putting a protected domain in the Host header after establishing connection. This behavior is a safe default, but you may explicitly turn it off with
insecure_off
; for example in the case of running a proxy where domain fronting is desired and access is not restricted based on hostname.
PKI Options
The PKI (Public Key Infrastructure) app is the foundation for Caddy's
Local HTTPS
and
ACME server
features. The app defines certificate authorities (CAs) which are capable of signing certificates.
The default CA ID is
local
. If the ID is omitted when configuring the
ca
, then
local
is assumed.
The user-facing name of the certificate authority. Default:
Caddy Local Authority
root_cn
The name to put in the CommonName field of the root certificate. Default:
{pki.ca.name} - {time.now.year} ECC Root
The name to put in the CommonName field of the intermediate certificates. Default:
{pki.ca.name} - ECC Intermediate
The
duration
for which intermediate certificates are valid. This value must be less than the lifetime of the root cert (
3600d
or 10 years). Default:
7d
. It is recommended not to change this unless absolutely necessary.
A key pair (certificate and private key) to use as the root for the CA. If not specified, one will be generated and managed automatically.
format
is the format in which the certificate and private key are provided. Currently, only
pem_file
is supported, which is the default, so this field is optional.
cert
is the certificate. This should be the path to a PEM file, when using
pem_file
format.
key
is the private key. This should be the path to a PEM file, when using
pem_file
format.
A key pair (certificate and private key) to use as the intermediate for the CA. If not specified, one will be generated and managed automatically.
format
is the format in which the certificate and private key are provided. Currently, only
pem_file
is supported, which is the default, so this field is optional.
cert
is the certificate. This should be the path to a PEM file, when using
pem_file
format.
key
is the private key. This should be the path to a PEM file, when using
pem_file
format.
Event Options
Caddy modules emit events when interesting things happen (or are about to happen).
Events typically include a metadata payload. The best way to learn about events and their payloads is from each module's documentation, but you may also see the events and their data payloads by enabling the
debug
global option
and reading the logs.
Binds an event handler to the named event. Specify the name of the event handler module, followed by its configuration.
For example, to run a command after a certificate is obtained (
third-party plugin
required), with a part of the event payload being passed to the script using a placeholder:
events
{
on
cert_obtained
exec
./my-script.sh
{event.data.certificate_path}
Events
These standard events are emitted by Caddy:
tls
events
reverse_proxy
events
Plugins may also emit events, so check their documentation for details.