Some checks failed
Run nix flake check / flake-check (push) Failing after 4m0s
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>
122 lines
4.5 KiB
Markdown
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
|