Caddy serving 403 Forbidden for SPA routes - React app and API proxy configuration help needed

1. The problem I’m having:

I’m trying to set up a Caddy server to host a Single Page Application (SPA) and reverse proxy API requests to a backend server. The SPA is built with React and located in the /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist directory. I want Caddy to serve the SPA and handle client-side routing, while also proxying API requests to a backend server running on localhost:5001.
The server is running, but it’s not serving the SPA correctly. Instead, it’s responding with 403 HTTP Error status code for all requests.
This is the output of curl:

curl -vL https://mydailyimpact.codecrafter.space/
*   Trying 3.67.67.181:443...
* Connected to mydailyimpact.codecrafter.space (3.67.67.181) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /usr/lib/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=mydailyimpact.codecrafter.space
*  start date: Mar  6 03:47:26 2025 GMT
*  expire date: Jun  4 03:47:25 2025 GMT
*  subjectAltName: host "mydailyimpact.codecrafter.space" matched cert's "mydailyimpact.codecrafter.space"
*  issuer: C=US; O=Let's Encrypt; CN=E6
*  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
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x5d2878f6e9f0)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET / HTTP/2
> Host: mydailyimpact.codecrafter.space
> user-agent: curl/7.81.0
> accept: */*
> 
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 403 
< alt-svc: h3=":443"; ma=2592000
< server: Caddy
< content-length: 0
< date: Thu, 06 Mar 2025 07:39:54 GMT
< 
* Connection #0 to host mydailyimpact.codecrafter.space left intact

However, when I run:

sudo caddy run --config /etc/caddy/Caddyfile --adapter caddyfile

It works.

2. Error messages and/or full log output:

Mar 06 07:43:25 ip-172-26-3-4 systemd[1]: Started Caddy.
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.9325602,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.9347594,"msg":"adapted config to JSON","adapter":"caddyfile"}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"warn","ts":1741247005.934786,"msg":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":6}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.936095,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//127.0.0.1:2019","//localhost:2019","//[::1]:2019"]}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.936409,"logger":"http.auto_https","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.93643,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247005.9364662,"logger":"http.auto_https","msg":"adjusted config","tls":{"automation":{"policies":[{}]}},"http":{"servers":{"remaining_auto_https_redirects":{"listen":[":80"],"routes":[{},{}],"logs":{"logger_names":{"mydailyimpact.codecrafter.space":["log0"]}}},"srv0":{"listen":[":443"],"routes":[{"handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"vars","root":"/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist"}]},{"handle":[{"handler":"rewrite","uri":"{http.matchers.file.relative}"}],"match":[{"file":{"try_files":["{http.request.uri.path}","/index.html"]}}]},{"handle":[{"encodings":{"gzip":{}},"handler":"encode","prefer":["gzip"]}]},{"group":"group2","handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"rewrite","strip_path_prefix":"/auth"}]},{"handle":[{"handler":"reverse_proxy","upstreams":[{"dial":"localhost:5001"}]}]}]}],"match":[{"path":["/auth/*"]}]},{"group":"group2","handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"rewrite","strip_path_prefix":"/api"}]},{"handle":[{"handler":"reverse_proxy","upstreams":[{"dial":"localhost:5001"}]}]}]}],"match":[{"path":["/api/*"]}]},{"handle":[{"handler":"file_server","hide":["/etc/caddy/Caddyfile"]}]}]}],"terminal":true}],"tls_connection_policies":[{}],"automatic_https":{},"logs":{"logger_names":{"mydailyimpact.codecrafter.space":["log0"]}}}}}}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.9367528,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0007a5880"}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247005.937794,"logger":"http","msg":"starting server loop","address":"[::]:443","tls":true,"http3":false}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.938387,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.938477,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 7168 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details."}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.9386013,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247005.938654,"logger":"http","msg":"starting server loop","address":"[::]:80","tls":false,"http3":false}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"warn","ts":1741247005.9386628,"logger":"http","msg":"HTTP/2 skipped because it requires TLS","network":"tcp","addr":":80"}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"warn","ts":1741247005.9386675,"logger":"http","msg":"HTTP/3 skipped because it requires TLS","network":"tcp","addr":":80"}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.9386718,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.938677,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["mydailyimpact.codecrafter.space"]}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247005.9392369,"logger":"tls.cache","msg":"added certificate to cache","subjects":["mydailyimpact.codecrafter.space"],"expiration":1749008846,"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"676c3133f7fbc24e86f2187538474f15f634712e0c41c331a9b5679761056061","cache_size":1,"cache_capacity":10000}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247005.9392755,"logger":"events","msg":"event","name":"cached_managed_cert","id":"4a200fd1-7f6e-4c1e-bf07-d705908b295b","origin":"tls","data":{"sans":["mydailyimpact.codecrafter.space"]}}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.9394221,"msg":"autosaved config (load with --resume flag)","file":"/var/lib/caddy/.config/caddy/autosave.json"}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.9394314,"msg":"serving initial configuration"}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.942718,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/var/lib/caddy/.local/share/caddy","instance":"3b4db656-0fd5-4b66-ab71-4eccc5c39ba9","try_again":1741333405.9427145,"try_again_in":86399.999999629}
Mar 06 07:43:25 ip-172-26-3-4 caddy[55625]: {"level":"info","ts":1741247005.942792,"logger":"tls","msg":"finished cleaning storage units"}
Mar 06 07:43:38 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247018.4561512,"logger":"events","msg":"event","name":"tls_get_certificate","id":"aace6fb5-724f-4e6d-8b4c-1d0e2e3693a9","origin":"tls","data":{"client_hello":{"CipherSuites":[4866,4867,4865,49196,49200,159,52393,52392,52394,49195,49199,158,49188,49192,107,49187,49191,103,49162,49172,57,49161,49171,51,157,156,61,60,53,47,255],"ServerName":"mydailyimpact.codecrafter.space","SupportedCurves":[29,23,30,25,24,256,257,258,259,260],"SupportedPoints":"AAEC","SignatureSchemes":[1027,1283,1539,2055,2056,2057,2058,2059,2052,2053,2054,1025,1281,1537,771,769,770,1026,1282,1538],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[772,771],"RemoteAddr":{"IP":"3.67.67.181","Port":45098,"Zone":""},"LocalAddr":{"IP":"172.26.3.4","Port":443,"Zone":""}}}}
Mar 06 07:43:38 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247018.4564464,"logger":"tls.handshake","msg":"choosing certificate","identifier":"mydailyimpact.codecrafter.space","num_choices":1}
Mar 06 07:43:38 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247018.4564588,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"mydailyimpact.codecrafter.space","subjects":["mydailyimpact.codecrafter.space"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"676c3133f7fbc24e86f2187538474f15f634712e0c41c331a9b5679761056061"}
Mar 06 07:43:38 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247018.4564705,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"3.67.67.181","remote_port":"45098","subjects":["mydailyimpact.codecrafter.space"],"managed":true,"expiration":1749008846,"hash":"676c3133f7fbc24e86f2187538474f15f634712e0c41c331a9b5679761056061"}
Mar 06 07:43:38 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247018.461961,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist","fs":"","request_path":"/","result":"/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist"}
Mar 06 07:43:38 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247018.4620721,"logger":"http.log.error.log0","msg":"open /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist: permission denied","request":{"remote_ip":"3.67.67.181","remote_port":"45098","client_ip":"3.67.67.181","proto":"HTTP/2.0","method":"GET","host":"mydailyimpact.codecrafter.space","uri":"/","headers":{"User-Agent":["curl/7.81.0"],"Accept":["*/*"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"mydailyimpact.codecrafter.space"}},"duration":0.000766447,"status":403,"err_id":"jj0re8b2u","err_trace":"fileserver.(*FileServer).ServeHTTP (staticfiles.go:306)"}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.1981063,"logger":"events","msg":"event","name":"tls_get_certificate","id":"8e7b08c0-6ed4-4caa-b271-4d8b8394462a","origin":"tls","data":{"client_hello":{"CipherSuites":[4866,4865,4867,49196,49195,52393,49200,49199,52392,255],"ServerName":"mydailyimpact.codecrafter.space","SupportedCurves":[29,23,24],"SupportedPoints":"AA==","SignatureSchemes":[1283,1027,2055,2054,2053,2052,1537,1281,1025],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[772,771],"RemoteAddr":{"IP":"4.227.36.69","Port":49702,"Zone":""},"LocalAddr":{"IP":"172.26.3.4","Port":443,"Zone":""}}}}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.1982105,"logger":"tls.handshake","msg":"choosing certificate","identifier":"mydailyimpact.codecrafter.space","num_choices":1}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.1982224,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"mydailyimpact.codecrafter.space","subjects":["mydailyimpact.codecrafter.space"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"676c3133f7fbc24e86f2187538474f15f634712e0c41c331a9b5679761056061"}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.1982322,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"4.227.36.69","remote_port":"49702","subjects":["mydailyimpact.codecrafter.space"],"managed":true,"expiration":1749008846,"hash":"676c3133f7fbc24e86f2187538474f15f634712e0c41c331a9b5679761056061"}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.344055,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist","fs":"","request_path":"/robots.txt","result":"/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/robots.txt"}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.3441472,"logger":"http.log.error.log0","msg":"open /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/robots.txt: permission denied","request":{"remote_ip":"4.227.36.69","remote_port":"49702","client_ip":"4.227.36.69","proto":"HTTP/2.0","method":"GET","host":"mydailyimpact.codecrafter.space","uri":"/robots.txt","headers":{"Accept":["*/*"],"From":["gptbot(at)openai.com"],"User-Agent":["Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.2; +https://openai.com/gptbot)"],"Accept-Encoding":["gzip, br, deflate"],"X-Openai-Host-Hash":["911541922"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"mydailyimpact.codecrafter.space"}},"duration":0.000158789,"status":403,"err_id":"ikkzc7gsv","err_trace":"fileserver.(*FileServer).ServeHTTP (staticfiles.go:306)"}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.6253858,"logger":"events","msg":"event","name":"tls_get_certificate","id":"f2477544-b8ac-453b-9513-bb93f2dd2815","origin":"tls","data":{"client_hello":{"CipherSuites":[4866,4865,4867,49196,49195,52393,49200,49199,52392,255],"ServerName":"mydailyimpact.codecrafter.space","SupportedCurves":[29,23,24],"SupportedPoints":"AA==","SignatureSchemes":[1283,1027,2055,2054,2053,2052,1537,1281,1025],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[772,771],"RemoteAddr":{"IP":"20.171.207.6","Port":55428,"Zone":""},"LocalAddr":{"IP":"172.26.3.4","Port":443,"Zone":""}}}}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.6255147,"logger":"tls.handshake","msg":"choosing certificate","identifier":"mydailyimpact.codecrafter.space","num_choices":1}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.6255255,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"mydailyimpact.codecrafter.space","subjects":["mydailyimpact.codecrafter.space"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"676c3133f7fbc24e86f2187538474f15f634712e0c41c331a9b5679761056061"}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.6255367,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"20.171.207.6","remote_port":"55428","subjects":["mydailyimpact.codecrafter.space"],"managed":true,"expiration":1749008846,"hash":"676c3133f7fbc24e86f2187538474f15f634712e0c41c331a9b5679761056061"}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.7660022,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist","fs":"","request_path":"/","result":"/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist"}
Mar 06 07:45:45 ip-172-26-3-4 caddy[55625]: {"level":"debug","ts":1741247145.766139,"logger":"http.log.error.log0","msg":"open /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist: permission denied","request":{"remote_ip":"20.171.207.6","remote_port":"55428","client_ip":"20.171.207.6","proto":"HTTP/2.0","method":"GET","host":"mydailyimpact.codecrafter.space","uri":"/","headers":{"X-Openai-Host-Hash":["911541922"],"Accept":["*/*"],"From":["gptbot(at)openai.com"],"User-Agent":["Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.2; +https://openai.com/gptbot)"],"Accept-Encoding":["gzip, br, deflate"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"mydailyimpact.codecrafter.space"}},"duration":0.000254741,"status":403,"err_id":"rg9bp8rnf","err_trace":"fileserver.(*FileServer).ServeHTTP (staticfiles.go:306)"}

3. Caddy version:

v2.9.1

4. How I installed and ran Caddy:

I followed the instructions from the official documentation for Ubuntu:

a. System environment:

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.5 LTS"
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.5 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

Systemd:

systemd 249 (249.11-0ubuntu3.12)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY -P11KIT -QRENCODE +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified

This is the content of:

sudo cat /etc/systemd/system/caddy.service
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

b. Command:

sudo systemctl start caddy
sudo systemctl enable caddy
sudo systemctl status caddy

d. My complete Caddy config:

{
        debug
}

mydailyimpact.codecrafter.space {
    root * /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist
    encode gzip
    file_server

    try_files {path} /index.html

    handle_path /api/* {
        reverse_proxy localhost:5001
    }

    handle_path /auth/* {
        reverse_proxy localhost:5001
    }

    log {
        output file /var/log/caddy/access.log
        format json
    }
}

5. Links to relevant resources:

One common problem can be that the user you are running caddy as does not have permission to open the file.

According to your config, you run under the user caddy and try to use /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist as the root.

What happens if you run sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/index.html? Do you get a directory listing back or an error? If you get an error back, you need to modify the permissions so the user caddy can access the files

2 Likes

Hi :wave:,
thank you for your reply. I don’t understand, when I run your command, I get:
ls: cannot access '/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/index.html': Permission denied
But I changed ownership to caddy already, see here:

~/WS24-MyDailyImpact/mdi-react/dist$ ll
total 24
drwxr-xr-x 3 caddy  caddy  4096 Mar  5 15:29 ./
drwxrwxr-x 6 ubuntu ubuntu 4096 Mar  5 15:08 ../
-rwxr-xr-x 1 caddy  caddy  2098 Mar  5 15:08 MDI-Favicon.svg*
drwxr-xr-x 2 caddy  caddy  4096 Mar  5 15:08 assets/
-rwxr-xr-x 1 caddy  caddy   910 Mar  5 15:08 index.html*
-rwxr-xr-x 1 caddy  caddy    36 Mar  5 15:29 test.html*

We have confirmed there is an OS level permissions issue

Check if you can access the parent folders:

sudo -u caddy ls -l /
sudo -u caddy ls -l /home/
sudo -u caddy ls -l /home/ubuntu/
sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/
sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/mdi-react/
sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/
sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/index.html

Note that if a parent folder denies permission, you cannot allow a user again in the subfolders. You need at least execute permissions on the folder and read permissions on the file

1 Like

Hi Fernando,
thank you again for helping me with my problem. I really appreciate it.
I went through commands. At line three I get permission denied:

sudo -u caddy ls -l /home/ubuntu/
ls: cannot open directory '/home/ubuntu/': Permission denied

Same with next line:

sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/
ls: cannot access '/home/ubuntu/WS24-MyDailyImpact/': Permission denied

And next line:

sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/mdi-react/
ls: cannot access '/home/ubuntu/WS24-MyDailyImpact/mdi-react/': Permission denied

And next line:

sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/
ls: cannot access '/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/': Permission denied

And same with last line of your ls commands:

sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/index.html
ls: cannot access '/home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/index.html': Permission denied

Let me guess, I should not place the folder containing my web app in a user’s folder.

How you decide to structure your folders is your opinion

Since you want the user account caddy to access the folders, we need to give it execute permissions on all the folders up to the last folder:

chmod o+x /home/ubuntu/ /home/ubuntu/WS24-MyDailyImpact/ /home/ubuntu/WS24-MyDailyImpact/mdi-react/

(We know the permissions on dist are correct, since you shared them already)

After running this, sudo -u caddy ls -l /home/ubuntu/WS24-MyDailyImpact/mdi-react/dist/index.html should work work now, and caddy should be able to show the files

3 Likes

Thank you, Fernando.