From 267f668663a893ad7faf5131bd285ad084d64c25 Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Fri, 6 Feb 2026 02:00:35 +0100 Subject: [PATCH] Initial setup: Flask app with CI/CD --- .github/workflows/deploy.yml | 90 ++++ README.md | 22 +- requirements.txt | 1 + setupserver.md | 893 +++++++++++++++++++++++++++++++++++ 4 files changed, 1005 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/deploy.yml create mode 100644 setupserver.md diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..5aa18d1 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,90 @@ +name: Deploy to Infomaniak + +on: + push: + branches: + - main + workflow_dispatch: # Manueller Trigger möglich + +env: + APP_DIR: /opt/ollama-webapp + SERVICE_NAME: ollama-webapp + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + # 1. Code auschecken + - name: Checkout code + uses: actions/checkout@v4 + + # 2. SSH Setup + - name: Setup SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key + chmod 600 ~/.ssh/deploy_key + ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts + + # 3. Dateien zum Server kopieren + - name: Deploy files to server + run: | + rsync -avz --delete \ + -e "ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no" \ + --exclude '.git' \ + --exclude '.github' \ + --exclude '__pycache__' \ + --exclude '*.pyc' \ + --exclude 'venv' \ + --exclude '.env' \ + --exclude 'logs' \ + ./ ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ env.APP_DIR }}/app/ + + # 4. Dependencies installieren und Service neu starten + - name: Install dependencies and restart service + run: | + ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no \ + ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << 'ENDSSH' + + echo "📦 Installing dependencies..." + cd /opt/ollama-webapp + ./venv/bin/pip install -r app/requirements.txt --quiet --upgrade + + echo "🔄 Restarting service..." + sudo systemctl restart ollama-webapp + + echo "⏳ Waiting for service to start..." + sleep 5 + + echo "📊 Service status:" + sudo systemctl status ollama-webapp --no-pager -l + + echo "✅ Deployment complete!" + ENDSSH + + # 5. Health Check + - name: Health Check + run: | + echo "🏥 Running health check..." + sleep 3 + + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + http://${{ secrets.SERVER_HOST }}:5000/api/health || echo "000") + + if [ "$HTTP_STATUS" = "200" ]; then + echo "✅ Health check passed! (HTTP $HTTP_STATUS)" + else + echo "❌ Health check failed! (HTTP $HTTP_STATUS)" + exit 1 + fi + + # 6. Deployment Summary + - name: Deployment Summary + if: success() + run: | + echo "🎉 Deployment successful!" + echo "" + echo "📍 App URL: http://${{ secrets.SERVER_HOST }}:5000" + echo "📍 Health: http://${{ secrets.SERVER_HOST }}:5000/api/health" + echo "📍 Ollama: http://${{ secrets.SERVER_HOST }}:5000/api/ollama/status" \ No newline at end of file diff --git a/README.md b/README.md index 5ce7891..f328ee2 100644 --- a/README.md +++ b/README.md @@ -1 +1,21 @@ -# private-llm \ No newline at end of file +# Private LLM - Belegscanner + +KI-Dokumentenanalyse mit lokalen Ollama Vision-Modellen. + +## Features + +- Rechnungen, Belege, Bankauszüge analysieren +- Handschrift erkennen +- PDF-Support +- 100% lokal - keine Cloud-APIs + +## Tech Stack + +- **Backend:** Python Flask +- **AI:** Ollama Vision Models +- **Server:** Infomaniak Swiss Cloud (GPU) + +## Deployment + +Automatisches Deployment via GitHub Actions bei Push zu `main`. + diff --git a/requirements.txt b/requirements.txt index f718672..c350cd9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ flask-cors>=4.0.0 requests>=2.31.0 werkzeug>=3.0.0 pymupdf>=1.24.0 +gunicorn>=21.0.0 \ No newline at end of file diff --git a/setupserver.md b/setupserver.md new file mode 100644 index 0000000..f5249e9 --- /dev/null +++ b/setupserver.md @@ -0,0 +1,893 @@ +# Local LLM Server - Komplette Setup-Anleitung + +Von GitHub Repo-Setup über Cursor bis zum automatischen Deployment auf Infomaniak. + +--- + +## Access + +## Server Data + +IP 83.228.200.109 +Instance: local-llm Ubuntu 24.04 LTS Noble Numbat 83.228.226.58, 2001:1600:16:10::7e3 nvl4-a8-ram16-disk0 ollama-deploy-key Active az-1 +Connect: ssh -i "C:\Users\pmots\Downloads\ollama-deploy-key.pem" ubuntu@83.228.200.109 + + +## Übersicht + +``` +┌─────────────────┐ ┌─────────────────┐ +│ Cursor │◄──── sync ────────▶│ GitHub │ +│ (lokale Dev) │ │ private-llm │ +└─────────────────┘ └────────┬────────┘ + │ + │ Push to main + ▼ + ┌─────────────────┐ + │ GitHub Actions │ + └────────┬────────┘ + │ + │ SSH Deploy + ▼ + ┌─────────────────┐ + │ Infomaniak GPU │ + │ Server │ + │ ┌───────────┐ │ + │ │ Ollama │ │ + │ │ + Flask │ │ + │ │ (LLM + │ │ + │ │ Vision) │ │ + │ └───────────┘ │ + └─────────────────┘ +``` + +--- + +# Teil A: GitHub Repository Setup + +## A.1 Repository klonen in Cursor + +Öffne ein Terminal in Cursor oder lokal: + +```bash +# In deinen Projektordner wechseln +cd ~/Projects # oder wo du deine Projekte speicherst + +# Repository klonen +git clone https://github.com/valueonag/private-llm.git + +# In den Ordner wechseln +cd private-llm +``` + +## A.2 Cursor mit Repo verbinden + +**Option 1: Ordner in Cursor öffnen** +1. Cursor öffnen +2. **File → Open Folder** +3. Wähle den `private-llm` Ordner + +**Option 2: Über Terminal** +```bash +cd ~/Projects/private-llm +cursor . +``` + +## A.3 Projektstruktur erstellen + +Erstelle folgende Struktur: + +``` +private-llm/ +├── app.py # Deine Flask App +├── requirements.txt # Python Dependencies +├── templates/ +│ └── index.html # Frontend Template +├── static/ # CSS, JS, Bilder (optional) +├── .github/ +│ └── workflows/ +│ └── deploy.yml # CI/CD Pipeline +├── .gitignore +└── README.md +``` + +### A.3.1 requirements.txt + +Erstelle `requirements.txt`: + +```txt +flask>=3.0.0 +flask-cors>=4.0.0 +requests>=2.31.0 +pymupdf>=1.24.0 +gunicorn>=21.0.0 +``` + +### A.3.2 .gitignore + +Erstelle `.gitignore`: + +```gitignore +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +venv/ +env/ +.venv/ + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +.cursor/ + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log +logs/ + +# Environment +.env +.env.local + +# Test +.pytest_cache/ +.coverage +htmlcov/ +``` + +### A.3.3 README.md + +Erstelle `README.md`: + +```markdown +# Private LLM - Belegscanner + +KI-Dokumentenanalyse mit lokalen Ollama Vision-Modellen. + +## Features + +- Rechnungen, Belege, Bankauszüge analysieren +- Handschrift erkennen +- PDF-Support +- 100% lokal - keine Cloud-APIs + +## Tech Stack + +- **Backend:** Python Flask +- **AI:** Ollama Vision Models +- **Server:** Infomaniak Swiss Cloud (GPU) + +## Deployment + +Automatisches Deployment via GitHub Actions bei Push zu `main`. +``` + +--- + +# Teil B: GitHub Actions Deploy Workflow + +## B.1 Workflow-Datei erstellen + +Erstelle `.github/workflows/deploy.yml`: + +```yaml +name: Deploy to Infomaniak + +on: + push: + branches: + - main + workflow_dispatch: # Manueller Trigger möglich + +env: + APP_DIR: /opt/ollama-webapp + SERVICE_NAME: ollama-webapp + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + # 1. Code auschecken + - name: Checkout code + uses: actions/checkout@v4 + + # 2. SSH Setup + - name: Setup SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key + chmod 600 ~/.ssh/deploy_key + ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts + + # 3. Dateien zum Server kopieren + - name: Deploy files to server + run: | + rsync -avz --delete \ + -e "ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no" \ + --exclude '.git' \ + --exclude '.github' \ + --exclude '__pycache__' \ + --exclude '*.pyc' \ + --exclude 'venv' \ + --exclude '.env' \ + --exclude 'logs' \ + ./ ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ env.APP_DIR }}/app/ + + # 4. Dependencies installieren und Service neu starten + - name: Install dependencies and restart service + run: | + ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no \ + ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << 'ENDSSH' + + echo "📦 Installing dependencies..." + cd /opt/ollama-webapp + ./venv/bin/pip install -r app/requirements.txt --quiet --upgrade + + echo "🔄 Restarting service..." + sudo systemctl restart ollama-webapp + + echo "⏳ Waiting for service to start..." + sleep 5 + + echo "📊 Service status:" + sudo systemctl status ollama-webapp --no-pager -l + + echo "✅ Deployment complete!" + ENDSSH + + # 5. Health Check + - name: Health Check + run: | + echo "🏥 Running health check..." + sleep 3 + + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + http://${{ secrets.SERVER_HOST }}:5000/api/health || echo "000") + + if [ "$HTTP_STATUS" = "200" ]; then + echo "✅ Health check passed! (HTTP $HTTP_STATUS)" + else + echo "❌ Health check failed! (HTTP $HTTP_STATUS)" + exit 1 + fi + + # 6. Deployment Summary + - name: Deployment Summary + if: success() + run: | + echo "🎉 Deployment successful!" + echo "" + echo "📍 App URL: http://${{ secrets.SERVER_HOST }}:5000" + echo "📍 Health: http://${{ secrets.SERVER_HOST }}:5000/api/health" + echo "📍 Ollama: http://${{ secrets.SERVER_HOST }}:5000/api/ollama/status" +``` + +## B.2 GitHub Secrets einrichten + +1. Gehe zu: `https://github.com/valueonag/private-llm/settings/secrets/actions` +2. Klicke **New repository secret** +3. Erstelle diese 3 Secrets: + +| Secret Name | Wert | Beschreibung | +|-------------|------|--------------| +| `SERVER_HOST` | `185.xxx.xxx.xxx` | Deine Server-IP | +| `SERVER_USER` | `ubuntu` | SSH Benutzer | +| `SSH_PRIVATE_KEY` | `-----BEGIN OPENSSH...` | Der Private Key (ganzer Inhalt) | + +--- + +# Teil C: Infomaniak Server Setup + +## C.1 Horizon Dashboard Login + +1. Öffne: https://api.pub1.infomaniak.cloud/horizon +2. Login-Daten: + +| Feld | Wert | +|------|------| +| **Domain** | `PCU-MPXPVCR` | +| **User Name** | `PCU-MPXPVCR` | +| **Password** | Dein OpenStack-Passwort | + +--- + +## C.2 SSH Key Pair erstellen + +1. Gehe zu: **Compute → Key Pairs** +2. Klicke: **Create Key Pair** +3. Fülle aus: + +| Feld | Wert | +|------|------| +| **Key Pair Name** | `ollama-deploy-key` | +| **Key Type** | `SSH Key` | + +4. Klicke **Create Key Pair** +5. ⚠️ **WICHTIG:** Die `.pem` Datei wird automatisch heruntergeladen + - Speichere sie sicher ab (z.B. `~/Downloads/ollama-deploy-key.pem`) + - Du brauchst sie später für SSH-Zugang! + +--- + +## C.3 Security Group erstellen + +1. Gehe zu: **Network → Security Groups** +2. Klicke: **Create Security Group** +3. Fülle aus: + +| Feld | Wert | +|------|------| +| **Name** | `ollama-webapp` | +| **Description** | `Ports für Ollama und Flask App` | + +4. Klicke **Create Security Group** +5. In der Liste: Klicke **Manage Rules** bei `ollama-webapp` +6. Klicke **Add Rule** und erstelle diese Regeln: + +| Rule | Direction | Ether Type | IP Protocol | Port Range | CIDR | +|------|-----------|------------|-------------|------------|------| +| 1 | Ingress | IPv4 | TCP | 22 | `0.0.0.0/0` | +| 2 | Ingress | IPv4 | TCP | 80 | `0.0.0.0/0` | +| 3 | Ingress | IPv4 | TCP | 443 | `0.0.0.0/0` | +| 4 | Ingress | IPv4 | TCP | 5000 | `0.0.0.0/0` | +| 5 | Ingress | IPv4 | TCP | 11434 | `0.0.0.0/0` | + +**Für jede Regel:** +- Klicke **Add Rule** +- Direction: `Ingress` +- Wähle bei "Rule": `Custom TCP Rule` +- Port: Jeweilige Portnummer eingeben +- CIDR: `0.0.0.0/0` +- Klicke **Add** + +--- + +## C.4 GPU-Instanz erstellen + +1. Gehe zu: **Compute → Instances** +2. Klicke: **Launch Instance** + +### Tab 1: Details + +| Feld | Wert | +|------|------| +| **Instance Name** | `local-llm` | +| **Description** | `Local LLM Server` | +| **Availability Zone** | `nova` (Standard lassen) | +| **Count** | `1` | + +→ Klicke **Next** + +### Tab 2: Source + +| Feld | Wert | +|------|------| +| **Select Boot Source** | `Image` | +| **Create New Volume** | `Yes` ✓ | +| **Volume Size (GB)** | `150` | +| **Delete Volume on Instance Delete** | `No` ✗ | + +**Image auswählen:** +1. In der unteren Liste "Available" suche: `Ubuntu 24.04 LTS Noble Numbat` +2. Klicke den **↑ Pfeil** rechts davon +3. Das Image erscheint oben unter "Allocated" + +→ Klicke **Next** + +### Tab 3: Flavor + +**GPU-Flavor auswählen:** + +In der Liste "Available" suche nach GPU-Flavors (beginnen mit `nvl4-`, `t4-`, oder `a2-`): + +| Flavor | GPU | VRAM | vCPUs | RAM | Empfehlung | +|--------|-----|------|-------|-----|------------| +| `nvl4-12-46-0` | L4 | 24GB | 12 | 46GB | ✓ Beste Wahl | +| `t4-8-32-0` | T4 | 16GB | 8 | 32GB | Budget | +| `a2-8-32-0` | A2 | 16GB | 8 | 32GB | Alternative | + +1. Finde den gewünschten Flavor (z.B. mit "L4" oder "nvl4" im Namen) +2. Klicke den **↑ Pfeil** rechts davon +3. Der Flavor erscheint oben unter "Allocated" + +→ Klicke **Next** + +### Tab 4: Networks + +| Feld | Wert | +|------|------| +| **Network** | `ext-net1` | + +1. In der Liste "Available" finde: `ext-net1` +2. Klicke den **↑ Pfeil** +3. `ext-net1` erscheint unter "Allocated" + +→ Klicke **Next** + +### Tab 5: Network Ports + +Überspringe diesen Tab (leer lassen). + +→ Klicke **Next** + +### Tab 6: Security Groups + +1. Falls `default` unter "Allocated" steht: Klicke den **↓ Pfeil** um es zu entfernen +2. In "Available" finde: `ollama-webapp` +3. Klicke den **↑ Pfeil** +4. Unter "Allocated" sollte nur `ollama-webapp` stehen + +→ Klicke **Next** + +### Tab 7: Key Pair + +1. In "Available" finde: `ollama-deploy-key` +2. Klicke den **↑ Pfeil** +3. Unter "Allocated" steht: `ollama-deploy-key` + +→ Klicke **Next** + +### Tab 8: Configuration (optional) + +Überspringe diesen Tab (leer lassen). + +→ Klicke **Next** + +### Tab 9: Server Groups (optional) + +Überspringe diesen Tab (leer lassen). + +→ Klicke **Next** + +### Tab 10: Scheduler Hints (optional) + +Überspringe diesen Tab (leer lassen). + +→ Klicke **Next** + +### Tab 11: Metadata (optional) + +Überspringe diesen Tab (leer lassen). + +--- + +### Instanz starten + +Klicke: **Launch Instance** + +⏳ Warte bis der Status von `Build` zu `Active` wechselt (ca. 1-3 Minuten). + +--- + +## C.5 Floating IP zuweisen + +Die Instanz braucht eine öffentliche IP-Adresse: + +1. Gehe zu: **Network → Floating IPs** +2. Klicke: **Allocate IP to Project** +3. Wähle: + +| Feld | Wert | +|------|------| +| **Pool** | `ext-net1` | +| **Description** | `IP für Ollama Server` | + +4. Klicke **Allocate IP** +5. In der Liste: Klicke **Associate** bei der neuen IP +6. Wähle: + +| Feld | Wert | +|------|------| +| **Port to be associated** | `local-llm` (deine Instanz) | + +7. Klicke **Associate** + +📝 **Notiere dir die IP-Adresse** (z.B. `185.132.xxx.xxx`) - du brauchst sie für: +- SSH-Zugang +- GitHub Secrets +- Browser-Zugriff auf die App + +--- + +## C.6 Zusammenfassung deiner Instanz + +Nach erfolgreichem Setup hast du: + +| Komponente | Wert | +|------------|------| +| **Instance Name** | `local-llm` | +| **Description** | `Local LLM Server` | +| **Image** | Ubuntu 24.04 LTS | +| **Flavor** | GPU mit L4/T4/A2 | +| **Disk** | 150 GB | +| **Network** | `ext-net1` | +| **Security Group** | `ollama-webapp` | +| **Key Pair** | `ollama-deploy-key` | +| **Floating IP** | `185.xxx.xxx.xxx` | + +## C.2 Server Basis-Setup + +SSH zum Server: + +```bash +ssh -i ~/Downloads/ollama-deploy-key.pem ubuntu@185.xxx.xxx.xxx +``` + +### System aktualisieren + +```bash +sudo apt update && sudo apt upgrade -y +``` + +### NVIDIA-Treiber installieren + +```bash +sudo apt install -y nvidia-driver-550 +sudo reboot +``` + +Nach Neustart wieder verbinden und prüfen: + +```bash +nvidia-smi +``` + +### Ollama installieren + +```bash +# Installieren +curl -fsSL https://ollama.com/install.sh | sh + +# Konfigurieren +sudo systemctl edit ollama +``` + +Füge ein: + +```ini +[Service] +Environment="OLLAMA_HOST=0.0.0.0" +Environment="OLLAMA_ORIGINS=*" +Environment="OLLAMA_NUM_PARALLEL=4" +Environment="OLLAMA_MAX_LOADED_MODELS=2" +``` + +```bash +sudo systemctl restart ollama +sudo systemctl enable ollama +``` + +### Modelle herunterladen + +```bash +ollama pull granite3.2-vision +ollama pull qwen2.5vl:7b +ollama pull deepseek-ocr +``` + +## C.3 Python-Umgebung vorbereiten + +```bash +# Pakete installieren +sudo apt install -y python3-pip python3-venv git + +# App-Verzeichnis erstellen +sudo mkdir -p /opt/ollama-webapp/{app,venv,logs} +sudo chown -R ubuntu:ubuntu /opt/ollama-webapp + +# Virtual Environment erstellen +python3 -m venv /opt/ollama-webapp/venv + +# Basis-Pakete installieren +/opt/ollama-webapp/venv/bin/pip install --upgrade pip +/opt/ollama-webapp/venv/bin/pip install flask flask-cors requests pymupdf gunicorn +``` + +## C.4 Deploy SSH-Key erstellen (für GitHub Actions) + +```bash +# Key erstellen +ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/github_deploy_key -N "" + +# Zu authorized_keys hinzufügen +cat ~/.ssh/github_deploy_key.pub >> ~/.ssh/authorized_keys + +# Private Key anzeigen - DIESEN IN GITHUB SECRETS KOPIEREN! +echo "" +echo "==========================================" +echo "DIESEN KEY ALS 'SSH_PRIVATE_KEY' IN GITHUB SPEICHERN:" +echo "==========================================" +cat ~/.ssh/github_deploy_key +echo "" +echo "==========================================" +``` + +**Kopiere den kompletten Private Key** (inkl. `-----BEGIN...` und `-----END...`) und speichere ihn als GitHub Secret `SSH_PRIVATE_KEY`. + +## C.5 Systemd Service erstellen + +```bash +sudo nano /etc/systemd/system/ollama-webapp.service +``` + +Inhalt: + +```ini +[Unit] +Description=Belegscanner Flask App +After=network.target ollama.service +Wants=ollama.service + +[Service] +Type=simple +User=ubuntu +Group=ubuntu +WorkingDirectory=/opt/ollama-webapp/app +Environment="PATH=/opt/ollama-webapp/venv/bin:/usr/bin" +Environment="FLASK_ENV=production" +ExecStart=/opt/ollama-webapp/venv/bin/gunicorn \ + --bind 0.0.0.0:5000 \ + --workers 2 \ + --timeout 3600 \ + --access-logfile /opt/ollama-webapp/logs/access.log \ + --error-logfile /opt/ollama-webapp/logs/error.log \ + app:app +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +Aktivieren: + +```bash +sudo systemctl daemon-reload +sudo systemctl enable ollama-webapp +``` + +## C.6 Sudo-Rechte für GitHub Actions + +```bash +sudo visudo +``` + +Füge am Ende hinzu: + +``` +ubuntu ALL=(ALL) NOPASSWD: /bin/systemctl restart ollama-webapp +ubuntu ALL=(ALL) NOPASSWD: /bin/systemctl status ollama-webapp +ubuntu ALL=(ALL) NOPASSWD: /bin/systemctl stop ollama-webapp +ubuntu ALL=(ALL) NOPASSWD: /bin/systemctl start ollama-webapp +``` + +## C.7 Templates-Ordner erstellen + +Falls deine Flask-App Templates verwendet: + +```bash +mkdir -p /opt/ollama-webapp/app/templates +mkdir -p /opt/ollama-webapp/app/static +``` + +--- + +# Teil D: Erster Commit und Deploy + +## D.1 In Cursor: Code committen + +Öffne Terminal in Cursor (im `private-llm` Ordner): + +```bash +# Status prüfen +git status + +# Alle Dateien hinzufügen +git add . + +# Commit erstellen +git commit -m "Initial setup: Flask app with CI/CD" + +# Zu GitHub pushen +git push origin main +``` + +## D.2 GitHub Actions beobachten + +1. Gehe zu: `https://github.com/valueonag/private-llm/actions` +2. Du solltest einen laufenden Workflow sehen +3. Klicke drauf um den Fortschritt zu sehen + +## D.3 App testen + +Nach erfolgreichem Deploy: + +```bash +# Health Check +curl http://185.xxx.xxx.xxx:5000/api/health + +# Ollama Status +curl http://185.xxx.xxx.xxx:5000/api/ollama/status + +# Im Browser öffnen +open http://185.xxx.xxx.xxx:5000 +``` + +--- + +# Teil E: Entwicklungs-Workflow + +## E.1 Lokale Entwicklung in Cursor + +```bash +# Virtual Environment erstellen (einmalig) +cd ~/Projects/private-llm +python3 -m venv venv +source venv/bin/activate # Mac/Linux +# oder: .\venv\Scripts\activate # Windows + +# Dependencies installieren +pip install -r requirements.txt + +# Lokal starten (mit lokalem Ollama) +python app.py +``` + +## E.2 Änderungen deployen + +```bash +# Änderungen speichern +git add . + +# Commit mit Beschreibung +git commit -m "Feature: Neue Funktion XYZ" + +# Push zu GitHub → Automatischer Deploy! +git push origin main +``` + +## E.3 Cursor Git-Integration + +In Cursor kannst du auch die GUI nutzen: + +1. **Source Control** Tab (linke Sidebar) +2. Änderungen sehen +3. **+** um Dateien zu stagen +4. Commit Message eingeben +5. **✓** zum Committen +6. **...** → **Push** zum Pushen + +--- + +# Teil F: Nützliche Befehle + +## Server-Befehle + +```bash +# SSH zum Server +ssh -i ~/Downloads/ollama-deploy-key.pem ubuntu@185.xxx.xxx.xxx + +# Service Status +sudo systemctl status ollama-webapp +sudo systemctl status ollama + +# Logs anschauen +tail -f /opt/ollama-webapp/logs/access.log +tail -f /opt/ollama-webapp/logs/error.log +sudo journalctl -u ollama-webapp -f + +# Service neu starten +sudo systemctl restart ollama-webapp + +# GPU Status +nvidia-smi + +# Ollama Modelle +ollama list +ollama pull +``` + +## Git-Befehle + +```bash +# Status +git status + +# Änderungen sehen +git diff + +# Commit und Push +git add . +git commit -m "Beschreibung" +git push origin main + +# Vom Server holen (falls jemand anders gepusht hat) +git pull origin main +``` + +--- + +# Teil G: Troubleshooting + +## Deploy schlägt fehl + +1. **GitHub Actions Tab prüfen** - Fehlermeldung lesen +2. **SSH testen:** + ```bash + ssh -i ~/.ssh/github_deploy_key ubuntu@185.xxx.xxx.xxx + ``` +3. **Secrets prüfen** - Sind alle 3 Secrets korrekt? + +## App startet nicht + +```bash +# Auf dem Server: +sudo systemctl status ollama-webapp -l +cat /opt/ollama-webapp/logs/error.log +``` + +## Ollama nicht erreichbar + +```bash +# Status prüfen +sudo systemctl status ollama + +# Neu starten +sudo systemctl restart ollama + +# Logs +sudo journalctl -u ollama -f +``` + +--- + +# Checkliste + +## GitHub Setup +- [ ] Repository geklont +- [ ] Cursor mit Repo verbunden +- [ ] `requirements.txt` erstellt +- [ ] `.gitignore` erstellt +- [ ] `.github/workflows/deploy.yml` erstellt +- [ ] GitHub Secrets konfiguriert: + - [ ] `SERVER_HOST` + - [ ] `SERVER_USER` + - [ ] `SSH_PRIVATE_KEY` + +## Server Setup +- [ ] GPU-Instanz erstellt +- [ ] Floating IP zugewiesen +- [ ] NVIDIA-Treiber installiert +- [ ] Ollama installiert und konfiguriert +- [ ] Modelle heruntergeladen +- [ ] Python venv erstellt +- [ ] Deploy SSH-Key erstellt +- [ ] Systemd Service erstellt +- [ ] Sudo-Rechte konfiguriert + +## Erster Deploy +- [ ] Code committed und gepusht +- [ ] GitHub Actions erfolgreich +- [ ] Health Check funktioniert +- [ ] App im Browser erreichbar + +--- + +# URLs + +| Service | URL | +|---------|-----| +| App | `http://DEINE-IP:5000` | +| Health Check | `http://DEINE-IP:5000/api/health` | +| Ollama Status | `http://DEINE-IP:5000/api/ollama/status` | +| GitHub Repo | `https://github.com/valueonag/private-llm` | +| GitHub Actions | `https://github.com/valueonag/private-llm/actions` | \ No newline at end of file