Logging Configuration
Caddy provides zero-allocation, high-performance structured logging using Zap. Logs can be customized with different outputs, encoders, and filters.
Default Logging
By default, Caddy logs to stderr at INFO level:
2024/01/15 10:30:00.123 [INFO] http.log.access handled request
Log Configuration
Custom Log Output
{
"logging": {
"logs": {
"default": {
"writer": {
"output": "file",
"filename": "/var/log/caddy/access.log"
},
"encoder": {
"format": "json"
},
"level": "INFO"
}
}
}
}
Log Levels
Available log levels (from most to least verbose):
- DEBUG - Detailed debugging information
- INFO - General informational messages (default)
- WARN - Warning messages
- ERROR - Error messages
- PANIC - Panic messages (causes panic)
- FATAL - Fatal messages (causes exit)
Use environment variables for dynamic log levels: level {$LOG_LEVEL}
Log Encoders
JSON Encoder
Structured JSON output:
{
"level": "info",
"ts": 1705318200.123,
"logger": "http.log.access",
"msg": "handled request",
"request": {
"method": "GET",
"uri": "/index.html",
"proto": "HTTP/2.0"
},
"duration": 0.123,
"size": 4096,
"status": 200
}
Console Encoder
Human-readable output:
2024-01-15T10:30:00.123Z INFO http.log.access handled request
{
"encoder": {
"format": "console",
"time_format": "2006/01/02 15:04:05.000",
"level_format": "color",
"message_key": "msg",
"time_key": "ts"
}
}
Log Writers
File Writer
{
"writer": {
"output": "file",
"filename": "/var/log/caddy/access.log",
"roll": true,
"roll_size_mb": 100,
"roll_keep": 10,
"roll_keep_days": 90
}
}
Network Writer
Send logs over the network:
{
"writer": {
"output": "net",
"address": "localhost:5140",
"dial_timeout": "10s"
}
}
Standard Streams
{
log {
output stdout # or stderr (default)
}
}
Discard
Disable logging:
{
log {
output discard
}
}
Log Filtering
Include Specific Modules
Only log from specific modules:
{
"logs": {
"admin_only": {
"include": ["admin.api", "admin"]
}
}
}
Exclude Modules
Filter out specific modules:
{
"logs": {
"no_access": {
"exclude": ["http.log.access"]
}
}
}
Complex Filtering
Combine include and exclude:
{
"logs": {
"http_without_access": {
"include": ["http"],
"exclude": ["http.log.access"],
"level": "WARN"
}
}
}
When both include and exclude are set, longer namespaces have priority. The lists must be mutually exclusive superset/subset pairs.
HTTP Access Logs
Configure access logs per site:
{
"apps": {
"http": {
"servers": {
"srv0": {
"logs": {
"logger_names": {
"example.com": "example_log"
}
}
}
}
}
},
"logging": {
"logs": {
"example_log": {
"writer": {
"output": "file",
"filename": "/var/log/caddy/example.com.log"
},
"encoder": {
"format": "json"
}
}
}
}
}
Access Log Fields
Customize which fields to log:
example.com {
log {
format filter {
wrap json
fields {
request>remote_ip ip
request>proto delete
common_log delete
}
}
}
}
Sampling
Reduce log volume on high-traffic servers:
{
"logging": {
"logs": {
"default": {
"sampling": {
"interval": "1s",
"first": 100,
"thereafter": 100
}
}
}
}
}
Sampling logs the first N entries per interval, then 1 in M thereafter. This drastically reduces log volume while preserving representative samples.
Include file and line numbers in logs:
{
"logs": {
"debug_log": {
"level": "DEBUG",
"with_caller": true,
"with_caller_skip": 0,
"with_stacktrace": "ERROR"
}
}
}
Multiple Logs
Configure different logs for different purposes:
{
# Access logs
log access {
include http.log.access
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 10
}
format json
}
# Error logs only
log errors {
include http
exclude http.log.access
output file /var/log/caddy/errors.log {
roll_size 10mb
roll_keep 5
}
level ERROR
format json
}
# Admin logs
log admin {
include admin
output file /var/log/caddy/admin.log
level INFO
}
}
Sink Log
Configure the sink for stdlib logger output:
{
"logging": {
"sink": {
"writer": {
"output": "file",
"filename": "/var/log/caddy/sink.log"
}
}
}
}
The sink captures logs from Go’s standard library logger, used by dependencies not built specifically for Caddy.
Complete Example
{
# Default log (stderr, console format for development)
log {
output stdout
format console {
time_format "2006/01/02 15:04:05"
level_format color
}
level DEBUG
}
# Production access logs
log access {
include http.log.access
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 10
roll_keep_days 90
}
format json
level INFO
}
# Error logs with stack traces
log errors {
include http
exclude http.log.access
output file /var/log/caddy/errors.log {
roll_size 10mb
roll_keep 5
}
format json
level ERROR
with_stacktrace ERROR
}
# Admin API logs
log admin {
include admin
output file /var/log/caddy/admin.log
format json
}
}
# Per-site access logging
example.com {
log {
output file /var/log/caddy/sites/example.com.log {
roll_size 50mb
roll_keep 7
}
format json
}
reverse_proxy backend:8080
}
Log Module Names
Common logger names for filtering:
http - All HTTP-related logs
http.log.access - HTTP access logs
http.handlers.* - HTTP handler logs
http.handlers.reverse_proxy - Reverse proxy logs
http.handlers.file_server - File server logs
admin - Admin endpoint logs
admin.api - Admin API logs
tls - TLS/certificate logs
tls.issuance - Certificate issuance logs
Best Practices
Use JSON in production - Easier to parse and analyze
Implement log rotation - Prevent disk space issues
Set appropriate levels - DEBUG for development, INFO for production
Filter by module - Separate access logs from errors
Enable sampling - On high-traffic servers to reduce volume
Monitor log sizes - Set up alerts for unusual growth
Verbose logging (DEBUG level) can impact performance and generate large volumes of logs. Use sparingly in production.