2.9 KiB
2.9 KiB
Hybrid VPS + Home LLM Hosting Pattern
When migrating a web app that has hardcoded local LLM calls to a VPS, keep the LLM at home and proxy calls back through Tailscale. The app code doesn't change — only the nginx routing changes.
When to use
- The app makes
fetch('/llm/...')calls hardcoded to a local Ollama endpoint - The LLM requires a GPU (e.g., qwen2.5:14b at ~9GB VRAM) — a $5/mo VPS can't run it
- You want to move the frontend and database to a VPS (static IP, no home IP exposure)
- Home server stays on 24/7 anyway (Home Assistant, Immich, other services)
Architecture
VPS ($5/mo) Home server (Tailscale)
├── Frontend (SPA) ├── Ollama (port 11434)
├── PocketBase / SQLite └── Tailscale IP: 100.xx.xx.xx
├── Nginx (SSL)
│ ├── / → frontend
│ ├── /api/ → PocketBase (local on VPS)
│ └── /llm/ → Tailscale → home:11434
└── Tailscale
Nginx Config (VPS)
# Add to existing server block:
location /llm/ {
proxy_pass http://<home-tailscale-ip>:11434/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 120s;
proxy_buffering off;
}
Key properties
- Zero code changes. The app's
fetch('/llm/v1/chat/completions')calls work unchanged — nginx handles the routing. - Latency: +2-5ms Tailscale overhead. For non-streaming LLM API calls (50-500 tokens), the added latency is completely irrelevant — the LLM generation time (2-5 seconds) dominates.
- Bandwidth: LLM API responses are small (JSON, a few KB). Tailscale overhead is negligible.
- Reliability: If the home server goes down,
/llm/calls fail gracefully (the app should already handle API errors). Frontend and database keep working on the VPS.
Migration checklist
- VPS: Install nginx, Docker (for PocketBase if needed), Tailscale
- Rsync frontend to VPS
- Rsync database (PocketBase
pb_data/, SQLite files) to VPS - Tailscale: Authorize VPS on the tailnet, note home server's Tailscale IP
- Nginx: Add
/llm/proxy block pointing to home Tailscale IP - SSL: Let's Encrypt cert for the VPS domain
- DNS: Point domain to VPS IP
- Test: Hit
/llm/v1/modelsto verify Ollama is reachable through the proxy
Example: ShopProQuote
Real-world application (shop management SPA):
| Component | Size | Migrate? |
|---|---|---|
| Frontend (HTML/JS/CSS) | 110 MB | → VPS |
| PocketBase (SQLite) | 17 MB (380 KB DB) | → VPS |
| Ollama (qwen2.5:14b) | ~9 GB VRAM | → stays home |
| Nginx config | — | → recreate on VPS |
LLM endpoints used: priority analysis, AI Write, repair order suggestions, appointment OCR parsing. All via fetch('/llm/v1/chat/completions') with model: 'qwen2.5:14b'.
Downtime: ~10 minutes during DNS switch. Test on a subdomain first.