Files
nixos-servers/docs/plans/remote-access.md
Torjus Håkestad af8e385b6e
Some checks failed
Run nix flake check / flake-check (push) Failing after 21m7s
Periodic flake update / flake-update (push) Successful in 2m16s
docs: finalize remote access plan with WireGuard gateway design
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:31:52 +01:00

5.7 KiB

Remote Access to Homelab Services

Status: Planning

Goal

Enable personal remote access to selected homelab services from outside the internal network, without exposing anything directly to the internet.

Current State

  • All services are only accessible from the internal 10.69.13.x network
  • http-proxy has a WireGuard tunnel (wg0, 10.69.222.0/24) to a VPS (docker2.t-juice.club) on an OpenStack cluster
  • VPS runs Traefik which proxies selected services (including Jellyfin) back through the tunnel to http-proxy's Caddy
  • No other services are directly exposed to the public internet

Decision: WireGuard Gateway

After evaluating WireGuard gateway vs Headscale (self-hosted Tailscale), the WireGuard gateway approach was chosen:

  • Only 2 client devices (laptop + phone), so Headscale's device management UX isn't needed
  • Split DNS works fine on Linux laptop via systemd-resolved; all-or-nothing DNS on phone is acceptable for occasional use
  • Simpler infrastructure - no control server to maintain
  • Builds on existing WireGuard experience and setup

Architecture

                    ┌─────────────────────────────────┐
                    │  VPS (OpenStack)                │
  Laptop/Phone ──→ │  WireGuard endpoint             │
  (WireGuard)      │  Client peers: laptop, phone    │
                    │  Routes 10.69.13.0/24 via tunnel│
                    └──────────┬──────────────────────┘
                               │ WireGuard tunnel
                               ▼
                    ┌─────────────────────────────────┐
                    │  extgw01 (gateway + bastion)    │
                    │  - WireGuard tunnel to VPS      │
                    │  - Firewall (allowlist only)    │
                    │  - SSH + 2FA (full access)      │
                    └──────────┬──────────────────────┘
                               │ allowed traffic only
                               ▼
                    ┌─────────────────────────────────┐
                    │  Internal network 10.69.13.0/24 │
                    │  - monitoring01:3000 (Grafana)  │
                    │  - jelly01:8096 (Jellyfin)      │
                    │  - *-jail hosts (arr stack)     │
                    └─────────────────────────────────┘

Existing path (unchanged)

The current public access path stays as-is:

Internet → VPS (Traefik) → WireGuard → http-proxy (Caddy) → internal services

This handles public Jellyfin access and any other publicly-exposed services.

New path (personal VPN)

A separate WireGuard tunnel for personal remote access with restricted firewall rules:

Laptop/Phone → VPS (WireGuard peers) → tunnel → extgw01 (firewall) → allowed services

Access tiers

  1. VPN (default): Laptop/phone connect to VPS WireGuard endpoint, traffic routed through extgw01 firewall. Only whitelisted services are reachable.
  2. SSH + 2FA (escalated): SSH into extgw01 for full network access when needed.

New Host: extgw01

A NixOS host on the internal network acting as both WireGuard gateway and SSH bastion.

Responsibilities

  • WireGuard tunnel to the VPS for client traffic
  • Firewall with allowlist controlling which internal services are reachable through the VPN
  • SSH bastion with 2FA for full network access when needed
  • DNS: Clients get split DNS config (laptop via systemd-resolved routing domain, phone uses internal DNS for all queries)

Firewall allowlist (initial)

Service Destination Port
Grafana monitoring01.home.2rjus.net 3000
Jellyfin jelly01.home.2rjus.net 8096
Sonarr sonarr-jail.home.2rjus.net 8989
Radarr radarr-jail.home.2rjus.net 7878
NZBget nzbget-jail.home.2rjus.net 6789

SSH 2FA options (to be decided)

  • Kanidm: Already deployed on kanidm01, supports RADIUS/OAuth2 for PAM integration
  • SSH certificates via OpenBao: Fits existing Vault infrastructure, short-lived certs
  • TOTP via PAM: Simplest fallback, Google Authenticator / similar

VPS Configuration

The VPS needs a new WireGuard interface (separate from the existing http-proxy tunnel):

  • WireGuard endpoint listening on a public UDP port
  • 2 peers: laptop, phone
  • Routes client traffic through tunnel to extgw01
  • Minimal config - just routing, no firewall policy (that lives on extgw01)

Implementation Steps

  1. Create extgw01 host configuration in this repo
    • VM provisioned via OpenTofu (same as other hosts)
    • WireGuard interface for VPS tunnel
    • nftables/iptables firewall with service allowlist
    • IP forwarding enabled
  2. Configure VPS WireGuard for client peers
    • New WireGuard interface with laptop + phone peers
    • Routing for 10.69.13.0/24 through extgw01 tunnel
  3. Set up client configs
    • Laptop: WireGuard config + systemd-resolved split DNS for home.2rjus.net
    • Phone: WireGuard app config with DNS pointing at internal nameservers
  4. Set up SSH 2FA on extgw01
    • Evaluate Kanidm integration vs OpenBao SSH certs vs TOTP
  5. Test and verify
    • VPN access to allowed services only
    • Firewall blocks everything else
    • SSH + 2FA grants full access
    • Existing public access path unaffected