How to setup reverse proxy for homelab with Caddy server
Posted on April 1, 2020 • 2 minutes • 344 words
The end goal is to be able to expose apps deployed locally on homelab publicly. I don’t want to expose multiple ports to the Internet for several reasons:
- I have to create multiple port-forwarding rules.
- The address not memorable because I need to remember the ports. Eg:
homeip.example.com:32400
for Plex,homeip.example.com:1194
for VPN, and so on…
The alternative is to use reverse proxy.
- setup reverse proxy
- setup port forward (80 & 443) for reverse proxy
- config reverse proxy to proxy the local apps
Reverse proxy
I would have gone with nginx but I want to tinker with Caddy . I have never used Caddy in production and this seems like a good excuse to learn about it (That’s what homelab is for right?). Caddy comes with HTTPS by default via Lets Encrypt. It’s perfect for home usage.
I was wondering if it’s possible to proxy upstream to Docker host. Turns out it’s possible. You just have to use host.docker.internal
as upstream address. (ref
)
docker run -d -p 1880:80 -p 18443:443 --network home-net \
-v $(pwd)/Caddyfile:/etc/caddy/Caddyfile \
-v $(pwd)/site:/usr/share/caddy \
-v $(pwd)/data:/data \
-v $(pwd)/config:/config \
caddy/caddy caddy run -config /etc/caddy/Caddyfile --watch
Notice that I run Caddy in home-net
network there, so that I can easily proxy other containers.
Dynamic DNS
You need to setup
- an A record for your home IP (eg:
homeip.example.com
) - multiple CNAME records for each of your apps (eg:
plex.example.com
CNAME tohomeip.example.com
).
I covered this topic in a previous post of mine here.
Port forwarding
You need to do port forwarding (80 & 443) for your Reverse proxy. The setting is different, largely depends on your lab equipment and your ISP.
I was stuck for a day debugging why port forwarding didn’t work and it turned out, my ISP use NAT public IP address.
Verify
To test this, I create an nginx container with
docker run --name nginx --network home-net -d nginx
And edit the Caddyfile
to this
example.com {
reverse_proxy / nginx:80
}
And it should show nginx default page
Also, you should see the page in HTTPS.