diff --git a/ADMIN-Frontend.md b/ADMIN-Frontend.md index 84a91c5..7b6199b 100644 --- a/ADMIN-Frontend.md +++ b/ADMIN-Frontend.md @@ -7,12 +7,13 @@ Das NSCT-Frontend ist eine **Single-Page-Application (SPA)**, die als statische ### 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/` -- **Runtime:** Node 22 Alpine, portiert auf `3000` -- **Proxy:** Caddy übernimmt TLS, Security Headers, Compression +- **Runtime:** Caddy liefert die statischen Assets auf Port `3000` aus. +- **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 - **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 -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 ``` -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 @@ -224,9 +233,6 @@ services: dockerfile: Dockerfile container_name: nsct-web restart: unless-stopped - environment: - - NSCT_API_BASE_URL=http://nsct-api:8080 - - DEFAULT_THEME=dark ports: - "3000:3000" # Direktzugriff (intern) networks: @@ -308,9 +314,10 @@ networks: driver: bridge ``` -Bridge-Netzwerk für inter-Container-Kommunikation. Container erreichen sich über ihren Namen als hostname: -- Web-Container erreicht Backend über `nsct-api:8080` -- Caddy erreicht Web-Container über `web:3000` +Das Bridge-Netzwerk verbindet ausschließlich die beiden Frontend-Container. +Caddy erreicht den Web-Container über `web:3000`. Das Backend wird nicht über +dieses Netzwerk adressiert, sondern über `NSCT_API_UPSTREAM` (DNS-Name oder IP +des Backend-Rechners). ### Resource Limits @@ -358,10 +365,9 @@ CMD ["node", "build"] **Stage 2 — Runtime:** - Node 22 Alpine (lean, ~70 MB) -- Nur `build/` und `node_modules` kopiert (kein Quellcode) -- Non-root-User `nsct` (Sicherheit) +- Die Build-Stage erzeugt `build/`; die Runtime liefert ausschließlich diese statischen Dateien aus. - Health-Check integriert -- Startet SvelteKit mit `node build` +- Caddy liefert die SPA einschließlich Fallback für Client-Routen aus. ### Vite Konfiguration @@ -374,7 +380,7 @@ export default defineConfig({ host: '0.0.0.0', proxy: { '/api': { - target: 'http://nsct-api:8080', + target: 'http://localhost:8080', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } @@ -384,8 +390,8 @@ export default defineConfig({ ``` - **Port:** 3000, strikte Bindung (`strictPort: true`) -- **Dev-Proxy:** `/api/*` wird an `http://nsct-api:8080` geroutet -- **Production:** Keine Proxy-Config — API-Calls gehen direkt an `NSCT_API_BASE_URL` +- **Dev-Proxy:** `/api/*` wird an ein lokal erreichbares Backend geroutet. +- **Production:** API-Calls gehen an `/api/*`; Caddy leitet sie an `NSCT_API_UPSTREAM` weiter. ### TailwindCSS Konfiguration @@ -550,8 +556,8 @@ localStorage.removeItem('nsct-api-key'); // Entfernen | Ursache | Diagnose | Lösung | |---|---|---| -| Falsche `NSCT_API_BASE_URL` | `curl $NSCT_API_BASE_URL/health` → fail | `.env` anpassen, `docker compose up -d` | -| CORS-Probleme (Backend) | Browser-Console: CORS error | Backend CORS-Headers prüfen | +| Falscher `NSCT_API_UPSTREAM` | `curl http://localhost/api/health` → fail | Host:Port in `.env` anpassen, `docker compose up -d` | +| 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 | | 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 docker compose logs web | grep -i error 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 @@ -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 | | Backend nicht erreichbar | `curl` auf Backend fail | Backend-Container 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 # 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 -- [ ] `.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 - [ ] 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`) -- [ ] 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 ### Deploy @@ -807,7 +813,7 @@ docker compose up -d 2. API-Anfrage (z.B. Research erstellen) → localStorage.getItem('nsct-api-key') - → POST ${NSCT_API_BASE_URL}/research + → POST /api/v1/research → Header: X-API-Key: → Body: { "query": "..." } @@ -817,7 +823,7 @@ docker compose up -d → Polling: pollingActive.set(true) → pollingInterval (5s) 4. Polling bis COMPLETED/FAILED - → GET ${NSCT_API_BASE_URL}/research/ + → GET /api/v1/research/ → X-API-Key: → Status prüfen: COMPLETED → pollingActive.set(false) diff --git a/README.md b/README.md index 782d3e1..1395fcc 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Web-Oberfläche für den **Neutral Search Crawler Tool (NSCT)** — eine Such- u │ └─────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ - ▼ fetch + ▼ /api/* ┌─────────────────────────────────────────────────────────────┐ │ Proxy │ │ ┌─────────────────────────────────────────────────────┐ │ @@ -34,7 +34,7 @@ Web-Oberfläche für den **Neutral Search Crawler Tool (NSCT)** — eine Such- u ┌─────────────────────────────────────────────────────────────┐ │ Backend API │ │ ┌─────────────────────────────────────────────────────┐ │ -│ │ NSCT Backend (Port 8080) │ │ +│ │ NSCT Backend auf separatem Rechner (z. B. :8080) │ │ │ │ - /v1/research │ │ │ │ - /v1/research/{id}/status │ │ │ │ - /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-Handling**: Polling bei COMPLETED/FAILED, onDestroy Cleanup - **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 @@ -68,19 +68,27 @@ npm run dev 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 -docker compose up -d +```env +# .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 | 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) | | `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`) - Build Output: `build/` - Polling: Alle 5 Sekunden, stoppt bei COMPLETED/FAILED -- Error-System: `ErrorBannerStore.ts` + `ErrorBanner.svelte` (stapelbar, auto-hide) \ No newline at end of file +- Error-System: `ErrorBannerStore.ts` + `ErrorBanner.svelte` (stapelbar, auto-hide)