Internal CA - automatic renewal of intermediate cert

1. Caddy version (caddy version):

v2.4.5

2. How I run Caddy:

a. System environment:

I’m trying to implement this here at my home: Caddy reverse proxy + Nextcloud + Collabora + Vaultwarden with local HTTPS

  • Docker on Raspi 4 (hostname: rowena) behind private DSL (port 80 and 443 forwarded to Pi, DynDNS etc. all working fine)
  • Caddy container to be used as reverse proxy
  • Nextcloud as backend service
  • Caddy and Nextcloud service connected via Docker network

Goal: TLS between Frontend (reverse proxy) and backend (Nextcloud)

b. Command:

docker-compose up

c. Service/unit/compose file:

version: "3.8"

volumes:
  caddydata:
    name: proxy-caddydata
    external: true

networks:
  proxy:
    name: proxy-network

services:
  caddy:
    container_name: proxy
    image: caddy:latest
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./etc-caddy:/etc/caddy:ro
      - caddydata:/data

d. My complete Caddyfile or JSON config:

Caddyfile of reverse proxy container (FRONTEND):

{
	debug
	email hostmaster@mydomain.tld
	auto_https disable_redirects
}

localhost, rowena, rowena.local, proxy {
	acme_server
	tls internal
}

https://localhost, https://rowena, https://rowena.local {
	tls internal

        # just some test forwarding to my laptop
	reverse_proxy /8000 http://ronbook:8000 {
		header_up Host {http.reverse_proxy.upstream.hostport}
		header_up X-Forwarded-Host {host}
	}
        # just some test forwarding to another Raspi
	reverse_proxy http://altair {
		header_up Host {http.reverse_proxy.upstream.hostport}
		header_up X-Forwarded-Host {host}
	}
}

http://localhost, http://rowena, http://rowena.local {
	respond "Hello World!"
}

cloud.mydomain.tld {
	reverse_proxy https://altair {
		#header_up Host {http.reverse_proxy.upstream.hostport}
		header_up Host cloud.mydomain.tld:443
		header_up X-Forwarded-Host {host}
		transport http {
			tls_server_name cloud.mydomain.tld
		}
	}
}

test.mydomain.tld {
	reverse_proxy https://ncweb {
		header_up Host {http.reverse_proxy.upstream.hostport}
		header_up X-Forwarded-Host {host}
	}
}

3. The problem I’m having:

The Caddy intermediate certificate does not seem to renew automatically.

I observed that a few days ago already (see first part of this post). After tinkering around with my setup, the intermediate cert was renewed again (most likely because of a container restart).

Since then I kept Caddy running and I’m checking every day if the intermediate certificate gets renewed automatically.

This is the situation as of today.

It’s less than 1,5 days until the expiry of the intermediate.

I haven’t found some details about when the automatic intermediate cert renewal would kick in normally. Should it have happened already?
My expectation is, if I restarted the Caddy container now, during startup it would do the renewal properly.

But obviously it should work without the need of a restart, right?

Hmm, okay. This is strange.

Now it seems to have done the renewal.
Screenshot 2021-10-03 at 17.11.36

And I find this in the logs:

2021-10-03T09:06:11.620468530Z {"level":"info","ts":1633251971.6200566,"logger":"pki","msg":"intermediate expires soon; renewing","ca":"local","time_remaining":120660.379947579}
2021-10-03T09:06:11.625319486Z {"level":"info","ts":1633251971.624969,"logger":"pki","msg":"renewed intermediate","ca":"local","new_expiration":1633856771}

Apparently this has happened before I wrote this post earlier today.
But around the time of writing the initial post, it definitely did not work. :thinking:

Browsers, particularly Chrome, have a known bug that doesn’t play well with certs with short lifetimes (they do a lot of “magic” with TLS connections). If you use curl you’ll see that you can get the right certificate.

Right, I should have checked more thoroughly.

Thanks for pointing out a browser issue. If you happen to have some more details on that, I would be interested.