Html file not served when using root directive

1. Caddy version (caddy version):

v2.6.1 h1:EDqo59TyYWhXQnfde93Mmv4FJfYe00dO60zMiEt+pzo=

2. How I run Caddy:

I just installed Caddy via homebew on my Mac and run it with caddy start --watch

a. System environment:

Mac OS 12.3.1

d. My complete Caddyfile or JSON config:

{
    debug
    log
}

localhost {
    root * /public
    encode zstd gzip
    file_server
}

3. The problem I’m having:

As soon as I use the root directive it stops working.
Means - without root * /public I get:

michaelbrauner@MacBook-Pro-2 caddy_start % curl -vL https://localhost/public

*   Trying 127.0.0.1:443...
* Connected to localhost (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: [NONE]
*  start date: Oct 11 18:03:27 2022 GMT
*  expire date: Oct 12 06:03:27 2022 GMT
*  subjectAltName: host "localhost" matched cert's "localhost"
*  issuer: CN=Caddy Local Authority - ECC Intermediate
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x120811000)
> GET /public HTTP/2
> Host: localhost
> user-agent: curl/7.79.1
> accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 308 
< alt-svc: h3=":443"; ma=2592000
< content-type: text/html; charset=utf-8
< location: /public/
< server: Caddy
< content-length: 44
< date: Wed, 12 Oct 2022 00:15:09 GMT
< 
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'https://localhost/public/'
* Found bundle for host localhost: 0x600002c6cd50 [can multiplex]
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 443 (#0)
* Using Stream ID: 3 (easy handle 0x120811000)
> GET /public/ HTTP/2
> Host: localhost
> user-agent: curl/7.79.1
> accept: */*
> 
< HTTP/2 200 
< accept-ranges: bytes
< alt-svc: h3=":443"; ma=2592000
< content-type: text/html; charset=utf-8
< etag: "rjlosy4n"
< last-modified: Tue, 11 Oct 2022 18:02:58 GMT
< server: Caddy
< content-length: 167
< date: Wed, 12 Oct 2022 00:15:09 GMT
< 
<!DOCTYPE html>
<html lang="de">
<head>
    <title>Caddy tutorial</title>
</head>
<body>
Page loaded at: {{ now | date "Mon Jan 2 15:04:05 MST 2006" }}
</body>
* Connection #0 to host localhost left intact
</html>%                                   

But as soon as I insert the root * /public line this html file is not accessible anymore:

michaelbrauner@MacBook-Pro-2 caddy_start % curl -vL https://localhost       
*   Trying 127.0.0.1:443...
* Connected to localhost (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: [NONE]
*  start date: Oct 11 18:03:27 2022 GMT
*  expire date: Oct 12 06:03:27 2022 GMT
*  subjectAltName: host "localhost" matched cert's "localhost"
*  issuer: CN=Caddy Local Authority - ECC Intermediate
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x158011000)
> GET / HTTP/2
> Host: localhost
> user-agent: curl/7.79.1
> accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 404 
< alt-svc: h3=":443"; ma=2592000
< server: Caddy
< content-length: 0
< date: Wed, 12 Oct 2022 00:17:09 GMT
< 
* Connection #0 to host localhost left intact

4. Error messages and/or full log output:

2022/10/12 00:19:32.179 DEBUG   events  event   {"name": "tls_get_certificate", "id": "d20df413-aae1-4ff3-86ce-683d71eb42c7", "origin": "tls", "data": {"client_hello":{"CipherSuites":[4867,4866,4865,52393,52392,52394,49200,49196,49192,49188,49172,49162,159,107,57,65413,196,136,129,157,61,53,192,132,49199,49195,49191,49187,49171,49161,158,103,51,190,69,156,60,47,186,65,49169,49159,5,4,49170,49160,22,10,255],"ServerName":"localhost","SupportedCurves":[29,23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[2054,1537,1539,2053,1281,1283,2052,1025,1027,513,515],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[772,771,770,769],"Conn":{}}}}
2022/10/12 00:19:32.179 DEBUG   tls.handshake   choosing certificate    {"identifier": "localhost", "num_choices": 1}
2022/10/12 00:19:32.179 DEBUG   tls.handshake   default certificate selection results   {"identifier": "localhost", "subjects": ["localhost"], "managed": true, "issuer_key": "local", "hash": "7966589d20c6568ed36b6efd910b9fc44093fff53778e817e7970c4f2d08ee60"}
2022/10/12 00:19:32.179 DEBUG   tls.handshake   matched certificate in cache    {"remote_ip": "127.0.0.1", "remote_port": "53974", "subjects": ["localhost"], "managed": true, "expiration": "2022/10/12 06:03:28.000", "hash": "7966589d20c6568ed36b6efd910b9fc44093fff53778e817e7970c4f2d08ee60"}
2022/10/12 00:19:32.203 DEBUG   http.handlers.file_server       sanitized path join     {"site_root": "/public", "request_path": "/", "result": "/public"}
2022/10/12 00:19:32.203 DEBUG   http.log.error  {id=hh775aa0y} fileserver.(*FileServer).notFound (staticfiles.go:579): HTTP 404 {"request": {"remote_ip": "127.0.0.1", "remote_port": "53974", "proto": "HTTP/2.0", "method": "GET", "host": "localhost", "uri": "/", "headers": {"User-Agent": ["curl/7.79.1"], "Accept": ["*/*"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4867, "proto": "h2", "server_name": "localhost"}}, "duration": 0.00006125, "status": 404, "err_id": "hh775aa0y", "err_trace": "fileserver.(*FileServer).notFound (staticfiles.go:579)"}

So, I am fairly new to caddy. I am just sniffing in since 3-4 hours.
Maybe I miss something essential here.

Can you help me?

If you make a request to /public and define the root as /public, then Caddy is looking for files in /public/public. The file_server appends the request path to the defined root.

Are you sure you have your files in the root of your filesystem, in a directory called public? Did you mean to point to a relative path instead? You used an absolute path.

2 Likes

Thank you Francis for the quick reply!

Yes. There is a file inside the public folder. public/index.html
Otherwise the curl -vL https://localhost/public would not return any html page:

< HTTP/2 200 
< accept-ranges: bytes
< alt-svc: h3=":443"; ma=2592000
< content-type: text/html; charset=utf-8
< etag: "rjlosy4n"
< last-modified: Tue, 11 Oct 2022 18:02:58 GMT
< server: Caddy
< content-length: 167
< date: Wed, 12 Oct 2022 00:15:09 GMT
< 
<!DOCTYPE html>
<html lang="de">
<head>
    <title>Caddy tutorial</title>
</head>
<body>
Page loaded at: {{ now | date "Mon Jan 2 15:04:05 MST 2006" }}
</body>
* Connection #0 to host localhost left intact
</html>%                                   

If I just add root * /public to my Caddyfile and curl curl -vL https://localhost this should be correct and working I guess.
But it’s not:

< HTTP/2 404 
< alt-svc: h3=":443"; ma=2592000
< server: Caddy
< content-length: 0
< date: Wed, 12 Oct 2022 00:17:09 GMT
< 
* Connection #0 to host localhost left intact

I don’t follow. That sounds contradictory to your original post. What’s your directory structure? Run tree and show what it looks like, I guess.

Why is this contradictory?
Actually these examples are just copied from original post. My answer is my original post just shorter ;).

