

Homelab from Zero #8: Clean internal HTTPS with Caddy
This is part 8 of Homelab from Zero. In
part 7 you learned what a reverse
proxy is and why your lab wants one. Today we install one (Caddy) and use
it to turn http://192.168.1.73:8080 into a clean https://heimdall.home with a
green padlock and no browser warning.
What we’re building
Right now every service lives at an IP and a port. By the end of this post:
| Before | After |
|---|---|
http://192.168.1.73:8080 |
https://heimdall.home |
http://192.168.1.73:8081/admin |
https://pihole.home |
http://192.168.1.73:3001 |
https://uptime.home |
Caddy sits in front of everything, terminates HTTPS, and routes each hostname to the right service. The certificates are issued and renewed automatically.
Step 1: Run Caddy
Caddy needs ports 80 and 443, so run it in a container that owns them:
docker run -d \ --name caddy \ -p 80:80 \ -p 443:443 \ -v ~/caddy/Caddyfile:/etc/caddy/Caddyfile \ -v ~/caddy/data:/data \ --restart unless-stopped \ caddy:2| Piece | Plain English |
|---|---|
-p 80:80 -p 443:443 |
The standard web ports: Caddy owns them |
-v ~/caddy/Caddyfile:... |
Your config file (we write it next) |
-v ~/caddy/data:/data |
Keeps the certificates across restarts |
Step 2: Write the Caddyfile
A Caddyfile is Caddy’s config, one block per hostname. Create
~/caddy/Caddyfile:
# Internal-only TLS. Caddy issues certs from its own local CA.*.home { tls internal
@heimdall host heimdall.home handle @heimdall { reverse_proxy 192.168.1.73:8080 }
@pihole host pihole.home handle @pihole { reverse_proxy 192.168.1.73:8081 }
@uptime host uptime.home handle @uptime { reverse_proxy 192.168.1.73:3001 }}Each @name host x.home / handle pair says: “when someone asks for this
hostname, forward to this service.” Reload Caddy to pick up the file:
docker exec caddy caddy reload --config /etc/caddy/CaddyfileStep 3: Why tls internal
On a public server you’d let Caddy fetch a real Let’s Encrypt certificate. But
.home isn’t a public domain; there’s no public DNS for Let’s Encrypt to
validate against. So we tell Caddy tls internal, which means Caddy runs its
own private certificate authority and signs certs itself.
The catch: your devices don’t trust that private CA yet, so you’ll still see a warning until you tell them to. That’s the next step.
Step 4: Point DNS at the proxy
Your laptop needs to know that heimdall.home means “the proxy.” You’re already
running Pi-hole, which makes this easy. In the Pi-hole admin page, go to
Settings → Local DNS → DNS Records and add one wildcard-style entry per
hostname, all pointing at the server:
heimdall.home → 192.168.1.73pihole.home → 192.168.1.73uptime.home → 192.168.1.73Now when any device on the network looks up heimdall.home, Pi-hole answers
with the proxy’s IP, and Caddy takes it from there.
Step 5: Trust the CA (the green padlock)
The last step removes the browser warning. Copy Caddy’s root certificate out of the container and install it on your computer:
docker cp caddy:/data/caddy/pki/authorities/local/root.crt ~/caddy-root.crtThen add ~/caddy-root.crt to your operating system’s trust store:
- macOS: open Keychain Access, import it, set it to “Always Trust.”
- Windows: double-click it → Install Certificate → Local Machine → Trusted Root Certification Authorities.
- Linux: copy to
/usr/local/share/ca-certificates/and runsudo update-ca-certificates.
Restart your browser and visit https://heimdall.home. Green padlock, no
warning. Do this once per device you browse from.
Redacted on purpose: use invented hostnames like
.homeand never expose this CA or these services to the public internet; it’s a LAN-only setup.
The commands you’ll actually use
| Command | What it does |
|---|---|
docker exec caddy caddy reload --config /etc/caddy/Caddyfile |
Apply Caddyfile changes |
docker logs caddy |
What is Caddy saying? (start here if a site won’t load) |
docker restart caddy |
Turn it off and on again |
What you have now
Every service in your lab answers at a clean https://name.home address with a
real green padlock, certificates issued and renewed automatically, and adding a
new service is just three lines in the Caddyfile plus a DNS record. Your lab
finally feels like a polished, professional setup.
In part 9 we go one step further: Tailscale, so you can reach all of this securely from anywhere (a coffee shop, your phone, another city) without opening a single port to the internet.
← Back to blog