Unable to upgrade existing services to HTTPS

Thanks for making Caddy!

1. The problem I’m having:

Upgrade services running on my local machine to be accessible only through HTTPS on my local network. Host is running these services through HTTP.

2. Error messages and/or full log output:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

3. Caddy version:

2.10.2-r1

4. How I installed and ran Caddy:

I installed www-servers/caddy through emerge. I’m on Gentoo.

Running caddy as a non-root user using:

caddy run --config ~/.config/caddy/Caddyfile

OR

caddy start --config ~/.config/caddy/Caddyfile

a. System environment:

My workstation is using OpenRC

b. Command:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

c. Service/unit/compose file:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

d. My complete Caddy config:

Ok. Here are the following configurations I’ve tried, followed by the errors:

localhost {
reverse_proxy localhost:1738 localhost:1740
}

localhost

reverse_proxy

Above two leads to Error code: SSL_ERROR_RX_RECORD_TOO_LONG


localhost:1738 localhost:1740
reverse_proxy

This one leads to Error: sending configuration to instance: caddy responded with error: HTTP 400: {“error”:“loading config: loading new config: http app module: start: listening on :1738: listen tcp :1738: bind: address already in use”}


For the following: Services are available though HTTPS, AND accessible through their corresponding HTTP ports. I won’t consider it the correct solution.

localhost:1111 {
reverse_proxy localhost:1738
}

localhost:1112 {
reverse_proxy localhost:1740
}

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

5. Links to relevant resources:

This should work, and generate a self-signed certificate, according to the documentation. What client are you using to connect that generated the error?

Try connecting using gnutls-cli instead so you can see what’s going on with the TLS negotiation.

What client are you using to connect that generated the error? → Librewolf, Zen, Chrome-beta and Cromite say “ERR_SSL_PROTOCOL_ERROR”. Last night I even tried on Chrome-Andriod. Same error as above. I probably need to use the root CA over my mobile phone too.

I don’t know how to use gnutls-cli

I used the following config

localhost {
reverse_proxy localhost:1738 localhost:1740 localhost:1742
}

And ran the following commands:

gnutls-cli http://localhost:1738/

gnutls-cli https://localhost:1738/

Processed 147 CA certificate(s).
Resolving ‘http://localhost:1738/’…
Cannot resolve http://localhost:1738/: Servname not supported for ai_socktype



gnutls-cli localhost:1738



Processed 147 CA certificate(s).
Resolving ‘localhost:1738’…
Connecting to ‘::1:1738’…
|<1>| Received record packet of unknown type 72
*** Fatal error: An unexpected TLS packet was received.

gnutls-cli 127.0.0.1 -p 1738

Processed 147 CA certificate(s).
Resolving ‘127.0.0.1:1738’…
Connecting to ‘127.0.0.1:1738’…
|<1>| Received record packet of unknown type 72
*** Fatal error: An unexpected TLS packet was received.


caddy run --config ~/.config/caddy/Caddyfile Logs:

2026/02/14 07:37:34.419	INFO	maxprocs: Leaving GOMAXPROCS=6: CPU quota undefined
2026/02/14 07:37:34.419	INFO	GOMEMLIMIT is updated	{"package": "github.com/KimMachineGun/automemlimit/memlimit", "GOMEMLIMIT": 22597340774, "previous": 9223372036854775807}
2026/02/14 07:37:34.419	INFO	using config from file	{"file": "/home/l3m0r/.config/caddy/Caddyfile"}
2026/02/14 07:37:34.419	INFO	adapted config to JSON	{"adapter": "caddyfile"}
2026/02/14 07:37:34.421	INFO	admin	admin endpoint started	{"address": "localhost:2019", "enforce_origin": false, "origins": ["//[::1]:2019", "//127.0.0.1:2019", "//localhost:2019"]}
2026/02/14 07:37:34.421	INFO	http.auto_https	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}
2026/02/14 07:37:34.421	INFO	http.auto_https	enabling automatic HTTP->HTTPS redirects	{"server_name": "srv0"}
2026/02/14 07:37:34.421	INFO	http	enabling HTTP/3 listener	{"addr": ":443"}
2026/02/14 07:37:34.421	INFO	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.
2026/02/14 07:37:34.421	INFO	http.log	server running	{"name": "srv0", "protocols": ["h1", "h2", "h3"]}
2026/02/14 07:37:34.421	WARN	http	HTTP/2 skipped because it requires TLS	{"network": "tcp", "addr": ":80"}
2026/02/14 07:37:34.421	WARN	http	HTTP/3 skipped because it requires TLS	{"network": "tcp", "addr": ":80"}
2026/02/14 07:37:34.421	INFO	http.log	server running	{"name": "remaining_auto_https_redirects", "protocols": ["h1", "h2", "h3"]}
2026/02/14 07:37:34.421	INFO	http	enabling automatic TLS certificate management	{"domains": ["localhost"]}
2026/02/14 07:37:34.421	WARN	tls	stapling OCSP	{"identifiers": ["localhost"]}
2026/02/14 07:37:34.421	INFO	pki.ca.local	root certificate is already trusted by system	{"path": "storage:pki/authorities/local/root.crt"}
2026/02/14 07:37:34.421	INFO	autosaved config (load with --resume flag)	{"file": "/home/l3m0r/.config/caddy/autosave.json"}
2026/02/14 07:37:34.421	INFO	serving initial configuration
2026/02/14 07:37:34.421	INFO	tls.cache.maintenance	started background certificate maintenance	{"cache": "0xc000626b80"}
2026/02/14 07:37:34.424	INFO	tls	storage cleaning happened too recently; skipping for now	{"storage": "FileStorage:/home/l3m0r/.local/share/caddy", "instance": "0ae22bdf-e090-4b7c-a5b0-0acf9fd749a4", "try_again": "2026/02/15 07:37:34.424", "try_again_in": 86399.99999966}
2026/02/14 07:37:34.424	INFO	tls	finished cleaning storage units

