Problem
I wanted a public portfolio that shows off the homelab (live status, a read-only terminal, the whole thing), but my ISP blocks inbound ports. I can't just point a domain at my house and call it a day.
christopher@homelab:~$ whoami
christopher. I build and run a homelab at home
christopher@homelab:~$ cat mission.txt
christopher@homelab:~$ _
How traffic gets to the static site, the live terminal, and everything running on the box at home.
A quick case study on shipping a public portfolio when your ISP won't let inbound ports through.
I wanted a public portfolio that shows off the homelab (live status, a read-only terminal, the whole thing), but my ISP blocks inbound ports. I can't just point a domain at my house and call it a day.
I put the static site on Cloudflare Pages (free, fast, no server to babysit). My afraid.org subdomain forwards to Pages so I get a clean URL. For the live terminal, a Cloudflare quick tunnel on the homelab exposes a WebSocket to a read-only gateway with sensitive paths blocked and output redacted. Status syncs from Uptime Kuma on a cron job.
Public site with zero open inbound ports. Visitors get HTTPS, live monitoring, and a sandboxed shell peek at the stack. Deploys are a script on the homelab that pushes to Pages. When the box reboots, Docker brings everything back in about two minutes.
All of this runs in Docker on one machine at my place. Caddy sits in front and handles HTTPS.
I use AdGuard Home with Unbound for network-wide blocking and recursive DNS. Queries go to the root servers, not some upstream resolver.
DoH, DoT, and DoQ endpoints so devices can resolve DNS privately. Works off-network too when I'm on the VPN.
Tailscale mesh VPN with an exit node and MagicDNS. I can reach everything at home from anywhere without opening ports.
Self-hosted SearXNG for search. No tracking, no profile building, just aggregated results.
Caddy as reverse proxy and TLS. Let's Encrypt certs via DNS-01, so every service gets a clean HTTPS URL.
Uptime Kuma for uptime, Beszel for metrics, Dozzle for container logs, and a speedtest tracker so I know when the ISP is acting up.
Homepage dashboard: one page with links and widgets for everything on the network.
Fabric Minecraft server (The Boys) with Chunky pregen and BlueMap for a live web map of the world.
Read-only shell into /opt/stacks and Minecraft config over a Cloudflare Tunnel. You can't edit anything. Sensitive paths are blocked and output gets redacted.
Pulled live from my Uptime Kuma instance. Updates every minute.
What happens when the box reboots, how status stays fresh, and what I actually monitor.
fetch_status.py runs every minute via cron. It pulls Uptime Kuma heartbeats, host uptime, deploy timestamp, and incident log into status.json, then deploys if the hash changed.No datacenter required. This whole stack runs on a recycled office desktop in my house.
I run a homelab at home: DNS, VPN, reverse proxy, monitoring, Docker containers, a Minecraft server. I set it all up and maintain it myself on hardware that's on 24/7 in my house.
Most of what I know about infra and Linux I picked up by actually running it, not just reading docs.
I'm available for contract work on homelab setup, Docker, reverse proxies, DNS/VPN, and self-hosted projects. If you want help standing up something similar, reach out on LinkedIn.