--- name: vps-deploy description: "Server auf den VPS (1984 Hosting, Island) deployen, Docker-Container verwalten, Logs prüfen, SSH-Verbindung, Troubleshooting. Trigger-Phrasen: 'deploy', 'deployen', 'VPS', 'Server deployen', 'Server starten', 'Server stoppen', 'Server logs', 'Container', 'Docker VPS', 'production', 'Produktion', '1984', 'Island-Server'." --- # Skill: VPS Deploy Deployt den Bollwerk Ktor-Server auf den 1984 Hosting VPS in Island. --- ## VPS-Infrastruktur | Eigenschaft | Wert | | --------------- | ----------------------------------------- | | Anbieter | 1984 Hosting (1984.is), Reykjavik, Island | | VPS-Name | vpshoxc2sc | | IP | `195.246.231.210` | | DNS PTR | vps-195-246-231-210.1984.is | | OS | Debian 12 (Bookworm) | | RAM | 2048 MB (Upgrade Mai 2026) | | CPU | 1 | | Disk | 50 GB SSD (Upgrade Mai 2026) | | Transfer | 1 TB/Monat | | Docker | Docker CE 29.x + docker-compose-plugin | | App-Verzeichnis | `/opt/krisenvorrat/` | --- ## SSH-Zugang ```powershell # Voraussetzung: SSH-Agent muss laufen und Key geladen sein ssh root@195.246.231.210 ``` ### SSH-Agent starten (einmalig pro Windows-Session) Der SSH-Key ist passphrase-geschützt. Der Agent muss laufen, damit Batch-Befehle funktionieren: ```powershell # 1. Agent-Dienst starten (braucht ggf. Admin-Rechte beim ersten Mal) Start-Service ssh-agent # 2. Key laden (fragt einmalig nach der Passphrase) ssh-add C:\Users\JensR\.ssh\id_ed25519 # Prüfen ssh-add -l ``` **Wichtig:** Ohne geladenen SSH-Agent schlagen alle `ssh`/`scp`-Befehle mit `Permission denied (publickey)` fehl. Immer zuerst `ssh-add -l` prüfen. ### SSH-Key-Details | Eigenschaft | Wert | | ----------- | ------------------------------------------------------- | | Typ | Ed25519 (256 Bit) | | Fingerprint | `SHA256:J/qjVt9r8CqnoshZFQWutau+3KG7JxDzRLHPyX41+gA` | | Private Key | `C:\Users\JensR\.ssh\id_ed25519` (passphrase-geschützt) | | Public Key | `C:\Users\JensR\.ssh\id_ed25519.pub` | | Kommentar | `bollwerk-vps` | --- ## Deployment-Workflow ### Vollständiges Deployment (JAR neu bauen + hochladen) ```powershell # 1. Fat-JAR lokal bauen cd x:\bollwerk .\gradlew.bat :server:buildFatJar # 2. JAR auf VPS kopieren scp x:\bollwerk\server\build\libs\server.jar root@195.246.231.210:/opt/krisenvorrat/server.jar # 3. Container neu bauen und starten ssh root@195.246.231.210 "cd /opt/krisenvorrat && docker compose up -d --build" ``` ### Nur Container neustarten (ohne neues JAR) ```powershell ssh root@195.246.231.210 "cd /opt/krisenvorrat && docker compose restart" ``` --- ## Docker-Konfiguration auf dem VPS ### Dockerfile (`/opt/krisenvorrat/Dockerfile`) ```dockerfile FROM eclipse-temurin:21-jre-alpine WORKDIR /app COPY server.jar server.jar EXPOSE 8080 ENTRYPOINT ["java", "-Xmx768m", "-jar", "server.jar"] ``` **Hinweis:** `-Xmx768m` begrenzt den JVM-Heap (VPS hat 2 GB RAM seit Upgrade Mai 2026). ### docker-compose.yml (`/opt/krisenvorrat/docker-compose.yml`) ```yaml services: bollwerk: build: . container_name: bollwerk-server restart: unless-stopped ports: - "8080:8080" environment: - BOLLWERK_JWT_SECRET= volumes: - ./data:/app/data ``` **Hinweis:** Das JWT-Secret NICHT in Skill-Dateien oder Git speichern. Es liegt nur in der `docker-compose.yml` auf dem VPS. --- ## Authentifizierung Der Server nutzt JWT-basierte Authentifizierung (kein API-Key mehr). ### Admin-Zugang - **Admin-UI:** `https://bollwerk.online/admin/` - **Admin-User:** `admin` - **Admin-Passwort:** Der User muss das Passwort selbst eingeben. Es ist NICHT gespeichert – bei Bedarf den User fragen. - Beim ersten Start ohne `BOLLWERK_ADMIN_PASSWORD` ENV wird ein zufälliges Passwort generiert und in die Logs geschrieben. ### Environment-Variablen | Variable | Pflicht | Beschreibung | | ------------------------- | ------- | -------------------------------------------------- | | `BOLLWERK_JWT_SECRET` | ja | Secret für JWT-Token-Signierung (mind. 32 Zeichen) | | `BOLLWERK_ADMIN_PASSWORD` | nein | Admin-Passwort beim ersten Start (sonst auto-gen.) | --- ## Server-Endpunkte | Endpunkt | Auth | Beschreibung | | --------------------------------- | ----- | ------------------------------------- | | `GET /api/health` | nein | Health-Check → "OK" | | `POST /api/auth/login` | nein | Login → JWT (Access + Refresh Token) | | `POST /api/auth/refresh` | nein | Access-Token erneuern | | `GET /api/inventory` | JWT | Inventar des Users abrufen | | `PUT /api/inventory` | JWT | Inventar des Users hochladen | | `PATCH /api/inventory/items/{id}` | JWT | Einzelnen Artikel updaten | | `GET /api/admin/users` | Admin | Alle User auflisten | | `POST /api/admin/users` | Admin | Neuen User anlegen | | `PUT /api/admin/users/{id}` | Admin | Passwort ändern | | `DELETE /api/admin/users/{id}` | Admin | User löschen | | `WS /ws/sync` | JWT | WebSocket für Push-Benachrichtigungen | JWT wird als `Authorization: Bearer ` Header mitgeschickt. --- ## Monitoring & Troubleshooting ### Container-Status prüfen ```powershell ssh root@195.246.231.210 "docker ps" ``` ### Logs anzeigen ```powershell # Letzte 50 Zeilen ssh root@195.246.231.210 "docker logs bollwerk-server --tail 50" # Live-Logs (Ctrl+C zum Beenden) ssh root@195.246.231.210 "docker logs bollwerk-server -f" ``` ### Health-Check ```powershell # Vom lokalen PC Invoke-WebRequest -Uri "https://bollwerk.online/api/health" -UseBasicParsing # Auf dem VPS direkt ssh root@195.246.231.210 "curl -s http://localhost:8080/api/health" ``` ### Container stoppen/starten ```powershell ssh root@195.246.231.210 "cd /opt/krisenvorrat && docker compose stop" ssh root@195.246.231.210 "cd /opt/krisenvorrat && docker compose start" ssh root@195.246.231.210 "cd /opt/krisenvorrat && docker compose down" # Container entfernen ``` ### RAM-Nutzung prüfen ```powershell ssh root@195.246.231.210 "free -h && echo '---' && docker stats --no-stream" ``` ### Daten-Persistenz Die SQLite-Datenbank wird unter `/opt/krisenvorrat/data/` auf dem Host gemountet und überlebt Container-Neustarts. --- ## Bekannte Einschränkungen - **1 GB RAM:** JVM-Heap auf 384 MB begrenzt. Kein Spielraum für weitere Dienste. - **Kein HTTPS:** Server läuft aktuell nur auf HTTP Port 8080. Für HTTPS → Caddy als Reverse Proxy einrichten. - **Kein CI/CD:** Deployment ist manuell (JAR bauen → scp → docker compose up). Ggf. GitHub Actions Pipeline ergänzen. - **Dockerfile lokal:** Das Dockerfile auf dem VPS (`/opt/krisenvorrat/Dockerfile`) ist ein schlankes Runtime-Only-Image. Das Multi-Stage-Dockerfile im Repo-Root ist für lokale Builds gedacht. - **SSH-Escape-Problem:** Beim Schreiben von Dateien via SSH-Heredoc werden JSON-Quotes zerstört. Dateien immer lokal erstellen und per `scp` hochladen.