1. The problem Iβm having:
Im trying to use my caddy config along with cloudflare tunnel to access my site. So far i can see only the index.html page is loading for me however the css/js in different directories are getting a HTTP 404 error
Caddy is build with 2 modules
xcaddy build --with github.com/ggicci/caddy-jwt --with github.com/caddy-dns/cloudflare
Caddy config
{
order jwtauth before reverse_proxy
log {
level debug
format json
output stdout
}
}
domain.com:8071 {
bind localhost
encode gzip
tls {
dns cloudflare abcd
}
route /ws {
jwtauth {
sign_key abcd=base64encoded
sign_alg HS256
user_claims name
from_query token
}
reverse_proxy localhost:8090 {
header_up X-User {http.auth.user.id}
# header_up Sec-WebSocket-Key {http.request.uuid}
header_up Upgrade websocket
header_up Connection Upgrade
}
}
route /css/* {
file_server
root * /etc/caddy/web
header {
Cache-Control "public, max-age=31536000"
}
}
@js path /js/*
handle @js {
root * /etc/caddy/web
file_server
header {
Cache-Control "public, max-age=31536000"
}
}
route / {
file_server {
root /etc/caddy/web
index index.html
}
header / {
Cache-Control "public, max-age=31536000" # Cache for 1 year
}
}
route /* {
reverse_proxy localhost:8091
}
My cloudflare tunnel is configured for https://localhost:8071
. Whenever i try to access https://domain.com , i can access the html page from file_server
$ curl -Lv https://domain.com
* Host domain.com:443 was resolved.
* IPv6: (none)
* IPv4: 104.21.16.169, 172.67.214.223
* Trying 104.21.16.169:443...
* schannel: disabled automatic use of client certificate
* Connected to domain.com (104.21.16.169) port 443
* using HTTP/1.x
> GET / HTTP/1.1
> Host: domain.com
> User-Agent: curl/8.12.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Date: Sat, 19 Apr 2025 16:34:08 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Alt-Svc: h3=":443"; ma=86400
< Last-Modified: Sat, 19 Apr 2025 11:10:58 GMT
< Server: cloudflare
< Vary: Accept-Encoding
< Cf-Cache-Status: DYNAMIC
< CF-RAY: 932dcec18b7c85ae-BOM
<
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>domain</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<div class="container">
<h1>Welcome to domain</h1>
<button type="button" id="loginButton" class="butta" onclick="window.location.href='/login'">Login</button>
<button type="button" id="signupButton" class="butta" onclick="window.location.href='/signup'">Signup</button>
</div>
</body>
</html>* Connection #0 to host domain.com left intact
But you see it also requires the ./css/index.css
in that html response. That however never loads and i always get a HTTP 404. Also i require .css/chat.css
. When i try to load that I get same HTTP 404
$ curl -Lv https://domain.com/css/chat.css
* Host domain.com:443 was resolved.
* IPv6: (none)
* IPv4: 172.67.214.223, 104.21.16.169
* Trying 172.67.214.223:443...
* schannel: disabled automatic use of client certificate
* Connected to domain.com (172.67.214.223) port 443
* using HTTP/1.x
> GET /css/chat.css HTTP/1.1
> Host: domain.com
> User-Agent: curl/8.12.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 404 Not Found
< Date: Sat, 19 Apr 2025 16:40:37 GMT
< Content-Length: 0
< Connection: keep-alive
< Server: cloudflare
< Alt-Svc: h3=":443"; ma=86400
< Cache-Control: max-age=14400
< Cf-Cache-Status: EXPIRED
< CF-RAY: 932dd83d38f580b5-BOM
<
* Connection #0 to host domain.com left intact
Here is the corresponding log which is generated at caddy.
{"level":"info","ts":1745074774.0660818,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"debug","ts":1745074780.9104924,"logger":"events","msg":"event","name":"tls*get_certificate","id":"08ba3d16-0902-44bc-941e-3654eef92034","origin":"tls","data":{"client_hello":{"CipherSuites":[49195,49199,49196,49200,52393,52392,49161,49171,49162,49172,49170,4865,4866,4867],"ServerName":"domain.com","SupportedCurves":[29,23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[2052,1027,2055,2053,2054,1025,1281,1537,1283,1539,513,515],"SupportedProtos":null,"SupportedVersions":[772,771],"RemoteAddr":{"IP":"127.0.0.1","Port":43386,"Zone":""},"LocalAddr":{"IP":"127.0.0.1","Port":8071,"Zone":""}}}}
{"level":"debug","ts":1745074780.9106822,"logger":"tls.handshake","msg":"choosing certificate","identifier":"domain.com","num_choices":1}
{"level":"debug","ts":1745074780.9106984,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"domain.com","subjects":["domain.com"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"3cbf3c035d7ad2a5f0ff30465847a139bfca7e7afbb7983113602422997aaeb3"}
{"level":"debug","ts":1745074780.9107325,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"127.0.0.1","remote_port":"43386","subjects":["domain.com"],"managed":true,"expiration":1752840408,"hash":"3cbf3c035d7ad2a5f0ff30465847a139bfca7e7afbb7983113602422997aaeb3"}
{"level":"debug","ts":1745074780.9143944,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":".","fs":"","request_path":"/css/chat.css","result":"css/chat.css"}
{"level":"debug","ts":1745074780.914521,"logger":"http.log.error","msg":"{id=ck1042ib5} fileserver.(\_FileServer).notFound (staticfiles.go:705): HTTP 404","request":{"remote_ip":"127.0.0.1","remote_port":"43386","client_ip":"127.0.0.1","proto":"HTTP/1.1","method":"GET","host":"domain.com","uri":"/css/chat.css","headers":{"User-Agent":["curl/7.81.0"],"Accept":["*/*"],"Cdn-Loop":["cloudflare; loops=1"],"Cf-Ipcountry":["IN"],"Cf-Ray":["932d450628274221-BOM"],"Cf-Visitor":["{\"scheme\":\"https\"}"],"Cf-Warp-Tag-Id":["3070986d-c812-4f77-b5ad-a16205fc4341"],"Connection":["keep-alive"],"Accept-Encoding":["gzip, br"],"Cf-Connecting-Ip":["1.2.3.4"],"X-Forwarded-For":["1.2.3.4"],"X-Forwarded-Proto":["https"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","server_name":"domain.com"}},"duration":0.000173224,"status":404,"err_id":"ck1042ib5","err_trace":"fileserver.(*FileServer).notFound (staticfiles.go:705)"}
Caddy is in /etc/caddy
I have my web directory inside /etc/caddy
web
βββ chat.html
βββ css
β βββ chat.css
β βββ index.css
β βββ style.css
βββ index.html
βββ js
β βββ chat.js
β βββ login.js
β βββ signup.js
βββ login.html
βββ signup.html
2. Error messages and/or full log output:
Shared above
3. Caddy version:
v2.10.0 h1:fonubSaQKF1YANl8TXqGcn4IbIRUDdfAkpcsfI/vX5U=
Caddy is run in the terminal and not as a service
sudo caddy run
4. How I installed and ran Caddy:
Caddy is run in the terminal and not as a service
sudo caddy run
a. System environment:
OS - Linux abcd 6.1.0-28-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.119-1 (2024-11-22) x86_64 GNU/Linux PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
b. Command:
sudo caddy run
c. Service/unit/compose file:
Systemd file
[Unit
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Environment="CADDY_JWTAUTH_SIGN_KEY=abcd=base64encoded"
Type=notify
User=abc
Group=abc
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
d. My complete Caddy config:
Shared above
5. Links to relevant resources:
n/a