SSL error with Caddy and PHP

1. The problem I’m having:

I have a server with a public IP address and another machine which is behind a NAT. This machine has a Nextcloud instance I’d like to publish. My idea is to use Tailscale to bypass the NAT and then Caddy to proxy a subdomain. I’m using Caddy both on the server as a proxy as well as on the machine to connect to php_fastcgi.
The problem I’m facing is that the machine doesn’t have a way to generate the SSL.
I can’t figure out the problem, even if I use tls crt key I’m still unable to get the SSL working. I’m sure that this configuration is correct because if I put it on the server with tls email I can successfully access the Nextcloud.

2. Error messages and/or full log output:

curl: (35) error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error

3. Caddy version:


4. How I installed and ran Caddy:

a. System environment:

I’m running Caddy on Docker Compose.

b. Command:

c. Service/unit/compose file:

    image: caddy:2.6.4-alpine
    restart: always
      - "80:80"
      - "443:443"
      - $PWD/Caddyfile:/etc/caddy/Caddyfile
      - $PWD/caddy_data:/data
      - $PWD/caddy_config:/config
      - ./nextcloud/html:/nextcloud/var/www/html
      - ./nextcloud/data:/nextcloud/var/www/html/data
      - ./nextcloud/custom_apps:/nextcloud/var/www/html/custom_apps
      - ./ssl:/ssl

d. My complete Caddy config:

