Right, I forgot to update the root path build
, since I started using the official caddy image I should have updated the root to /srv
since there is where I’m copying my build files to at the end of my Dockerfile.
My file structure is
srv
├── index.html
├── asset-manifest.json
├── favicon.ico
├── manifest.json
├── robots.txt
├── service-worker.js
├── service-worker.js.LICENSE.txt
└── static
├── css
│ └── bunch of css files
└── js
└── bunch of js files
This is my updated Dockerfile:
FROM node:alpine3.18 as base
WORKDIR /app
COPY . .
RUN npm install --include=dev
RUN npm run build
FROM caddy
COPY --from=base /app/build/ /srv
COPY --from=base /app/Caddyfile /etc/caddy/Caddyfile
EXPOSE 443
This is my updated Caddyfile:
{
admin off
persist_config off
log {
format json
output file /var/log/caddy/global-log.json
}
debug
}
localhost {
log {
format json
output file /var/log/caddy/localhost-log.json
}
respond /health 200
root * /srv
encode gzip
file_server
try_files {path} index.html
}
So with these changes I would think that it will work and it does but in a weird way, this is the curl response:
curl -v https://localhost:443
* Host localhost:443 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:443...
* Connected to localhost (::1) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
* subject: [NONE]
* start date: Jul 6 13:35:12 2024 GMT
* expire date: Jul 7 01:35:12 2024 GMT
* subjectAltName: host "localhost" matched cert's "localhost"
* issuer: CN=Caddy Local Authority - ECC Intermediate
* SSL certificate verify ok.
* Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256
* Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://localhost:443/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: localhost]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.8.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: localhost
> User-Agent: curl/8.8.0
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
< accept-ranges: bytes
< alt-svc: h3=":443"; ma=2592000
< content-type: text/html; charset=utf-8
< etag: "d2ihuo5t5zk5r9"
< last-modified: Sat, 06 Jul 2024 13:35:08 GMT
< server: Caddy
< vary: Accept-Encoding
< content-length: 981
< date: Sat, 06 Jul 2024 14:18:42 GMT
<
* Connection #0 to host localhost left intact
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="my-app"/><base href="/"><link rel="apple-touch-icon" href="./logo192.png"/><link rel="manifest" href="./manifest.json"/><title>My App</title><script defer="defer" src="./static/js/main.376a5fe7.js"></script><link href="./static/css/main.0a85a964.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><script>"serviceWorker"in navigator&&navigator.serviceWorker.register("service-worker.js").catch((function(e){console.warn(e),console.warn("(This warning can be safely ignored outside of the production build.)")}))</script><div id="root"></div><div id="someId"></div><div id="someId"></div><div id="someId"></div></body></html>
From that it may seem, at least to me, that the issue is solved because I’m getting an actual html response with code 200, however in firefox that url doesn’t load the page, instead I get Error code: SEC_ERROR_BAD_SIGNATURE
, in chrome the page does load but in the chrome console I get this error An SSL certificate error occurred when fetching the script.
and I cannot utilize any function in my app that needs to connect to my api server which is running in a separate container because of CORS errors.
This is weird because in these days I’ve been working with a very basic express server (in the mean time since I’m having issues with caddy) to serve my app’s static files and it worked just fine, without cors errors or so. This leads me to believe that I’m doing something wrong in my caddy configuration.
These are the logs for when the caddy server just starts:
{
"level": "warn",
"ts": 1720280535.1809287,
"logger": "admin",
"msg": "admin endpoint disabled"
}
{
"level": "info",
"ts": 1720280535.1812863,
"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
}
{
"level": "info",
"ts": 1720280535.1812987,
"logger": "http.auto_https",
"msg": "enabling automatic HTTP->HTTPS redirects",
"server_name": "srv0"
}
{
"level": "info",
"ts": 1720280535.181343,
"logger": "tls.cache.maintenance",
"msg": "started background certificate maintenance",
"cache": "0xc00064c300"
}
{
"level": "debug",
"ts": 1720280535.1816103,
"logger": "http.auto_https",
"msg": "adjusted config",
"tls": {
"automation": {
"policies": [
{
"subjects": [
"localhost"
]
},
{}
]
}
},
"http": {
"servers": {
"remaining_auto_https_redirects": {
"listen": [
":80"
],
"routes": [
{},
{}
],
"logs": {
"logger_names": {
"localhost": [
"log0"
]
}
}
},
"srv0": {
"listen": [
":443"
],
"routes": [
{
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "vars",
"root": "/srv"
}
]
},
{
"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"
]
}
]
},
{
"handle": [
{
"handler": "static_response",
"status_code": 200
}
],
"match": [
{
"path": [
"/health"
]
}
]
},
{
"handle": [
{
"handler": "file_server",
"hide": [
"/etc/caddy/Caddyfile"
]
}
]
}
]
}
],
"terminal": true
}
],
"tls_connection_policies": [
{}
],
"automatic_https": {},
"trusted_proxies": {
"ranges": [
"192.168.0.0/16",
"172.16.0.0/12",
"10.0.0.0/8",
"127.0.0.1/8",
"fd00::/8",
"::1"
],
"source": "static"
},
"logs": {
"logger_names": {
"localhost": [
"log0"
]
}
}
}
}
}
}
{
"level": "warn",
"ts": 1720280535.1820352,
"logger": "pki.ca.local",
"msg": "installing root certificate (you might be prompted for password)",
"path": "storage:pki/authorities/local/root.crt"
}
{
"level": "info",
"ts": 1720280535.1842167,
"logger": "tls",
"msg": "storage cleaning happened too recently; skipping for now",
"storage": "FileStorage:/data/caddy",
"instance": "5d261392-cee3-4b51-bbd5-ebabdceba0df",
"try_again": 1720366935.1842139,
"try_again_in": 86399.999998899
}
{
"level": "info",
"ts": 1720280535.1842873,
"logger": "tls",
"msg": "finished cleaning storage units"
}
{
"level": "info",
"ts": 1720280535.2093556,
"logger": "http",
"msg": "enabling HTTP/3 listener",
"addr": ":443"
}
{
"level": "debug",
"ts": 1720280535.2094836,
"logger": "http",
"msg": "starting server loop",
"address": "[::]:443",
"tls": true,
"http3": true
}
{
"level": "info",
"ts": 1720280535.209493,
"logger": "http.log",
"msg": "server running",
"name": "srv0",
"protocols": [
"h1",
"h2",
"h3"
]
}
{
"level": "debug",
"ts": 1720280535.2095242,
"logger": "http",
"msg": "starting server loop",
"address": "[::]:80",
"tls": false,
"http3": false
}
{
"level": "info",
"ts": 1720280535.2095325,
"logger": "http.log",
"msg": "server running",
"name": "remaining_auto_https_redirects",
"protocols": [
"h1",
"h2",
"h3"
]
}
{
"level": "info",
"ts": 1720280535.2095368,
"logger": "http",
"msg": "enabling automatic TLS certificate management",
"domains": [
"localhost"
]
}
{
"level": "warn",
"ts": 1720280535.2097847,
"logger": "tls",
"msg": "stapling OCSP",
"error": "no OCSP stapling for [localhost]: no OCSP server specified in certificate",
"identifiers": [
"localhost"
]
}
{
"level": "debug",
"ts": 1720280535.2097962,
"logger": "tls.cache",
"msg": "added certificate to cache",
"subjects": [
"localhost"
],
"expiration": 1720316113,
"managed": true,
"issuer_key": "local",
"hash": "a20f02ffe53a4f6d7a993d719b8ab9969b6f81108b752fe2765f28150f8a42e0",
"cache_size": 1,
"cache_capacity": 10000
}
{
"level": "debug",
"ts": 1720280535.209817,
"logger": "events",
"msg": "event",
"name": "cached_managed_cert",
"id": "e41c46f1-1dc1-404d-a404-8cc447e6e19e",
"origin": "tls",
"data": {
"sans": [
"localhost"
]
}
}
{
"level": "info",
"ts": 1720280535.2098567,
"msg": "serving initial configuration"
}
And these are the logs for when I make the curl request https://localhost:443
:
{
"level": "debug",
"ts": 1720280629.5782323,
"logger": "events",
"msg": "event",
"name": "tls_get_certificate",
"id": "746a176c-5082-4345-bab2-917dc960c6c8",
"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": "localhost",
"SupportedCurves": [
29,
23,
30,
25,
24,
256,
257,
258,
259,
260
],
"SupportedPoints": "AAEC",
"SignatureSchemes": [
1027,
1283,
1539,
2055,
2056,
2074,
2075,
2076,
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": "172.18.0.1",
"Port": 47596,
"Zone": ""
},
"LocalAddr": {
"IP": "172.18.0.3",
"Port": 443,
"Zone": ""
}
}
}
}
{
"level": "debug",
"ts": 1720280629.578272,
"logger": "tls.handshake",
"msg": "choosing certificate",
"identifier": "localhost",
"num_choices": 1
}
{
"level": "debug",
"ts": 1720280629.5782814,
"logger": "tls.handshake",
"msg": "default certificate selection results",
"identifier": "localhost",
"subjects": [
"localhost"
],
"managed": true,
"issuer_key": "local",
"hash": "a20f02ffe53a4f6d7a993d719b8ab9969b6f81108b752fe2765f28150f8a42e0"
}
{
"level": "debug",
"ts": 1720280629.578286,
"logger": "tls.handshake",
"msg": "matched certificate in cache",
"remote_ip": "172.18.0.1",
"remote_port": "47596",
"subjects": [
"localhost"
],
"managed": true,
"expiration": 1720316113,
"hash": "a20f02ffe53a4f6d7a993d719b8ab9969b6f81108b752fe2765f28150f8a42e0"
}
{
"level": "debug",
"ts": 1720280629.5884564,
"logger": "http.handlers.rewrite",
"msg": "rewrote request",
"request": {
"remote_ip": "172.18.0.1",
"remote_port": "47596",
"client_ip": "172.18.0.1",
"proto": "HTTP/2.0",
"method": "GET",
"host": "localhost",
"uri": "/",
"headers": {
"User-Agent": [
"curl/8.8.0"
],
"Accept": [
"*/*"
]
},
"tls": {
"resumed": false,
"version": 772,
"cipher_suite": 4865,
"proto": "h2",
"server_name": "localhost"
}
},
"method": "GET",
"uri": "/index.html"
}
{
"level": "debug",
"ts": 1720280629.5885112,
"logger": "http.handlers.file_server",
"msg": "sanitized path join",
"site_root": "/srv",
"fs": "",
"request_path": "/index.html",
"result": "/srv/index.html"
}
{
"level": "debug",
"ts": 1720280629.5885305,
"logger": "http.handlers.file_server",
"msg": "opening file",
"filename": "/srv/index.html"
}