Logs¶
Every request handled by the webserver is logged for you, so you can debug issues and see who accessed your site.
Access logs¶
You'll find your webserver's access log at ~/logs/caddy, which resolves to /var/log/caddy-userlogs/$USER.
[isabell@moondust ~]$ tail --follow=name ~/logs/caddy/access.log
{"level":"info","ts":"2026-07-11T11:02:18.428+0200","logger":"http.log.access.[...]","msg":"handled request","request":{"client_ip":"192.0.2.100","proto":"HTTP/2.0","method":"GET","host":"isabell.uber.space","uri":"/robots.txt","headers":{"User-Agent":["[...]"]}},"bytes_read":0,"user_id":"","duration":0.002604887,"size":512,"status":200}
Always on
There is currently no way to disable this log.
Each line is a JSON object. The most relevant fields are:
{
"ts": "2026-07-11T11:02:18.428+0200",
"request": {
"client_ip": "192.0.2.100",
"proto": "HTTP/2.0",
"method": "GET",
"host": "isabell.uber.space",
"uri": "/robots.txt"
},
"status": 200,
"size": 512,
"duration": 0.002604887
}
You can use jq to filter and format the log, for example to only show the timestamp, method, path and status code:
[isabell@moondust ~]$ tail --follow=name ~/logs/caddy/access.log | jq --unbuffered --raw-output '[.ts, .request.method, .request.uri, .status] | @tsv'
2026-07-11T11:02:18.428+0200 GET /robots.txt 200
Apache-style logs¶
Some tools expect the Apache combined log format. You can use jq to convert the live output:
[isabell@moondust ~]$ tail --follow=name ~/logs/caddy/access.log | jq --unbuffered --raw-output '
def apache_time:
capture("^(?<date>[0-9-]+T[0-9:]+)(?:\\.[0-9]+)?(?<zone>[+-][0-9]{4})$")
| ((.date + "Z" | fromdateiso8601 | strftime("%d/%b/%Y:%H:%M:%S")) + " " + .zone);
[
.request.client_ip,
"-",
((.user_id | select(length > 0)) // "-"),
("[" + (.ts | apache_time) + "]"),
("\"" + .request.method + " " + .request.uri + " " + .request.proto + "\""),
(.status | tostring),
(.size | if . == 0 then "-" else tostring end),
("\"" + (.request.headers.Referer[0] // "-") + "\""),
("\"" + (.request.headers["User-Agent"][0] // "-") + "\"")
]
| join(" ")'
192.0.2.100 - - [11/Jul/2026:11:02:18 +0200] "GET /robots.txt HTTP/2.0" 200 512 "-" "[...]"
This only reformats the command's output. The original log remains unchanged in structured JSON and can still be filtered and parsed directly.