Why do you add the port? That is one of your http backend services, not where caddy is listening, according to the config you posted.

Ok.

I ran gnutls-cli localhost, It gave the following message:

Processed 147 CA certificate(s).
Resolving 'localhost:443'...
Connecting to '::1:443'...
- Certificate type: X.509
- Got a certificate list of 2 certificates.
- Certificate[0] info:
 - no subject,issuer `CN=Caddy Local Authority - ECC Intermediate', serial 0x00e9783a92f018b62647571d20c43e9698, EC/ECDSA key 256 bits, signed using ECDSA-SHA256, activated `2026-02-14 07:17:08 UTC', expires `2026-02-14 19:17:08 UTC', pin-sha256="01v4DM5YXO8xkSz9EuspEsnyYEV/z5ttJtnbRHfrziY="
	Public Key ID:
		sha1:1a342a15107b55edb6a85248b4366bac3138b014
		sha256:d35bf80cce585cef31912cfd12eb2912c9f260457fcf9b6d26d9db4477ebce26
	Public Key PIN:
		pin-sha256:01v4DM5YXO8xkSz9EuspEsnyYEV/z5ttJtnbRHfrziY=

- Certificate[1] info:
 - subject `CN=Caddy Local Authority - ECC Intermediate', issuer `CN=Caddy Local Authority - 2026 ECC Root', serial 0x00b22ae86b420beb3cc0db65c252d981ad, EC/ECDSA key 256 bits, signed using ECDSA-SHA256, activated `2026-02-13 13:42:41 UTC', expires `2026-02-20 13:42:41 UTC', pin-sha256="0oh/jzgBILXx4OtFd5sKtl2v/kki1+2KICcZCuMMPB4="
- Status: The certificate is NOT trusted. The certificate issuer is unknown.
*** PKI verification of server certificate failed...
*** Fatal error: Error in the certificate.

But what I want, is use backend services running on localhost:1738 localhost:1740 localhost:1742

OK, looks good. It didn’t like the self-signed certificate, but that’s expected. Use gnutls-cli --insecure to bypass that check.

OK. But caddy is listening on port 80 (http) and port 443 (https), as you configured it. Is that what you want?

When you got Above two leads to Error code: SSL_ERROR_RX_RECORD_TOO_LONG in your browser, what URL were you using?

Your browser isn’t going to like the self-signed certificate either, but it shouldn’t give you that error message.

OK, but how is Caddy going to use those? Currently you have told it to use all of them as equivalent. Do you want to have different hostnames for them, or different ports, or different paths?

OK. But caddy is listening on port 80 (http) and port 443 (https), as you configured it. Is that what you want?

No. Are you suggesting to use a config like the following?

localhost:1111 127.0.0.1:1111 {
reverse_proxy localhost:1738
}

localhost:1112 127.0.0.1:1112 {
reverse_proxy localhost:1740
}

localhost:1113 127.0.0.1:1113 {
reverse_proxy localhost:1742
}

what URL were you using? https://localhost:1738/


OK, but how is Caddy going to use those? Currently you have told it to use all of them as equivalent. Do you want to have different hostnames for them, or different ports, or different paths?

That’s an interesting question!

Before all of this, I forwarded the ports through my workstation. I’ve given my workstation a static IP and view the sites using IP:PORT in web browser.

  • Do you want to have different hostnames : Same hostname
  • Different ports or different paths: Different ports.

That’s one of your services listening on http - that’s why you got the SSL error. You didn’t even connect to caddy.

1 Like

Hmm… What’s the solution?

Um… The question is an xor.

1 Like

For clarity, we can go with different ports.

Then your config as above will work for different ports.

With everything on localhost I wonder what the point of using https is anyway, especially with the pain of self signed certificates and non-standard ports.