Files
nixos-servers/docs/plans/remote-access.md
Torjus Håkestad eec1e374b2
Some checks failed
Run nix flake check / flake-check (push) Failing after 4m0s
docs: simplify mermaid diagram labels
Use <br/> for line breaks and shorter node labels so the diagram
renders cleanly in Gitea.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:29:52 +01:00

122 lines
4.5 KiB
Markdown

# 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
```mermaid
graph TD
clients["Laptop / Phone"]
vps["VPS<br/>(WireGuard endpoint)"]
extgw["extgw01<br/>(gateway + bastion)"]
grafana["Grafana<br/>monitoring01:3000"]
jellyfin["Jellyfin<br/>jelly01:8096"]
arr["arr stack<br/>*-jail hosts"]
clients -->|WireGuard| vps
vps -->|WireGuard tunnel| extgw
extgw -->|allowed traffic| grafana
extgw -->|allowed traffic| jellyfin
extgw -->|allowed traffic| arr
```
### 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