1. Caddy version (caddy version
):
Working to switch to:
v2.2.0 h1:sMUFqTbVIRlmA8NkFnNt9l7s0e+0gw+7GPIrhty905A=
Currently on:
Caddy v1.0.0 (h1:KI6RPGih2GFzWRPG8s9clKK28Ns4ZlVMKR/v7mxq6+c=)
2. How I run Caddy:
a. System environment:
- Ubuntu 20.04
- systemd
- local network only
b. Command:
Currently:
ExecStart=/usr/local/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/www/caddy/error.lan
Plan to switch to:
ExecStart=/usr/local/bin/caddy run -config=/etc/caddy/Caddyfile
c. Service/unit/compose file:
[Unit]
Description=Caddy HTTP/2 web server
Documentation=https://caddyserver.com/docs
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service
[Service]
Restart=on-abnormal
; User and group the process will run as.
User=www-data
Group=www-data
; Letsencrypt-issued certificates will be written to this directory.
Environment=CADDYPATH=/etc/caddy/ssl/
; Always set "-root" to something safe in case it gets forgotten in the Caddyfile.
ExecStart=/usr/local/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/www/caddy/error.lan
ExecReload=/bin/kill -USR1 $MAINPID
; Use graceful shutdown with a reasonable timeout
KillMode=mixed
KillSignal=SIGQUIT
TimeoutStopSec=5s
; Limit the number of file descriptors; see `man systemd.exec` for more limit settings.
LimitNOFILE=1048576
; Unmodified caddy is not expected to use more than that.
LimitNPROC=512
; Use private /tmp and /var/tmp, which are discarded after caddy stops.
PrivateTmp=true
; Use a minimal /dev (May bring additional security if switched to 'true', but it may not work on Raspberry Pi's or other devices, so it has been disabled in this dist.)
PrivateDevices=true
; Hide /home, /root, and /run/user. Nobody will steal your SSH-keys.
ProtectHome=true
; Make /usr, /boot, /etc and possibly some more folders read-only.
ProtectSystem=full
; … except /etc/caddy/ssl, because we want Letsencrypt-certificates there.
; except log directory because want to write logs there
; This merely retains r/w access rights, it does not add any new. Must still be writable on the host!
ReadWriteDirectories=/etc/caddy/ssl/
ReadWriteDirectories=/var/log/caddy/rclone-restic-rest/
; The following additional security directives only work with systemd v229 or later.
; They further restrict privileges that can be gained by caddy. Uncomment if you like.
; Note that you may have to add capabilities required by any plugins in use.
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
but plan to revise to:
[Unit]
Description=Caddy HTTP/2 web server
Documentation=https://caddyserver.com/docs
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service
[Service]
Restart=on-abnormal
; User and group the process will run as.
User=www-data
Group=www-data
; Letsencrypt-issued certificates will be written to this directory.
Environment=CADDYPATH=/etc/caddy/ssl/
; Your service file will vary depending on if you use caddy run or caddy start.
; Probably best to use run.
ExecStart=/usr/local/bin/caddy run -config=/etc/caddy/Caddyfile
; v2 doesn’t implement USR1.
; Use the caddy reload command or the API instead to load new configuration.
ExecReload=/usr/local/bin/caddy reload -config=/etc/caddy/Caddyfile
; Use graceful shutdown with a reasonable timeout
KillMode=mixed
KillSignal=SIGQUIT
TimeoutStopSec=5s
; Limit the number of file descriptors; see `man systemd.exec` for more limit settings.
LimitNOFILE=1048576
; Unmodified caddy is not expected to use more than that.
LimitNPROC=512
; Use private /tmp and /var/tmp, which are discarded after caddy stops.
PrivateTmp=true
; Use a minimal /dev (May bring additional security if switched to 'true', but it may not work on Raspberry Pi's or other devices, so it has been disabled in this dist.)
PrivateDevices=true
; Hide /home, /root, and /run/user. Nobody will steal your SSH-keys.
ProtectHome=true
; Make /usr, /boot, /etc and possibly some more folders read-only.
ProtectSystem=full
; … except /etc/caddy/ssl, because we want Letsencrypt-certificates there.
; except log directory because want to write logs there
; This merely retains r/w access rights, it does not add any new. Must still be writable on the host!
ReadWriteDirectories=/etc/caddy/ssl/
ReadWriteDirectories=/var/log/caddy/rclone-restic-rest/
; The following additional security directives only work with systemd v229 or later.
; They further restrict privileges that can be gained by caddy. Uncomment if you like.
; Note that you may have to add capabilities required by any plugins in use.
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
d. My complete Caddyfile or JSON config:
This is my old Caddyfile. My issue is finding suitable adaptions in v2 for for Caddy v1’s limits
and timeouts
:
192.168.1.106:8889 {
tls /etc/caddy/ssl/server-bundle.pem /etc/caddy/ssl/end_device-key.pem {
protocols tls1.2 tls1.3
}
# Reverse proxy to rclone restic rest service
proxy / localhost:8080 {
transparent
max_conns 1024
}
root /var/www/caddy/rclone-restic-rest/
header / {
# Enable HTTP Strict Transport Security (HSTS) to force clients to always
# connect via HTTPS (do not use if only testing)
# Strict-Transport-Security "max-age=31536000;"
# Enable cross-site filter (XSS) and tell browser to block detected attacks
X-XSS-Protection "1; mode=block"
# Prevent some browsers from MIME-sniffing a response away from the declared Content-Type
X-Content-Type-Options "nosniff"
# Disallow the site to be rendered within a frame (clickjacking protection)
X-Frame-Options "DENY"
# Hide server header field
-Server
# Disable caching since https
# The cache should not store anything about the client request or server response.
Cache-Control "no-store"
Pragma "no-cache"
}
# Better manage server connectivity in the face of buggy or malicious clients.
timeouts {
read 10s # Maximum duration for reading the entire request, including the body.
header 10s # The amount of time allowed to read request headers.
write 10s # The maximum duration before timing out writes of the response.
idle 2m # The maximum time to wait for the next request (when using keep-alive).
}
# Limit the HTTP header and body sizes to reasonable values
# Increase if legitmate traffic results in HTTP 413 errors
limits {
header 4kb
#body / 10mb
}
# use gzip compression if the client supports it.
gzip
log / /var/log/caddy/rclone-restic-rest/access.log {
rotate_size 5 # Rotate after the log file reaches this size (in megabytes)
rotate_age 90 # Keep rotated files for this many days
rotate_keep 40 # Keep at most this many log files (older files get pruned)
rotate_compress # compress rotated log files. gzip is the only format supported.
}
errors /var/log/caddy/rclone-restic-rest/error.log {
rotate_size 5 # Rotate after the log file reaches this size (in megabytes)
rotate_age 90 # Keep rotated files for this many days
rotate_keep 40 # Keep at most this many log files (older files get pruned)
rotate_compress # compress rotated log files. gzip is the only format supported.
}
}
192.168.1.106:9089 {
tls /etc/caddy/ssl/prometheus-bundle.pem /etc/caddy/ssl/prometheus-key.pem {
protocols tls1.3
}
# Reverse proxy to Prometheus
proxy / localhost:9090 {
transparent
max_conns 1024
}
root /var/www/caddy/prometheus/
basicauth / name password
header / {
# Enable HTTP Strict Transport Security (HSTS) to force clients to always
# connect via HTTPS (do not use if only testing)
# Strict-Transport-Security "max-age=31536000;"
# Enable cross-site filter (XSS) and tell browser to block detected attacks
X-XSS-Protection "1; mode=block"
# Prevent some browsers from MIME-sniffing a response away from the declared Content-Type
X-Content-Type-Options "nosniff"
# Disallow the site to be rendered within a frame (clickjacking protection)
X-Frame-Options "DENY"
# Hide server header field
-Server
# Disable caching since https
# The cache should not store anything about the client request or server response.
Cache-Control "no-store"
Pragma "no-cache"
}
# Better manage server connectivity in the face of buggy or malicious clients.
timeouts {
read 10s # Maximum duration for reading the entire request, including the body.
header 10s # The amount of time allowed to read request headers.
write 10s # The maximum duration before timing out writes of the response.
idle 2m # The maximum time to wait for the next request (when using keep-alive).
}
# Limit the HTTP header and body sizes to reasonable values
# Increase if legitmate traffic results in HTTP 413 errors
limits {
header 4kb
body / 10mb
}
# use gzip compression if the client supports it.
gzip
log / /var/log/caddy/prometheus/access.log {
rotate_size 5 # Rotate after the log file reaches this size (in megabytes)
rotate_age 90 # Keep rotated files for this many days
rotate_keep 40 # Keep at most this many log files (older files get pruned)
rotate_compress # compress rotated log files. gzip is the only format supported.
}
errors /var/log/caddy/prometheus/error.log {
rotate_size 5 # Rotate after the log file reaches this size (in megabytes)
rotate_age 90 # Keep rotated files for this many days
rotate_keep 40 # Keep at most this many log files (older files get pruned)
rotate_compress # compress rotated log files. gzip is the only format supported.
}
}
For completeness, here’s what I have in mind for v2. However, I realize I’ll have to adapt to JSON and make some additional edits/additions to achieve parity.
192.168.1.106:8889 {
# https://caddyserver.com/docs/caddyfile/directives/tls
tls /etc/caddy/ssl/server-bundle.pem /etc/caddy/ssl/end_device-key.pem {
protocols tls1.2 tls1.3
}
# https://caddyserver.com/docs/caddyfile/directives/reverse_proxy
# Reverse proxy to rclone restic rest service
reverse_proxy localhost:8080 {
#### max_conns 1024
#### max_conns isn't in Caddyfile anymore but is keep_alive.max_idle_conns_per_host in JSON
}
root * /var/www/caddy/rclone-restic-rest/
# https://caddyserver.com/docs/caddyfile/directives/header
header {
# enable HSTS
# Enable HTTP Strict Transport Security (HSTS) to force clients to always
# connect via HTTPS (do not use if only testing)
# Strict-Transport-Security "max-age=31536000;"
# disable clients from sniffing the media type
# Prevent some browsers from MIME-sniffing a response away from the declared Content-Type
X-Content-Type-Options "nosniff"
# clickjacking protection
# Disallow the site to be rendered within a frame (clickjacking protection)
X-Frame-Options "DENY"
# keep referrer data off of HTTP connections
Referrer-Policy no-referrer-when-downgrade
# Enable cross-site filter (XSS) and tell browser to block detected attacks
X-XSS-Protection "1; mode=block"
# Hide server header field
-Server
# Disable caching since https
# The cache should not store anything about the client request or server response.
Cache-Control "no-store"
Pragma "no-cache"
}
# Better manage server connectivity in the face of buggy or malicious clients.
###timeouts {
### read 10s # Maximum duration for reading the entire request, including the body.
### header 10s # The amount of time allowed to read request headers.
### write 10s # The maximum duration before timing out writes of the response.
### idle 2m # The maximum time to wait for the next request (when using keep-alive).
###}
### In JSON
# read_timeout
# read_header_timeout
# write_timeout
# idle_timeout
#### Limit the HTTP header and body sizes to reasonable values
#### Increase if legitmate traffic results in HTTP 413 errors
###limits {
### header 4kb
### #body / 10mb
###}
# think it is max_header_bytes and request_body with max_size.
# https://caddyserver.com/docs/json/apps/http/servers/max_header_bytes/
# https://caddyserver.com/docs/json/apps/http/servers/routes/handle/request_body/
# https://caddyserver.com/docs/caddyfile/directives/encode
# use gzip compression and Zstandard if the client supports it.
encode zstd gzip
# https://caddyserver.com/docs/caddyfile/directives/log
log {
output file /var/log/caddy/rclone-restic-rest/caddy.log {
roll_size 5mb # Rotate after the log file reaches this size (in megabytes)
roll_keep 40 # Keep at most this many log files (older files get pruned)
roll_keep_for 90d # Keep rotated files for this many days
}
}
}
192.168.1.106:9089 {
tls /etc/caddy/ssl/prometheus-bundle.pem /etc/caddy/ssl/prometheus-key.pem {
protocols tls1.3
}
# Reverse proxy to Prometheus
proxy localhost:9090
root * /var/www/caddy/prometheus/
# Use https://caddyserver.com/docs/command-line#caddy-hash-password
basicauth / Bob JDJhJDEwJEVCNmdaNEg2Ti5iejRMYkF3MFZhZ3VtV3E1SzBWZEZ5Q3VWc0tzOEJwZE9TaFlZdEVkZDhX
# https://caddyserver.com/docs/caddyfile/directives/header
header {
# enable HSTS
# Enable HTTP Strict Transport Security (HSTS) to force clients to always
# connect via HTTPS (do not use if only testing)
# Strict-Transport-Security "max-age=31536000;"
# disable clients from sniffing the media type
# Prevent some browsers from MIME-sniffing a response away from the declared Content-Type
X-Content-Type-Options "nosniff"
# clickjacking protection
# Disallow the site to be rendered within a frame (clickjacking protection)
X-Frame-Options "DENY"
# keep referrer data off of HTTP connections
Referrer-Policy no-referrer-when-downgrade
# Enable cross-site filter (XSS) and tell browser to block detected attacks
X-XSS-Protection "1; mode=block"
# Hide server header field
-Server
# Disable caching since https
# The cache should not store anything about the client request or server response.
Cache-Control "no-store"
Pragma "no-cache"
}
#### Better manage server connectivity in the face of buggy or malicious clients.
###timeouts {
### read 10s # Maximum duration for reading the entire request, including the body.
### header 10s # The amount of time allowed to read request headers.
### write 10s # The maximum duration before timing out writes of the response.
### idle 2m # The maximum time to wait for the next request (when using keep-alive).
###}
#### Limit the HTTP header and body sizes to reasonable values
#### Increase if legitmate traffic results in HTTP 413 errors
###limits {
### header 4kb
### body / 10mb
###}
# https://caddyserver.com/docs/caddyfile/directives/encode
# use gzip compression and Zstandard if the client supports it.
encode zstd gzip
# https://caddyserver.com/docs/caddyfile/directives/log
log {
output file /var/log/caddy/rclone-restic-rest/caddy.log {
roll_size 5mb # Rotate after the log file reaches this size (in megabytes)
roll_keep 40 # Keep at most this many log files (older files get pruned)
roll_keep_for 90d # Keep rotated files for this many days
}
}
}
3. The problem I’m having:
Find a way to get a similarly secure Caddy 2 config. Namely, I’m looking to find suitable replacements for Caddy v1’s limits
and timeouts
:
# Limit the HTTP header and body sizes to reasonable values
# Increase if legitimate traffic results in HTTP 413 errors
limits {
header 4kb
body / 10mb
}
and
# Better manage server connectivity in the face of buggy or malicious clients.
timeouts {
read 10s # Maximum duration for reading the entire request, including the body.
header 10s # The amount of time allowed to read request headers.
write 10s # The maximum duration before timing out writes of the response.
idle 2m # The maximum time to wait for the next request (when using keep-alive).
}
For limits header, I think max_header_bytes may work. However, I’m not sure what to use the body portion. Maybe request_body? Am I on the right track?
For timeouts, I’m fairly certain the following are suitable alternatives:
Please let me know if that’s incorrect.
4. Error messages and/or full log output:
N/A
5. What I already tried:
Reading through the tutorials, upgrading to Caddy 2 article, Caddyfile docs, and JSON config structure docs. I’ve also searched the forum and Github.
6. Links to relevant resources:
These were seem related:
- Max_size of request body doesn't respond with HTTP 413 code
- Rate limit or Limit Connection Per IP Caddy 2 · Issue #3467 · caddyserver/caddy · GitHub
These links were also above. Including here for completeness: