Back to Log
2026 — MAR 15 Networking Security 8 MIN READ

Deploying a Zero-Trust Network with Tailscale and Nginx Proxy Manager

How I rebuilt my home lab's networking layer from the ground up — eliminating exposed ports, hardening ingress rules, and achieving full mesh connectivity.

For years, my home lab ran on a patchwork of port forwards, dynamic DNS, and good intentions. It worked — mostly — but every exposed port was a liability, and I knew it. This is the story of how I tore it all down and rebuilt on a zero-trust foundation.

Why Zero Trust?

The traditional model assumes that anything inside your network is safe. Zero trust flips that entirely: verify everything, trust nothing. Every request is authenticated, every connection is encrypted, and no service is reachable unless explicitly permitted.

For a home lab, this might sound excessive. But consider what's running: Nextcloud with personal files, Vaultwarden with every password, Grafana with full infrastructure telemetry. These are worth protecting.

The threat model for a home lab isn't nation-state actors. It's misconfigured services, leaked credentials, and the slow accumulation of technical debt. — Personal notes, 2025

The Stack

After evaluating several options, I settled on Tailscale for mesh VPN and Nginx Proxy Manager for internal reverse proxying. Here's why:

  • Tailscale handles device authentication via your identity provider — no PKI to manage
  • WireGuard under the hood means excellent performance with minimal overhead
  • NPM provides a clean UI for managing SSL certs and proxy hosts
  • The two integrate cleanly: NPM listens on the Tailscale interface only

Installation

Start with Tailscale. On any Debian-based system, it's a single command:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --advertise-routes=192.168.1.0/24

The --advertise-routes flag is key — it lets other Tailscale nodes reach your entire local subnet, not just the device running Tailscale.

Nginx Proxy Manager via Docker

services:
  npm:
    image: jc21/nginx-proxy-manager:latest
    restart: unless-stopped
    ports:
      - "100.x.x.x:80:80"    # Tailscale IP only
      - "100.x.x.x:443:443"
      - "100.x.x.x:81:81"    # Admin UI
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

Note the bind to 100.x.x.x — your Tailscale IP. NPM will only be accessible via the VPN. No public exposure whatsoever.

Results

After migration: zero open ports on the router, all services behind authentication, SSL everywhere courtesy of Let's Encrypt via DNS challenge, and access from any device on the Tailnet — phone, laptop, a friend's machine with a quick invite.


The setup took an afternoon. The peace of mind has been permanent. If you're running any services worth protecting, I can't recommend this approach strongly enough.

// END OF TRANSMISSION — T. SEUGLING
← Back to Log