Maybe I didn’t make myself clear enough.

Anyway everything works perfectly without root directive and as soon as I use the root directive I get 404 responses.

Here is a screenshot of my very very simple structure:

When I use root * /public I get only 404 no matter what I try to access.
As soon as I don’t use the root directive everything works just fine and I can access /public with 202 status.

1 Like

don’t use relative paths, always use absolute paths, instead of using /website, do /var/www/website

your root path isnt related to the location of your caddy config ( I don’t think that’s true, but for peace of mind I always use absolute paths)

2 Likes

Bam. That’s it. Saved my day. Thank you much.

The reason your root directive was causing it to not work is because setting it to /public makes it look in the folder called /public on your OS. If you open a terminal and type ls /public I am guessing you would not see your site files there.

If you set your root to public or ./public (same thing), it would have worked only if the current working directory was $HOME/Sites/tests/caddy_start. The root paths are relative to the working dir.

To reiterate what @francislavoie said, even if you did set your root dir to the right public folder, making the request to localhost/public would cause Caddy to load the files from /public/public which is probably a mistake. The uri path is appended to the site root.

2 Likes

Yes, that’s right. Was a weird rookie mistake on my part.
But I have to say, you take really good care of the people here in the forum.

Thank you for your time and effort.

2 Likes

This topic was automatically closed after 30 days. New replies are no longer allowed.