bollwerk/.github/skills/vps-deploy/SKILL.md

190 lines
6.1 KiB
Markdown

---
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 Krisenvorrat 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 | 1024 MB |
| CPU | 1 |
| Disk | 25 GB SSD |
| 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 | `krisenvorrat-vps` |
---
## Deployment-Workflow
### Vollständiges Deployment (JAR neu bauen + hochladen)
```powershell
# 1. Fat-JAR lokal bauen
cd x:\krisenvorrat
.\gradlew.bat :server:buildFatJar
# 2. JAR auf VPS kopieren
scp x:\krisenvorrat\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", "-Xmx384m", "-jar", "server.jar"]
```
**Hinweis:** `-Xmx384m` begrenzt den JVM-Heap, weil der VPS nur 1 GB RAM hat.
### docker-compose.yml (`/opt/krisenvorrat/docker-compose.yml`)
```yaml
services:
krisenvorrat:
build: .
container_name: krisenvorrat-server
restart: unless-stopped
ports:
- '8080:8080'
environment:
- KRISENVORRAT_API_KEY=<key>
volumes:
- ./data:/app/data
```
**Hinweis:** Den echten API-Key NICHT in Skill-Dateien oder Git speichern. Er liegt nur in der `docker-compose.yml` auf dem VPS.
---
## Server-Endpunkte
| Endpunkt | Auth | Beschreibung |
| ----------------------- | ------- | ------------------ |
| `GET /api/health` | nein | Health-Check → "OK"|
| `GET /api/inventory` | API-Key | Inventar abrufen |
| `PUT /api/inventory` | API-Key | Inventar hochladen |
API-Key wird als `Authorization: Bearer <key>` oder `X-API-Key: <key>` 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 krisenvorrat-server --tail 50"
# Live-Logs (Ctrl+C zum Beenden)
ssh root@195.246.231.210 "docker logs krisenvorrat-server -f"
```
### Health-Check
```powershell
# Vom lokalen PC
Invoke-WebRequest -Uri "http://195.246.231.210:8080/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.