Document remote backend deployment
This commit is contained in:
@@ -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)
|
||||||
|
|
||||||
|
|||||||
24
README.md
24
README.md
@@ -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 |
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user