Homelab
Proof

U2 / 6 guides

Networking and remote access

Reverse proxies, VPNs, DNS filtering, local HTTPS and single sign-on. Each one is measured under load or proven with a real request, on an isolated network with no public ports.

Line drawing: a small server connected through a winding tunnel to a distant laptop, with a padlock-shaped gate in the middle of the tunnel.
  1. 2026-11-012.11.7Caddy vs Traefik vs NGINX vs NPM: reverse proxy measuredOn this 4 vCPU test VM, NGINX with upstream keepalive served the most requests per second (40,942 on plain HTTP) and used the least RAM, Traefik 25,941 and Caddy 17,888. A minimal NGINX config and Nginx Proxy Manager landed at 2,081 and 2,271 req/s, most likely because every proxied request opened a new upstream connection (not traced; see below).
  2. 2026-11-0115.5.0wg-easy 15.5.0: what a WireGuard tunnel costs in throughputwg-easy 15.5.0 stood up a working WireGuard tunnel from a scripted setup, with its API answering 3.8 s after the container started (one measurement, on a warm second start). On this 4 vCPU test VM, iperf3 through the tunnel reached 2.35 Gbit/s against 27.54 Gbit/s between the same containers without it, and whole-VM CPU rose from 41% to 81%.
  3. 2026-11-010.29.7Headscale 0.29.7 with two Tailscale clients, no DERP relayHeadscale 0.29.7 registered two official Tailscale 1.104.1 containers with a pre-auth key and they pinged each other over their tailnet IPs, directly. Without any DERP entry Headscale refused to start, and with a dead placeholder relay, blocking the direct UDP path left the two nodes unable to talk.
  4. 2026-11-022026.10.1Pi-hole vs AdGuard Home on one 300,000-domain listBoth blocked the test list correctly, answering 0.0.0.0 and ::, and both loaded 300,000 domains in under 3 s. Throughput was close and the three-run ranges overlap (Pi-hole 31,030 allowed and 24,888 blocked queries/s, AdGuard Home 29,292 and 29,161), but AdGuard Home idled at 57.8 MiB against Pi-hole's 10.0 MiB, and a Pi-hole container with Docker's 64 MB /dev/shm and its rate limit switched off exited mid-benchmark when that memory filled.
  5. 2026-11-012.11.7Local HTTPS without a public CA: Caddy internal vs step-caCaddy's internal CA issued a certificate for a .internal name in a median of 0.75 s with one extra line (tls internal) in the Caddyfile; step-ca over ACME took a median of 1.58 s once running, and for a .internal name it needed an explicit issuer block in the site config because a global acme_ca was ignored. Either way curl fails with exit 60 until the root is trusted, and passes with exit 0 afterwards.
  6. 2026-11-014.39.28Authelia vs authentik behind Caddy forward_auth, measuredBoth gated the backend correctly: no cookie got a redirect, and a scripted login got 200 with the user's name in a header. Authelia idled at 60.2 MiB (74.6 MiB with Caddy and the backend) and answered 1.82 s after start; authentik idled at 822.6 MiB across three containers (892.4 MiB across five with Caddy and the backend), answered 110.53 s after start, and needed three API write calls to wire up a protected app. The two times are single first-start measurements.