Automatic HTTPS with IP address

1. Caddy version (caddy version):


2. How I run Caddy:


a. System environment:

Ubuntu 20.04, Docker 20.10.15, Compose 1.25.0

b. Command:

docker-compose up -d

c. Service/unit/compose file:

version: "2.2"

    container_name: caddy-cluster-proxy
    image: caddy:2.5.1-alpine
    restart: unless-stopped
      - "80:80"
      - "443:443"
      - caddy_data:/data
      - ./:/etc/caddy/
    command: caddy run --config /etc/caddy/Caddyfile --watch

  # Cached caddy data, e.g. certs

d. My complete Caddyfile or JSON config:

import "*.Caddyfile"

} {
	header {
		Cache-Control "no-cache, no-store, must-revalidate"
	encode gzip
	handle_path /107731/* {
		reverse_proxy {
			flush_interval -1


3. The problem I’m having:

I want to enable HTTPS on just an IP address. When I use the above config I get HTTPS errors in my browser, and with curl:

curl -k -v
*   Trying
* Connected to ( port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Unknown (21):
* TLSv1.3 (IN), TLS alert, internal error (592):
* error:0A000438:SSL routines::tlsv1 alert internal error
* Closing connection 0
curl: (35) error:0A000438:SSL routines::tlsv1 alert internal error

4. Error messages and/or full log output:

{"level":"info","ts":1657528686.1966174,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":""}
{"level":"warn","ts":1657528686.19679,"msg":"No files matching import glob pattern","pattern":"*.Caddyfile"}
{"level":"warn","ts":1657528686.1981165,"msg":"Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":1}
{"level":"info","ts":1657528686.1991653,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//"]}
{"level":"info","ts":1657528686.1993258,"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":1657528686.199342,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1657528686.1994512,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000217ab0"}
{"level":"info","ts":1657528686.200295,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/data/caddy"}
{"level":"info","ts":1657528686.2009776,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"info","ts":1657528686.2203028,"logger":"","msg":"root certificate is already trusted by system","path":"storage:pki/authorities/local/root.crt"}
{"level":"debug","ts":1657528686.2206156,"logger":"http","msg":"starting server loop","address":"[::]:443","http3":false,"tls":true}
{"level":"debug","ts":1657528686.2206867,"logger":"http","msg":"starting server loop","address":"[::]:80","http3":false,"tls":false}
{"level":"info","ts":1657528686.2207088,"logger":"http","msg":"enabling automatic TLS certificate management","domains":[""]}
{"level":"warn","ts":1657528686.2211394,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for []: no OCSP server specified in certificate","identifiers":[""]}
{"level":"debug","ts":1657528686.2211623,"logger":"tls.cache","msg":"added certificate to cache","subjects":[""],"expiration":1657569657,"managed":true,"issuer_key":"local","hash":"9d440d4d2bbab98eeaf1e2a3ed669bbec7c347598f7f6a30bbffbc73b5ebc191","cache_size":1,"cache_capacity":10000}
{"level":"info","ts":1657528686.221428,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1657528686.2214453,"msg":"serving initial configuration"}
{"level":"info","ts":1657528686.2215388,"logger":"watcher","msg":"watching config file for changes","config_file":"/etc/caddy/Caddyfile"}

5. What I already tried:

I believe HTTPS is technically possible with IP addresses: https - Is it possible to have SSL certificate for IP address, not domain name? - Stack Overflow

And I think Caddy uses ZeroSSL, which supports certs for IP addresses:

But I’ve only seen cert errors when I use this setup.

(Why am I doing this? We spin up/down servers every day on a schedule with terraform. Getting DNS to work with this system would be a pain. Currently we have a few small permanent servers that I run Caddy on it with a regular domain name that reverse proxies to our Terraform servers, but I’m trying to remove this server-for-the-sake-of-a-domain-name).

6. Links to relevant resources:

Hi :wave:

Caddy is able to use certs for IP addresses.
It just won’t be publically trusted, but instead self-signed when using the auto-https feature currently.
The docs/automatic-https#hostname-requirements (pretty far down though) state:

In addition, hostnames qualify for publicly-trusted certificates if they:

  • are not an IP address

I am pretty sure I read an issue or some mention to track it not long ago, but I can’t seem to find it right now :frowning:
Maybe someone else has some insights on that.

A quick workaround, at least for now, if you want publicly-trusted certificates, would be to use services like that resolve as without any additional setup.
That way you would have a “valid” domain name :woman_shrugging:

Though, you really shouldn’t be getting SSL routines::tlsv1 alert internal error when using the plain IP.
Both { and { are valid and will serve that vhost via some self-signed certificate.

Are you absolutely sure that the Caddyfile and logs you shared are from the on the server publically accessible under and not some other server?



ZeroSSL supposedly supports it but nobody has tried it out yet to confirm whether they actually do. And Certmagic will probably need some updates/fixes to allow it if it does work.

But yeah, for now, you need a domain name. Or use Caddy’s internal CA.


As others have said, Caddy will present a certificate for an IP address, but it won’t be trusted by default. It attempts to install trust into the local root store, but that requires a password and only works for some clients on the local machine. (That’s not a limitation of Caddy.) For a publicly-trusted IP certificate, you’ll need a CA that supports issuing that (preferably via ACME, since Caddy supports that already).

Thank you so much! provides exactly what I need. And it’s easy and free. Appreciate it!

1 Like

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