Document remote backend deployment

This commit is contained in:
faligam
2026-09-06 16:55:37 +02:00
parent fac3d1ce2c
commit c6f1889fe2
2 changed files with 48 additions and 34 deletions

View File

@@ -7,12 +7,13 @@ Das NSCT-Frontend ist eine **Single-Page-Application (SPA)**, die als statische
### Architektur ### Architektur
``` ```
Browser → Caddy (HTTPS/Reverse-Proxy) → Web-Container (Statische Assets) → NSCT-Backend (API) Browser → Caddy (`/` statische SPA, `/api/*` Proxy) → NSCT-Backend auf konfigurierbarem Host
``` ```
- **Build:** SvelteKit mit `@sveltejs/adapter-static` → alle Assets landen in `build/` - **Build:** SvelteKit mit `@sveltejs/adapter-static` → alle Assets landen in `build/`
- **Runtime:** Node 22 Alpine, portiert auf `3000` - **Runtime:** Caddy liefert die statischen Assets auf Port `3000` aus.
- **Proxy:** Caddy übernimmt TLS, Security Headers, Compression - **Proxy:** Der äußere Caddy übernimmt TLS, Security Headers, Compression und leitet `/api/*` an `NSCT_API_UPSTREAM` weiter.
- **Deployment:** Frontend und Backend können auf getrennten Rechnern laufen; sie benötigen kein gemeinsames Docker-Netzwerk.
- **Auth:** API-Key-basiert, persistiert im `localStorage` des Browsers - **Auth:** API-Key-basiert, persistiert im `localStorage` des Browsers
- **UI-Pattern:** Svelte 5 Stores (`writable`), TailwindCSS utility-first, Svelte 5 Runes - **UI-Pattern:** Svelte 5 Stores (`writable`), TailwindCSS utility-first, Svelte 5 Runes
@@ -30,7 +31,7 @@ Browser → Caddy (HTTPS/Reverse-Proxy) → Web-Container (Statische Assets) →
### Deployment ### Deployment
Multi-Stage Docker Build (Node 22 Alpine) → statische Assets → Caddy Reverse-Proxy. Multi-Stage Docker Build (Node 22 Alpine) → statische Assets → Caddy-Webserver → Caddy Reverse-Proxy.
--- ---
@@ -75,7 +76,15 @@ docker compose up -d
curl http://localhost:3000/health curl http://localhost:3000/health
``` ```
Erwartete Antwort: HTTP 200 mit JSON-Payload. Erwartete Antwort: HTTP 200.
### Backend-Verbindung prüfen
```bash
curl http://localhost/api/health
```
Die Anfrage wird durch Caddy an `${NSCT_API_UPSTREAM}/health` weitergeleitet. Für einen getrennten Backend-Rechner müssen DNS bzw. Firewall den Zugriff des Frontend-Rechners auf dessen API-Port erlauben.
### Browser öffnen ### Browser öffnen
@@ -224,9 +233,6 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: nsct-web container_name: nsct-web
restart: unless-stopped restart: unless-stopped
environment:
- NSCT_API_BASE_URL=http://nsct-api:8080
- DEFAULT_THEME=dark
ports: ports:
- "3000:3000" # Direktzugriff (intern) - "3000:3000" # Direktzugriff (intern)
networks: networks:
@@ -308,9 +314,10 @@ networks:
driver: bridge driver: bridge
``` ```
Bridge-Netzwerk für inter-Container-Kommunikation. Container erreichen sich über ihren Namen als hostname: Das Bridge-Netzwerk verbindet ausschließlich die beiden Frontend-Container.
- Web-Container erreicht Backend über `nsct-api:8080` Caddy erreicht den Web-Container über `web:3000`. Das Backend wird nicht über
- Caddy erreicht Web-Container über `web:3000` dieses Netzwerk adressiert, sondern über `NSCT_API_UPSTREAM` (DNS-Name oder IP
des Backend-Rechners).
### Resource Limits ### Resource Limits
@@ -358,10 +365,9 @@ CMD ["node", "build"]
**Stage 2 — Runtime:** **Stage 2 — Runtime:**
- Node 22 Alpine (lean, ~70 MB) - Node 22 Alpine (lean, ~70 MB)
- Nur `build/` und `node_modules` kopiert (kein Quellcode) - Die Build-Stage erzeugt `build/`; die Runtime liefert ausschließlich diese statischen Dateien aus.
- Non-root-User `nsct` (Sicherheit)
- Health-Check integriert - Health-Check integriert
- Startet SvelteKit mit `node build` - Caddy liefert die SPA einschließlich Fallback für Client-Routen aus.
### Vite Konfiguration ### Vite Konfiguration
@@ -374,7 +380,7 @@ export default defineConfig({
host: '0.0.0.0', host: '0.0.0.0',
proxy: { proxy: {
'/api': { '/api': {
target: 'http://nsct-api:8080', target: 'http://localhost:8080',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '') rewrite: (path) => path.replace(/^\/api/, '')
} }
@@ -384,8 +390,8 @@ export default defineConfig({
``` ```
- **Port:** 3000, strikte Bindung (`strictPort: true`) - **Port:** 3000, strikte Bindung (`strictPort: true`)
- **Dev-Proxy:** `/api/*` wird an `http://nsct-api:8080` geroutet - **Dev-Proxy:** `/api/*` wird an ein lokal erreichbares Backend geroutet.
- **Production:** Keine Proxy-Config — API-Calls gehen direkt an `NSCT_API_BASE_URL` - **Production:** API-Calls gehen an `/api/*`; Caddy leitet sie an `NSCT_API_UPSTREAM` weiter.
### TailwindCSS Konfiguration ### TailwindCSS Konfiguration
@@ -550,8 +556,8 @@ localStorage.removeItem('nsct-api-key'); // Entfernen
| Ursache | Diagnose | Lösung | | Ursache | Diagnose | Lösung |
|---|---|---| |---|---|---|
| Falsche `NSCT_API_BASE_URL` | `curl $NSCT_API_BASE_URL/health` → fail | `.env` anpassen, `docker compose up -d` | | Falscher `NSCT_API_UPSTREAM` | `curl http://localhost/api/health` → fail | Host:Port in `.env` anpassen, `docker compose up -d` |
| CORS-Probleme (Backend) | Browser-Console: CORS error | Backend CORS-Headers prüfen | | Netzwerk/Firewall blockiert Backend | `curl http://localhost/api/health` → 502 | DNS, Routing und Firewall zwischen den Rechnern prüfen |
| API-Key falsch/ungültig | 401/403 vom Backend | API-Key validieren, neu generieren | | API-Key falsch/ungültig | 401/403 vom Backend | API-Key validieren, neu generieren |
| Backend nicht erreichbar | `docker compose logs web` → connection refused | Backend-Container prüfen: `docker ps` | | Backend nicht erreichbar | `docker compose logs web` → connection refused | Backend-Container prüfen: `docker ps` |
@@ -559,7 +565,7 @@ localStorage.removeItem('nsct-api-key'); // Entfernen
# Diagnose-Skript # Diagnose-Skript
docker compose logs web | grep -i error docker compose logs web | grep -i error
curl -v http://localhost:3000/health curl -v http://localhost:3000/health
docker compose exec web wget -qO- http://nsct-api:8080/health || echo "Backend unreachable" curl -v http://localhost/api/health
``` ```
### Share-Links funktionieren nicht ### Share-Links funktionieren nicht
@@ -573,7 +579,7 @@ docker compose exec web wget -qO- http://nsct-api:8080/health || echo "Backend u
| Token abgelaufen | Backend gibt 404/410 zurück | Neues Share-Link generieren | | Token abgelaufen | Backend gibt 404/410 zurück | Neues Share-Link generieren |
| Backend nicht erreichbar | `curl` auf Backend fail | Backend-Container prüfen | | Backend nicht erreichbar | `curl` auf Backend fail | Backend-Container prüfen |
| Caddy-Proxy blockiert | Caddy logs zeigen 404 | Caddyfile auf `/share/`-Route prüfen | | Caddy-Proxy blockiert | Caddy logs zeigen 404 | Caddyfile auf `/share/`-Route prüfen |
| Falsche `NSCT_API_BASE_URL` | Frontend kann Share-Endpoint nicht reachen | `.env` überprüfen | | Falscher `NSCT_API_UPSTREAM` | Frontend kann Share-Endpoint nicht erreichen | `.env`, DNS und Firewall prüfen |
```bash ```bash
# Share-Token auf Gültigkeit prüfen # Share-Token auf Gültigkeit prüfen
@@ -720,11 +726,11 @@ Caddy 2.8 mit [`caddymetrics`](https://github.com/mholt/caddymetrics) oder built
### Pre-Deploy ### Pre-Deploy
- [ ] `.env`-Datei überprüft: `NSCT_API_BASE_URL`, `CADDY_DOMAIN`, `DEFAULT_THEME` - [ ] `.env`-Datei überprüft: `NSCT_API_UPSTREAM`, `CADDY_DOMAIN`
- [ ] DNS-Eintrag für `CADDY_DOMAIN` zeigt auf Server-IP - [ ] DNS-Eintrag für `CADDY_DOMAIN` zeigt auf Server-IP
- [ ] Ports 80 und 443 im Firewall/Security-Group freigeschaltet - [ ] Ports 80 und 443 im Firewall/Security-Group freigeschaltet
- [ ] Caddyfile auf Korrektheit geprüft (Syntax: `docker compose exec caddy caddy validate --config /etc/caddy/Caddyfile`) - [ ] Caddyfile auf Korrektheit geprüft (Syntax: `docker compose exec caddy caddy validate --config /etc/caddy/Caddyfile`)
- [ ] Backend-Container erreichbar: `docker compose exec web wget -qO- http://nsct-api:8080/health` - [ ] Backend vom Frontend-Rechner erreichbar: `curl http://localhost/api/health`
- [ ] Git-Status sauber: `git status` → kein uncommitted Code - [ ] Git-Status sauber: `git status` → kein uncommitted Code
### Deploy ### Deploy
@@ -807,7 +813,7 @@ docker compose up -d
2. API-Anfrage (z.B. Research erstellen) 2. API-Anfrage (z.B. Research erstellen)
→ localStorage.getItem('nsct-api-key') → localStorage.getItem('nsct-api-key')
→ POST ${NSCT_API_BASE_URL}/research → POST /api/v1/research
→ Header: X-API-Key: <key> → Header: X-API-Key: <key>
→ Body: { "query": "..." } → Body: { "query": "..." }
@@ -817,7 +823,7 @@ docker compose up -d
→ Polling: pollingActive.set(true) → pollingInterval (5s) → Polling: pollingActive.set(true) → pollingInterval (5s)
4. Polling bis COMPLETED/FAILED 4. Polling bis COMPLETED/FAILED
→ GET ${NSCT_API_BASE_URL}/research/<id> → GET /api/v1/research/<id>
→ X-API-Key: <key> → X-API-Key: <key>
→ Status prüfen: COMPLETED → pollingActive.set(false) → Status prüfen: COMPLETED → pollingActive.set(false)

View File

@@ -19,7 +19,7 @@ Web-Oberfläche für den **Neutral Search Crawler Tool (NSCT)** — eine Such- u
│ └─────────────────────────────────────────┘ │ │ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────┘
fetch /api/*
┌─────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────┐
│ Proxy │ │ Proxy │
│ ┌─────────────────────────────────────────────────────┐ │ │ ┌─────────────────────────────────────────────────────┐ │
@@ -34,7 +34,7 @@ Web-Oberfläche für den **Neutral Search Crawler Tool (NSCT)** — eine Such- u
┌─────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────┐
│ Backend API │ │ Backend API │
│ ┌─────────────────────────────────────────────────────┐ │ │ ┌─────────────────────────────────────────────────────┐ │
│ │ NSCT Backend (Port 8080) │ │ │ │ NSCT Backend auf separatem Rechner (z. B. :8080) │ │
│ │ - /v1/research │ │ │ │ - /v1/research │ │
│ │ - /v1/research/{id}/status │ │ │ │ - /v1/research/{id}/status │ │
│ │ - /v1/research/{id} │ │ │ │ - /v1/research/{id} │ │
@@ -51,7 +51,7 @@ Web-Oberfläche für den **Neutral Search Crawler Tool (NSCT)** — eine Such- u
- **Error-System**: Stapelbare Toast-Notifications mit Auto-hide - **Error-System**: Stapelbare Toast-Notifications mit Auto-hide
- **Error-Handling**: Polling bei COMPLETED/FAILED, onDestroy Cleanup - **Error-Handling**: Polling bei COMPLETED/FAILED, onDestroy Cleanup
- **Responsive Design**: Mobile-First mit TailwindCSS - **Responsive Design**: Mobile-First mit TailwindCSS
- **Docker Deployment**: Caddy Reverse-Proxy mit HTTPS, Healthchecks, Resource-Limits - **Docker Deployment**: Caddy Reverse-Proxy mit API-Weiterleitung, Healthchecks, Resource-Limits
## Installation ## Installation
@@ -68,19 +68,27 @@ npm run dev
docker compose up -d docker compose up -d
``` ```
### Mit API-Key ### Getrenntes Frontend- und Backend-Deployment
Setze die `NSCT_API_BASE_URL` Environment Variable für die Backend-Adresse: Frontend und Backend können auf unterschiedlichen Rechnern laufen. Der Browser
spricht ausschließlich die Frontend-Domain unter `/api/*` an; Caddy leitet diese
Anfragen an den Backend-Rechner weiter. Dadurch ist keine gemeinsame Docker-Bridge
und keine Backend-CORS-Freigabe für den Browser erforderlich.
```bash ```env
docker compose up -d # .env im Frontend-Repository; Host:Port, ohne http:// und ohne /api
NSCT_API_UPSTREAM=backend.example.com:8080
``` ```
Der Backend-Rechner muss vom Frontend-Rechner auf dem angegebenen Port erreichbar
sein. Für zwei Compose-Stacks auf demselben Rechner funktioniert der Default
`host.docker.internal:8080`.
## Environment Variables ## Environment Variables
| Variable | Beschreibung | Default | | Variable | Beschreibung | Default |
|----------|-------------|---------| |----------|-------------|---------|
| `NSCT_API_BASE_URL` | Backend API URL | `http://localhost:8080` | | `NSCT_API_UPSTREAM` | Erreichbarer Backend-Host inklusive Port | `host.docker.internal:8080` |
| `CADDY_DOMAIN` | Domain für HTTPS (Let's Encrypt) | keine (HTTP nur) | | `CADDY_DOMAIN` | Domain für HTTPS (Let's Encrypt) | keine (HTTP nur) |
| `NSCT_RATE_LIMIT` | Rate-Limit Config für Caddy | keine | | `NSCT_RATE_LIMIT` | Rate-Limit Config für Caddy | keine |
@@ -116,4 +124,4 @@ Die Tests befinden sich im `tests/`-Verzeichnis:
- SvelteKit Static Adapter (`adapter-static`) - SvelteKit Static Adapter (`adapter-static`)
- Build Output: `build/` - Build Output: `build/`
- Polling: Alle 5 Sekunden, stoppt bei COMPLETED/FAILED - Polling: Alle 5 Sekunden, stoppt bei COMPLETED/FAILED
- Error-System: `ErrorBannerStore.ts` + `ErrorBanner.svelte` (stapelbar, auto-hide) - Error-System: `ErrorBannerStore.ts` + `ErrorBanner.svelte` (stapelbar, auto-hide)