# SPQ-v2 Nginx Deployment (grajmedia.duckdns.org) Serves the React/Vite SPA at **https://grajmedia.duckdns.org** on port 443. ## Current live config The live nginx config is at `/etc/nginx/sites-enabled/shopproquote` — this is a **regular file** (not a symlink to `sites-available/`), and its content is completely different from the one at `sites-available/shopproquote`. Always check the **sites-enabled** version first when debugging; the sites-available version is stale. ## Root directory ``` root /mnt/seagate8tb/Websites/ShopProQuote.backup-20260626-2058/spq-v2/dist; ``` ## Reverse proxy routes | Path | Target | Purpose | |------|--------|---------| | `/pb/` | `http://127.0.0.1:8091/` | PocketBase API (used by spq-v2) | | `/api/` | `http://127.0.0.1:8091/api/` | PocketBase API (compatibility) | | `/llm/` | `http://127.0.0.1:11434/` | Ollama LLM | | `/vision/` | `http://127.0.0.1:11434/` | Ollama vision model | | `/deepseek/` | `https://api.deepseek.com/` | DeepSeek API proxy (with auth header) | ## Security headers (Phase 3.3 / 1.4 — already LIVE) `/etc/nginx/snippets/spq-security.conf` is included at the top of the server block. Confirmed via `curl -sI`: - `Content-Security-Policy` (script-src 'self', style-src 'self' 'unsafe-inline', img-src 'self' data: blob:, frame-ancestors 'none') - `X-Content-Type-Options: nosniff` - `X-Frame-Options: DENY` - `Referrer-Policy: no-referrer` (stricter than roadmap's strict-origin-when-cross-origin) - `Permissions-Policy: microphone=(), geolocation=(), interest-cohort=()` Do NOT re-implement roadmap 3.3 or 3.4 from the spec — they are already deployed (static hosting + SPA fallback + /pb + /api reverse proxy). Verify with: ```bash curl -sI https://shopproquote.graj-media.com/ | grep -iE 'content-security|x-content|x-frame|referrer|permissions' ``` ## SPA fallback ```nginx location / { try_files $uri $uri/ /index.html; } ``` ## Building and deploying 1. Source code: `/mnt/seagate8tb/Websites/ShopProQuote.backup-20260626-2058/spq-v2/` 2. Run `npx vite build` in background mode (foreground gets falsely flagged as a server process): ``` cd /mnt/seagate8tb/Websites/ShopProQuote.backup-20260626-2058/spq-v2 ``` Use `terminal(background=true, notify_on_complete=true)` to build. 3. Build output goes to `dist/` in the same directory — nginx already points here, so no copy needed. 4. Reload nginx: `sudo nginx -t && sudo systemctl reload nginx` 5. Verify at https://grajmedia.duckdns.org ## Build workaround `npx vite build` in foreground mode is flagged by Hermes as a long-lived server process. Use background mode instead. The project uses Vite 8.x with rolldown — builds complete in <1s. ## Port conflict notes Port 3448 has a server_name conflict between `hermes-webui` (proxies to :8787) and `shopproquote` (serves legacy site). The VPS reverse proxy on graj-media.com sends traffic to port 443 (spq-v2), not 3448.