https://* {
  tls internal 

	encode gzip

  root * /nextcloud/var/www/html

  php_fastcgi nextcloud:9000 
    root /var/www/html
    env front_controller_active true

  redir /.well-known/carddav /remote.php/dav 301
  redir /.well-known/caldav /remote.php/dav 301

  # .htaccess / data / config / ... shouldn't be accessible from outside
  @forbidden {
    path /.htaccess
    path /data/*
    path /config/*
    path /db_structure
    path /.xml
    path /README
    path /3rdparty/*
    path /lib/*
    path /templates/*
    path /occ
    path /console.php
  respond @forbidden 404

5. Links to relevant resources:

Hi @albertoZurini, welcome to the Caddy community.

Caddy should definitely be able to generate an internal certificate, even without tls internal in this case (as the domain name does not qualify for a public certificate).

Basic example
whitestrake in ~ at merlin
➜ cat Caddyfile
https://* {
  respond "Hello!"

whitestrake in ~ at merlin
➜ caddy version
v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

whitestrake in ~ at merlin
➜ caddy start
2023/03/09 06:36:51.844	INFO	using adjacent Caddyfile
2023/03/09 06:36:51.845	WARN	Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies	{"adapter": "caddyfile", "file": "Caddyfile", "line": 2}
2023/03/09 06:36:51.847	INFO	admin	admin endpoint started	{"address": "localhost:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//"]}
2023/03/09 06:36:51.847	INFO	tls.cache.maintenance	started background certificate maintenance	{"cache": "0xc0004c3f10"}
2023/03/09 06:36:51.850	INFO	http	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}
2023/03/09 06:36:51.850	INFO	http	enabling automatic HTTP->HTTPS redirects	{"server_name": "srv0"}
2023/03/09 06:36:51.858	INFO	root certificate is already trusted by system	{"path": "storage:pki/authorities/local/root.crt"}
2023/03/09 06:36:51.859	INFO	http	enabling HTTP/3 listener	{"addr": ":443"}
2023/03/09 06:36:51.859	INFO	tls	cleaning storage unit	{"description": "FileStorage:/Users/whitestrake/Library/Application Support/Caddy"}
2023/03/09 06:36:51.859	INFO	http.log	server running	{"name": "srv0", "protocols": ["h1", "h2", "h3"]}
2023/03/09 06:36:51.859	INFO	http.log	server running	{"name": "remaining_auto_https_redirects", "protocols": ["h1", "h2", "h3"]}
2023/03/09 06:36:51.859	INFO	http	enabling automatic TLS certificate management	{"domains": ["*"]}
2023/03/09 06:36:51.859	WARN	tls	stapling OCSP	{"error": "no OCSP stapling for [*]: no OCSP server specified in certificate", "identifiers": ["*"]}
2023/03/09 06:36:51.859	INFO	autosaved config (load with --resume flag)	{"file": "/Users/whitestrake/Library/Application Support/Caddy/autosave.json"}
2023/03/09 06:36:51.860	INFO	serving initial configuration
2023/03/09 06:36:51.860	INFO	tls	finished cleaning storage units
Successfully started Caddy (pid=75882) - Caddy is running in the background

whitestrake in ~ at merlin
➜ curl -k https://localhost

The curl error you’ve posted is lacking context, though. I don’t even know which Caddy instance you made that request to, or the parameters of that request, so I can’t tell you why it might have failed.

You could try adding the debug global option and posting full logs, as well as the full curl -v command and its output.

Thank you a lot for the answer.
I ran
curl -vk
And the output is:

*   Trying
* Connected to ( port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, internal error (592):
* error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error
* Closing connection 0
curl: (35) error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error

And have you added the debug global option yet? If so, what does Caddy output when you start it up and make this request?

How do I do that on Docker?

{"level":"info","ts":1678357966.1307187,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
{"level":"warn","ts":1678357966.244666,"msg":"Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
{"level":"info","ts":1678357966.2950706,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//[::1]:2019","//","//localhost:2019"]}
{"level":"info","ts":1678357966.3187313,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000410d90"}
{"level":"info","ts":1678357966.3283975,"logger":"http","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":1678357966.3284812,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1678357966.3623154,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
{"level":"info","ts":1678357966.366054,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See for details."}
{"level":"info","ts":1678357966.3662484,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
{"level":"info","ts":1678357966.3664012,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
{"level":"info","ts":1678357966.384005,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/data/caddy"}
{"level":"info","ts":1678357966.3841128,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"warn","ts":1678357966.9244506,"logger":"","msg":"installing root certificate (you might be prompted for password)","path":"storage:pki/authorities/local/root.crt"}
{"level":"info","ts":1678357966.938974,"msg":"warning: \"certutil\" is not available, install \"certutil\" with \"apt install libnss3-tools\" or \"yum install nss-tools\" and try again"}
{"level":"info","ts":1678357966.93905,"msg":"define JAVA_HOME environment variable to use the Java trust"}
{"level":"info","ts":1678357967.217824,"msg":"certificate installed properly in linux trusts"}
{"level":"info","ts":1678357967.2300353,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1678357967.2300835,"msg":"serving initial configuration"}

If I curl I don’t see any update in the logs.

Okay, so, in my logs I have this:

2023/03/09 06:36:51.859 INFO http enabling automatic TLS certificate management {"domains": ["*"]}

Which is missing from yours, but I expected to see for a site address https://*.

Can you please double check your Caddyfile for me?

If you have debug enabled and you don’t see any update at all when you make your request (even an erroring one), that’s a strong indicator that your requests are not actually reaching Caddy at all. Even in instances of no valid HTTPS certificate, Caddy outputs tls.handshake debug logs similar to this:

2023/03/09 23:57:34.459 DEBUG tls.handshake no matching certificates and no custom selection logic {"identifier": ""}
2023/03/09 23:57:34.459 DEBUG tls.handshake all external certificate managers yielded no certificates and no errors {"remote_ip": "", "remote_port": "50306", "sni": ""}

Which, to loop back to this note you made earlier…

I should point out this regarding wildcards in site addresses:

Wildcards (*) may be used, but only to represent precisely one label of the hostname. For example, * matches but not, and * matches localhost but not To catch all hosts, omit the host portion of the address.

Which means that a site address of https://* will NOT match a request to

A site address of https:// will, but then there won’t be a hostname to put on your certificate. You should consider setting specifically as your site address if that’s the address you want to use to reach your site.