Local TLS for arbitrary hostnames

1. The problem I’m having:

I’m hoping to be able to use Caddy’s internal certificate authority to issue certificates for fake/arbitrary domains for locally testing. Certificates work for named hosts, but not for arbitrary ones. I would like Caddy to issue a certificate for myexampleuser.test in order to locally test our custom domains system.

➜  app  ✗ curl -v https://myexampleuser.test
*   Trying 127.0.0.1:443...
* Connected to myexampleuser.test (127.0.0.1) port 443 (#0)
* ALPN: offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* LibreSSL/3.3.6: error:1404B438:SSL routines:ST_CONNECT:tlsv1 alert internal error
* Closing connection 0
curl: (35) LibreSSL/3.3.6: error:1404B438:SSL routines:ST_CONNECT:tlsv1 alert internal error

2. Error messages and/or full log output:

app-caddy-1  | {"level":"debug","ts":1693417155.99898,"logger":"events","msg":"event","name":"tls_get_certificate","id":"9615e8ad-3e29-4af4-8edc-765bb59a1eb6","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":"myexampleuser.test","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":{}}}}
app-caddy-1  | {"level":"debug","ts":1693417155.9993315,"logger":"tls.handshake","msg":"no matching certificates and no custom selection logic","identifier":"myexampleuser.test"}
app-caddy-1  | {"level":"debug","ts":1693417155.9993403,"logger":"tls.handshake","msg":"no matching certificates and no custom selection logic","identifier":"*.test"}
app-caddy-1  | {"level":"debug","ts":1693417155.999344,"logger":"tls.handshake","msg":"no matching certificates and no custom selection logic","identifier":"*.*"}
app-caddy-1  | {"level":"debug","ts":1693417155.9993725,"logger":"tls.handshake","msg":"all external certificate managers yielded no certificates and no errors","remote_ip":"198.19.248.1","remote_port":"16485","sni":"myexampleuser.test"}
app-caddy-1  | {"level":"debug","ts":1693417155.9993799,"logger":"tls.handshake","msg":"no certificate matching TLS ClientHello","remote_ip":"198.19.248.1","remote_port":"16485","server_name":"myexampleuser.test","remote":"198.19.248.1:16485","identifier":"myexampleuser.test","cipher_suites":[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],"cert_cache_fill":0,"load_if_necessary":true,"obtain_if_necessary":true,"on_demand":false}
app-caddy-1  | {"level":"debug","ts":1693417155.9995995,"logger":"http.stdlib","msg":"http: TLS handshake error from 198.19.248.1:16485: no certificate available for 'myexampleuser.test'"}

3. Caddy version:

2.6.4

4. How I installed and ran Caddy:

a. System environment:

MacOS, Orbstack (Docker), Docker Compose

version: '3'
services:

    caddy:
        image: caddy:2.6.4
        networks:
            - app
        ports:
            - "80:80"
            - "443:443"
            - "2019:2019"
        volumes:
            - ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile
            - ./:/var/www/html
            - caddy-data:/data
            - caddy-config:/config

Caddyfile:

{
	debug
	admin 0.0.0.0:2019
	log default {
		output stderr
	}
	local_certs
	skip_install_trust
	pki {
		ca local {
			name "App Development Authority"
		}
	}
	on_demand_tls {
		burst 5
		interval 1s
	}
}

*.app.test, app.test, https://* {
	root * /var/www/html/public

	php_fastcgi fpm:9000
	file_server

	tls internal {
		on_demand
	}
}

b. Command:

docker-compose up -d caddy

c. Service/unit/compose file:

version: '3'
services:

    caddy:
        image: caddy:2.6.4
        networks:
            - app
        ports:
            - "80:80"
            - "443:443"
            - "2019:2019"
        volumes:
            - ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile
            - ./:/var/www/html
            - caddy-data:/data
            - caddy-config:/config

d. My complete Caddy config:

{
	debug
	admin 0.0.0.0:2019
	log default {
		output stderr
	}
	local_certs
	skip_install_trust
	pki {
		ca local {
			name "App Development Authority"
		}
	}
	on_demand_tls {
		burst 5
		interval 1s
	}
}

*.app.test, app.test, https://* {
	root * /var/www/html/public

	php_fastcgi fpm:9000
	file_server

	tls internal {
		on_demand
	}
}

5. Links to relevant resources:

A * only matches a single segment of a domain. Remove the * to match all hostnames.

2 Likes

Ah! You’re right! That works now, thank you so much!

1 Like

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