# 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.