Internal HTTPS for a homelab with Caddy Internal HTTPS for a homelab with Caddy

Internal HTTPS for a homelab with Caddy

This is an example of the kind of write-up I like: a small, specific problem, solved end to end, with the config you can actually copy. Names and secrets are redacted; the structure is real.

The problem

Self-signed certs mean a browser warning on every internal service. I wanted clean https://service.home URLs with a green padlock, issued and renewed automatically, all inside the LAN.

The setup

PieceRole
Reverse proxyCaddy, terminating TLS for every service
DNSSplit-horizon: *.home resolves to the proxy’s LAN IP
ServicesPlain HTTP on the backend; Caddy adds TLS in front

The Caddyfile

# Internal-only TLS. Caddy issues certs from its own local CA and
# installs the root automatically on hosts that trust it.
*.home {
tls internal
@dashboard host dashboard.home
handle @dashboard {
reverse_proxy 127.0.0.1:8080
}
@git host git.home
handle @git {
reverse_proxy 192.168.1.50:3000
}
}

Why tls internal

On a public VPS you’d let Caddy fetch a real Let’s Encrypt cert. Inside the LAN there’s no public DNS to validate against, so tls internal tells Caddy to run its own CA. Trust the root once per device and every .home service is green.

Redacted on purpose: real hostnames, the CA fingerprint, and any tokens. The pattern is what’s worth sharing — not my secrets.

That’s the format. Specific problem, real config, nothing leaked.


← Back to blog