Sanitized mirror from private repository - 2026-03-20 09:49:40 UTC
This commit is contained in:
178
docs/infrastructure/offline-and-remote-access.md
Normal file
178
docs/infrastructure/offline-and-remote-access.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# Offline & Remote Access Guide
|
||||
|
||||
Last updated: 2026-03-20
|
||||
|
||||
## How DNS Resolution Works
|
||||
|
||||
The homelab uses **split-horizon DNS** so services are reachable from anywhere — LAN, Tailscale VPN, or the open internet — using the same `*.vish.gg` domain names.
|
||||
|
||||
### Three Access Paths
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────┐
|
||||
│ DNS Query: nb.vish.gg │
|
||||
├──────────────┬──────────────────┬────────────────────────────────────┤
|
||||
│ LAN Client │ Tailscale Client│ Internet Client │
|
||||
│ (at home) │ (travel laptop) │ (phone on cellular) │
|
||||
├──────────────┼──────────────────┼────────────────────────────────────┤
|
||||
│ DNS: AdGuard│ DNS: Headscale │ DNS: Cloudflare │
|
||||
│ (192.168.0 │ MagicDNS → │ (1.1.1.1) │
|
||||
│ .250) │ AdGuard │ │
|
||||
├──────────────┼──────────────────┼────────────────────────────────────┤
|
||||
│ Resolves to:│ Resolves to: │ Resolves to: │
|
||||
│ 100.85.21.51│ 100.85.21.51 │ 104.21.73.214 (Cloudflare) │
|
||||
│ (NPM via TS)│ (NPM via TS) │ │
|
||||
├──────────────┼──────────────────┼────────────────────────────────────┤
|
||||
│ Path: │ Path: │ Path: │
|
||||
│ Client → │ Client → │ Client → Cloudflare → │
|
||||
│ NPM (direct)│ Tailscale → │ Router → NPM → │
|
||||
│ → backend │ NPM → backend │ backend │
|
||||
├──────────────┼──────────────────┼────────────────────────────────────┤
|
||||
│ Latency: │ Latency: │ Latency: │
|
||||
│ ~1ms │ ~5-50ms │ ~50-100ms │
|
||||
│ (LAN) │ (Tailscale) │ (Cloudflare roundtrip) │
|
||||
├──────────────┼──────────────────┼────────────────────────────────────┤
|
||||
│ Internet │ Internet │ Internet │
|
||||
│ required? │ required? │ required? │
|
||||
│ NO │ NO (peer-to-peer│ YES │
|
||||
│ │ if both on TS) │ │
|
||||
└──────────────┴──────────────────┴────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Key: Everything Resolves to 100.85.21.51
|
||||
|
||||
All `*.vish.gg`, `*.thevish.io`, and `*.crista.love` domains resolve to `100.85.21.51` (matrix-ubuntu's Tailscale IP) when queried through AdGuard. This is NPM's address on the Tailscale network, reachable from:
|
||||
|
||||
- **LAN clients** — via the router's DHCP DNS (AdGuard at 192.168.0.250)
|
||||
- **Remote Tailscale clients** — via Headscale MagicDNS which forwards to AdGuard
|
||||
- **Both paths hit NPM on its Tailscale IP**, which works from anywhere on the tailnet
|
||||
|
||||
## When Internet Goes Down
|
||||
|
||||
If your WAN link drops:
|
||||
|
||||
| What works | How |
|
||||
|------------|-----|
|
||||
| All `*.vish.gg` services | AdGuard returns Tailscale IP, NPM proxies locally |
|
||||
| MagicDNS names (`atlantis.tail.vish.gg`) | Headscale resolves directly |
|
||||
| Direct Tailscale IPs (100.x.x.x) | Always work between peers |
|
||||
| Olares/K8s (k9s, kubectl) | LAN access at 192.168.0.145 |
|
||||
|
||||
| What breaks | Why |
|
||||
|-------------|-----|
|
||||
| External access (from internet) | Cloudflare can't reach you |
|
||||
| Cloudflare-only domains without split-horizon rewrite | DNS returns unreachable CF proxy IP |
|
||||
| Renovate, DDNS updates | Need internet to reach APIs |
|
||||
| DERP relays for remote peers | Remote Tailscale clients may lose connectivity |
|
||||
|
||||
## Access from Travel Laptop
|
||||
|
||||
Your travel laptop (MSI Prestige) connects via Headscale VPN:
|
||||
|
||||
1. **Join the tailnet**: `tailscale up --login-server=https://headscale.vish.gg`
|
||||
2. **DNS is automatic**: Headscale pushes AdGuard as the DNS server via MagicDNS
|
||||
3. **All domains work**: `nb.vish.gg`, `git.vish.gg`, etc. resolve to NPM's Tailscale IP
|
||||
4. **No VPN split tunneling needed**: Only homelab traffic routes through Tailscale
|
||||
|
||||
```bash
|
||||
# From the travel laptop:
|
||||
curl https://nb.vish.gg/ # → 100.85.21.51 (Tailscale) → NPM → backend
|
||||
curl https://gf.vish.gg/ # → 100.85.21.51 (Tailscale) → NPM → Grafana
|
||||
ssh homelab.tail.vish.gg # → MagicDNS → direct Tailscale peer
|
||||
```
|
||||
|
||||
### If Headscale Is Down
|
||||
|
||||
If the Headscale control server (calypso) is unreachable, already-connected peers maintain their connections. New peers can't join. Use direct Tailscale IPs as fallback:
|
||||
|
||||
| Service | Direct URL |
|
||||
|---------|-----------|
|
||||
| Grafana | `http://100.67.40.126:3300` |
|
||||
| NetBox | `http://100.67.40.126:8443` |
|
||||
| Portainer | `https://100.83.230.112:9443` |
|
||||
| Gitea | `http://100.103.48.78:3052` |
|
||||
|
||||
## MagicDNS (.tail.vish.gg)
|
||||
|
||||
Headscale MagicDNS provides `<hostname>.tail.vish.gg` for all peers:
|
||||
|
||||
| Hostname | Tailscale IP | Use |
|
||||
|----------|-------------|-----|
|
||||
| atlantis.tail.vish.gg | 100.83.230.112 | NAS, media |
|
||||
| calypso.tail.vish.gg | 100.103.48.78 | NAS, Gitea, auth |
|
||||
| homelab.tail.vish.gg | 100.67.40.126 | Monitoring, tools |
|
||||
| matrix-ubuntu.tail.vish.gg | 100.85.21.51 | NPM, Matrix, Mastodon |
|
||||
| pve.tail.vish.gg | 100.87.12.28 | Proxmox |
|
||||
| pi-5.tail.vish.gg | 100.77.151.40 | Uptime Kuma |
|
||||
| vish-concord-nuc.tail.vish.gg | 100.72.55.21 | Home Assistant, edge |
|
||||
| setillo.tail.vish.gg | 100.125.0.20 | Remote NAS |
|
||||
| seattle.tail.vish.gg | 100.82.197.124 | Cloud VPS |
|
||||
| truenas-scale.tail.vish.gg | 100.75.252.64 | TrueNAS |
|
||||
|
||||
**Note:** MagicDNS only works on devices connected to the Headscale tailnet. It requires the Tailscale client to override the system DNS resolver. Some devices (like pi-5 with AdGuard as DNS) can't resolve `.tail.vish.gg` names — use Tailscale IPs directly instead.
|
||||
|
||||
## AdGuard DNS Rewrites (Split-Horizon)
|
||||
|
||||
AdGuard on Calypso (`192.168.0.250:9080`) has wildcard rewrites:
|
||||
|
||||
| Domain Pattern | Resolves To | Purpose |
|
||||
|---------------|-------------|---------|
|
||||
| `*.vish.gg` | `100.85.21.51` | NPM via Tailscale |
|
||||
| `*.thevish.io` | `100.85.21.51` | NPM via Tailscale |
|
||||
| `*.crista.love` | `100.85.21.51` | NPM via Tailscale |
|
||||
| `derp.vish.gg` | `192.168.0.250` | DERP relay (direct) |
|
||||
| `derp-atl.vish.gg` | `192.168.0.200` | DERP relay (direct) |
|
||||
| `turn.thevish.io` | `192.168.0.200` | TURN server (direct) |
|
||||
|
||||
## SSL Certificates
|
||||
|
||||
All services use **Let's Encrypt wildcard certificates** (issued via DNS challenge with Cloudflare API):
|
||||
|
||||
| Certificate | Domains | Issuer |
|
||||
|------------|---------|--------|
|
||||
| Cert 8 | `*.vish.gg`, `vish.gg` | ZeroSSL (via acme.sh) |
|
||||
| Cert 9 | `*.thevish.io`, `thevish.io` | ZeroSSL (via acme.sh) |
|
||||
| Cert 10 | `*.crista.love`, `crista.love` | ZeroSSL (via acme.sh) |
|
||||
|
||||
These certs are **publicly trusted** — no certificate warnings on any access path (LAN, Tailscale, or internet).
|
||||
|
||||
### Certificate Renewal
|
||||
|
||||
acme.sh is installed on matrix-ubuntu (`/home/test/.acme.sh/`) with auto-renewal via cron. To manually renew:
|
||||
|
||||
```bash
|
||||
ssh matrix-ubuntu
|
||||
export CF_Token="REDACTED_TOKEN" # pragma: allowlist secret
|
||||
~/.acme.sh/acme.sh --renew -d '*.vish.gg' -d 'vish.gg' --force
|
||||
~/.acme.sh/acme.sh --renew -d '*.thevish.io' -d 'thevish.io' --force
|
||||
~/.acme.sh/acme.sh --renew -d '*.crista.love' -d 'crista.love' --force
|
||||
|
||||
# Then re-upload to NPM (certs need to be uploaded via NPM API or UI)
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### I'm at home on WiFi
|
||||
Just use `https://nb.vish.gg` — AdGuard resolves to NPM's Tailscale IP, works instantly.
|
||||
|
||||
### I'm traveling with the laptop
|
||||
Connect to Headscale tailnet → same URLs work: `https://nb.vish.gg`
|
||||
|
||||
### I'm on my phone (no VPN)
|
||||
Use the public URLs: `https://nb.vish.gg` → goes through Cloudflare as normal.
|
||||
|
||||
### Internet is down at home
|
||||
All services still work from LAN via AdGuard → Tailscale IP → NPM. No Cloudflare dependency.
|
||||
|
||||
### I need to access a service directly (no NPM)
|
||||
Use Tailscale IPs: `http://100.67.40.126:3300` (Grafana), `http://100.83.230.112:9443` (Portainer)
|
||||
|
||||
### Everything is down — emergency access
|
||||
SSH via Tailscale: `ssh homelab` (uses ~/.ssh/config with Tailscale IPs)
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Split-Horizon DNS Implementation](split-horizon-dns.md)
|
||||
- [NPM Migration Plan](npm-migration-to-matrix-ubuntu.md)
|
||||
- [Authentik SSO](authentik-sso.md)
|
||||
- [Image Update Guide](../admin/IMAGE_UPDATE_GUIDE.md)
|
||||
Reference in New Issue
Block a user