Unable to verify/authenticate certs in Docker on local machine

1. The problem I’m having:

I am trying to get a most basic docker setup running locally. I used the recommended docker compose configuration shown here (with some small changes as described below). The problem is that while local certs seem to work just fine within docker, the authentication is not working outside of the server, whether in a browser or using curl.

On Firefox, I receive Error code: SEC_ERROR_BAD_SIGNATURE and cannot proceed.
On Chromium based browsers, I receive a warning an have to explicitly accept risks.
With curl, I receive a verification error (seen below)

2. Error messages and/or full log output:

caddy-docker-caddy-1  | {"level":"info","ts":1685118477.831558,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.8326027,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.8327231,"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}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.8327372,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.8327959,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0003e1490"}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.833135,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/data/caddy"}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.8336496,"logger":"tls","msg":"finished cleaning storage units"}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.8452787,"logger":"pki.ca.local","msg":"root certificate is already trusted by system","path":"storage:pki/authorities/local/root.crt"}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.845432,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.8455675,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Receive-Buffer-Size for details."}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.845677,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.8457282,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.845736,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["localhost"]}
caddy-docker-caddy-1  | {"level":"warn","ts":1685118477.8460975,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [localhost]: no OCSP server specified in certificate","identifiers":["localhost"]}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.846288,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
caddy-docker-caddy-1  | {"level":"info","ts":1685118477.846301,"msg":"serving initial configuration"}

(Sidenote: is the UDP Receive Buffer Size message a problem?)

Here is a curl output:

$ curl -vL https://localhost:4443
*   Trying 127.0.0.1:4443...
* Connected to localhost (127.0.0.1) port 4443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* 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 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

3. Caddy version:

caddy:2.7-alpine

4. How I installed and ran Caddy:

a. System environment:

Docker

b. Command:

docker compose up

c. Service/unit/compose file:

version: "3.9"

services:
  caddy:
    image: caddy:2.7-alpine
    restart: unless-stopped
    ports:
      - "8080:80"
      - "4443:443"
      - "4443:443/udp"
    volumes:
      - $PWD/Caddyfile:/etc/caddy/Caddyfile
      - $PWD/site:/srv
      - caddy_data:/data
      - caddy_config:/config

volumes:
  caddy_data:
  caddy_config:

Note: because I do not have permissions to bind to ports 80 and 443, I set them to different ports, 8080 and 4443, respectively.

d. My complete Caddy config:

localhost

respond "Hello, world!"

5. Links to relevant resources:

Did you run the command at the bottom of the page to install Caddy’s root CA cert on your host machine?

1 Like

Thank you. My apologies for managing to miss that at the bottom every time I looked. When I tried to run it, I first got this:

open /usr/local/share/ca-certificates/root.crt: permission denied

I tried running with sudo and received this:

WARN[0000] The "PWD" variable is not set. Defaulting to a blank string. 
WARN[0000] The "PWD" variable is not set. Defaulting to a blank string. 
no container found for service "caddy"

This happened whether or not it was already running.

Are you running that in the directory in which your docker-compose.yml file exists?

Yes, I am.

That’s confusing. Your Docker setup doesn’t make sense to me. Sudoers should always be able to run Docker commands.

Either way, you can split up the command in two if you must, do it in two steps by copying the cert file to the host with your current user, then copy it with sudo to the final location.

Oh, I see. Apparently PWD isn’t set when you run sudo, so it gets confused by the docker-compose.yml.

You can change $PWD to . in there and it should work better.

I had no idea sudo didn’t inherit PWD. I just updated the docs accordingly

I wasn’t sure how to set $PWD. I tried setting it in environment in docker-compose.yml. In any case, I just copied it locally and then moved root.crt to /usr/local/share/ca-certificates/root.crt and ran sudo update-ca-certificates.

I got this output:

Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

I am still seeing the same errors though.

Try this again.

I still received the same error as before.

*   Trying 127.0.0.1:4443...
* Connected to localhost (127.0.0.1) port 4443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* 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 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

I just wanted to report that I came back to this a few days later, and I’m able to at least load things in Firefox after accepting a warning. I still receive the same warning with cURL.

Bumping in case anyone has any additional thoughts on how I might get over this last hump.

(Thanks again for the help so far!)

I mean, if you’re going to bypass the warning anyway you could use curl -K / curl --insecure but obviously that defeats the purpose :upside_down_face:

My understanding is that you’ve installed Caddy’s root certificate from the container onto your host machine. Are you sure you got the root cert and that it wasn’t re-generated?

If so, sorry, I’m not really sure how to help here. I haven’t encountered a problem like this and I’m not experienced with Docker environments.

You’re right that maybe it’s getting re-generated. It would make some sense. Perhaps someone else who knows more about docker than you or me can explain how I might improve the docker volumes related to this container to prevent things from being regenerated.

The following is in the recommended docker compose setup:

volumes:
  caddy_data:
  caddy_config:

I’ve also seen references to setting it as:

volumes:
  caddy_data:
    external: true
  caddy_config:

Should these be keeping it from happening?

I don’t know, but you can verify by reading the root cert from the container again and seeing if it matches the one you installed.

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