From 43c63f0e59930ccc17d429489b576a2502ce06f2 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 12 Apr 2026 16:50:36 +0200 Subject: [PATCH] =?UTF-8?q?Deploy=20via=20rsync=20statt=20git=20auf=20DS?= =?UTF-8?q?=20=E2=80=94=20kein=20git=20auf=20DS=20n=C3=B6tig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 145 +++++++++++++++++++++++++------------------- scripts/setup-ds.sh | 137 ++++++++++++++++++----------------------- 2 files changed, 141 insertions(+), 141 deletions(-) diff --git a/Makefile b/Makefile index 151c2d0..3d965f4 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,9 @@ # ============================================================== # BAN YARO — Makefile -# Alle häufigen Operationen mit kurzen Befehlen. -# Verwendung: make +# Deploy-Strategie: rsync vom Mac zur DS (kein git auf DS nötig) +# Git wird nur lokal auf dem Mac und für Forgejo-Backup genutzt. # ============================================================== -# Konfiguration DS_HOST := ds DS_IP := 10.47.11.10 DS_SSH_PORT := 22 @@ -12,108 +11,128 @@ DS_PATH := /volume1/docker/ban-yaro CONTAINER := ban-yaro GIT_REMOTE := origin -.PHONY: help deploy push pull logs logs-f shell db restart stop status build \ - clean-cache dev lint check-ssh +# rsync: was NICHT auf die DS übertragen wird +RSYNC_EXCLUDE := --exclude='.git' \ + --exclude='data/' \ + --exclude='backend/venv/' \ + --exclude='backend/__pycache__/' \ + --exclude='backend/*.pyc' \ + --exclude='.env' \ + --exclude='*.db' \ + --exclude='.DS_Store' + +.PHONY: help deploy sync push restart build stop status \ + logs logs-f shell db dev clean-cache check-ssh # ---------------------------------------------------------- -# SSH-Prüfung — intern, wird von allen DS-Befehlen genutzt +# SSH-Prüfung — Abhängigkeit aller DS-Befehle # ---------------------------------------------------------- check-ssh: @if ! nc -z -w3 $(DS_IP) $(DS_SSH_PORT) 2>/dev/null; then \ echo ""; \ echo " ✗ DS nicht erreichbar ($(DS_IP):$(DS_SSH_PORT))"; \ echo ""; \ - echo " SSH-Port $(DS_SSH_PORT) ist geschlossen oder DS ist offline."; \ - echo " → Port in der Fritz!Box / DS-Firewall öffnen, dann erneut versuchen."; \ + echo " SSH-Port $(DS_SSH_PORT) ist geschlossen oder DS offline."; \ + echo " → Port in Fritz!Box / DS-Firewall öffnen, dann erneut versuchen."; \ echo ""; \ exit 1; \ fi # ---------------------------------------------------------- -# Standard: Hilfe anzeigen +# Hilfe # ---------------------------------------------------------- help: @echo "" @echo " Ban Yaro — verfügbare Befehle:" @echo "" - @echo " make deploy Push zu Git + Rebuild auf DS (häufigster Befehl)" - @echo " make push Nur Git push (ohne DS-Deploy)" - @echo " make pull Nur auf DS pullen + neustarten (ohne Git push)" - @echo " make restart Container neustarten (ohne Rebuild)" - @echo " make build Nur Docker-Image neu bauen (ohne Start)" + @echo " make deploy Sync + Rebuild + Neustart (häufigster Befehl)" + @echo " make sync Nur Dateien zur DS übertragen (ohne Rebuild)" + @echo " make push Nur Git push zu Forgejo (Backup/Versionierung)" + @echo " make restart Container neustarten (kein Rebuild)" + @echo " make build Docker neu bauen (ohne Neustart)" @echo " make stop Container stoppen" - @echo " make status Container-Status auf DS anzeigen" + @echo " make status Container-Status anzeigen" @echo "" - @echo " make logs Letzte 100 Log-Zeilen" - @echo " make logs-f Log-Stream (live)" - @echo " make shell Bash-Shell im Container" - @echo " make db SQLite-Shell auf DS" + @echo " make logs Letzte 100 Zeilen" + @echo " make logs-f Live-Log-Stream" + @echo " make shell Bash im Container" + @echo " make db SQLite-Shell" @echo "" - @echo " make dev Lokaler Entwicklungsserver (ohne Docker)" - @echo " make clean-cache Service Worker + Browser-Cache leeren (Push)" + @echo " make dev Lokaler Dev-Server auf Mac (Port 8001)" + @echo " make clean-cache SW-Cache-Version erhöhen + restart" @echo "" # ---------------------------------------------------------- -# DEPLOY: Git push → DS pull → Rebuild → Neustart -# Das ist der Befehl den du am meisten nutzen wirst. +# DEPLOY — der Haupt-Befehl +# 1. Git push (Backup) +# 2. rsync zum DS +# 3. Docker rebuild + restart # ---------------------------------------------------------- deploy: check-ssh - @echo "→ Git push..." + @echo "→ Git push (Backup)..." @git push $(GIT_REMOTE) main - @echo "→ DS: pull + rebuild + restart..." - @ssh $(DS_HOST) "cd $(DS_PATH) && \ - git pull && \ + @echo "→ Sync zu DS..." + @rsync -az --delete $(RSYNC_EXCLUDE) \ + ./ $(DS_HOST):$(DS_PATH)/ + @echo "→ Docker rebuild + restart..." + @ssh $(DS_HOST) " \ + cd $(DS_PATH) && \ sudo docker compose down && \ sudo docker compose build --no-cache && \ - sudo docker compose up -d && \ - echo '✓ Deploy fertig.' && \ - sudo docker compose logs --tail=20" + sudo docker compose up -d" + @echo "" + @echo " ✓ Deploy fertig. Letzte Logs:" + @ssh $(DS_HOST) "sudo docker logs $(CONTAINER) --tail=15" # ---------------------------------------------------------- -# NUR Git push (z.B. um nur Code zu sichern) +# SYNC — nur Dateien übertragen, kein Docker +# Sinnvoll für reine Frontend-Änderungen (CSS, JS, HTML) +# danach nur make restart statt make deploy +# ---------------------------------------------------------- +sync: check-ssh + @echo "→ Sync zu DS..." + @rsync -az --delete $(RSYNC_EXCLUDE) \ + ./ $(DS_HOST):$(DS_PATH)/ + @echo " ✓ Sync fertig." + +# ---------------------------------------------------------- +# PUSH — nur Git, ohne DS-Deploy # ---------------------------------------------------------- push: git push $(GIT_REMOTE) main # ---------------------------------------------------------- -# NUR auf DS deployen (ohne neuen Git push) -# z.B. wenn jemand anderes gepusht hat -# ---------------------------------------------------------- -pull: check-ssh - @ssh $(DS_HOST) "cd $(DS_PATH) && \ - git pull && \ - sudo docker compose down && \ - sudo docker compose up -d --build && \ - echo '✓ Pull + Restart fertig.'" - -# ---------------------------------------------------------- -# Nur neustarten (kein Rebuild, kein Git) -# z.B. nach .env-Änderung +# RESTART — kein Rebuild, nur Container neu starten +# Nach sync von reinen Frontend-Änderungen ausreichend # ---------------------------------------------------------- restart: check-ssh - @ssh $(DS_HOST) "cd $(DS_PATH) && \ - sudo docker compose restart $(CONTAINER) && \ - echo '✓ Container neugestartet.'" + @ssh $(DS_HOST) " \ + cd $(DS_PATH) && \ + sudo docker compose restart $(CONTAINER)" + @echo " ✓ Neugestartet." # ---------------------------------------------------------- -# Nur bauen (kein Start) +# BUILD — nur Docker-Image neu bauen # ---------------------------------------------------------- build: check-ssh - @ssh $(DS_HOST) "cd $(DS_PATH) && \ + @ssh $(DS_HOST) " \ + cd $(DS_PATH) && \ sudo docker compose build --no-cache" # ---------------------------------------------------------- -# Stoppen +# STOP # ---------------------------------------------------------- stop: check-ssh @ssh $(DS_HOST) "cd $(DS_PATH) && sudo docker compose down" + @echo " ✓ Gestoppt." # ---------------------------------------------------------- -# Status +# STATUS # ---------------------------------------------------------- status: check-ssh - @ssh $(DS_HOST) "sudo docker ps --filter name=$(CONTAINER) --format \ - 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'" + @ssh $(DS_HOST) "sudo docker ps \ + --filter name=$(CONTAINER) \ + --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'" # ---------------------------------------------------------- # LOGS @@ -131,15 +150,14 @@ shell: check-ssh @ssh -t $(DS_HOST) "sudo docker exec -it $(CONTAINER) bash" # ---------------------------------------------------------- -# SQLite direkt öffnen +# SQLite # ---------------------------------------------------------- db: check-ssh @ssh -t $(DS_HOST) "sudo docker exec -it $(CONTAINER) \ sqlite3 /data/banyaro.db" # ---------------------------------------------------------- -# Lokale Entwicklung (ohne Docker, direkt auf Mac) -# Voraussetzung: Python-Venv in backend/venv/ +# DEV — lokaler Server auf Mac (kein Docker, kein DS) # ---------------------------------------------------------- dev: @cd backend && \ @@ -152,12 +170,13 @@ dev: uvicorn main:app --reload --port 8001 # ---------------------------------------------------------- -# Service-Worker-Cache auf DS forciert leeren -# (nach größeren CSS/JS-Änderungen sinnvoll) +# CACHE leeren — SW-Version erhöhen, dann restart +# Nach größeren CSS/JS-Änderungen wenn SW gecacht hat # ---------------------------------------------------------- -clean-cache: - @ssh $(DS_HOST) "cd $(DS_PATH) && \ - sudo docker exec $(CONTAINER) \ - sed -i 's/by-v[0-9]*/by-v'$$(date +%s)'/g' /app/static/sw.js && \ - echo '✓ Cache-Version aktualisiert.'" +clean-cache: check-ssh + @NEW_VER="by-v$$(date +%s)"; \ + ssh $(DS_HOST) " \ + sed -i \"s/by-v[0-9]*/$$NEW_VER/g\" \ + $(DS_PATH)/backend/static/sw.js" @$(MAKE) restart + @echo " ✓ Cache-Version erhöht." diff --git a/scripts/setup-ds.sh b/scripts/setup-ds.sh index 49ba02d..5e09dde 100755 --- a/scripts/setup-ds.sh +++ b/scripts/setup-ds.sh @@ -2,10 +2,9 @@ # ============================================================== # BAN YARO — Ersteinrichtung auf der DiskStation # -# Läuft auf deinem MAC und richtet die DS per SSH ein. -# Du musst dieses Skript NICHT auf die DS kopieren. +# Läuft auf deinem MAC, richtet DS per SSH + rsync ein. +# Kein git auf DS nötig — Dateien kommen direkt vom Mac. # -# Voraussetzung: SSH-Port auf DS offen, SSH-Key eingerichtet # Aufruf: bash scripts/setup-ds.sh # ============================================================== @@ -15,44 +14,32 @@ DS_HOST="ds" DS_IP="10.47.11.10" DS_SSH_PORT="22" DS_PATH="/volume1/docker/ban-yaro" -REPO_URL="https://git.motocamp.de/rene/banyaro.git" # HTTPS, kein SSH-Key auf DS nötig +ROOT="$(cd "$(dirname "$0")/.." && pwd)" -# Farben RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' ok() { echo -e "${GREEN} ✓ $1${NC}"; } warn() { echo -e "${YELLOW} ⚠ $1${NC}"; } -err() { echo -e "${RED} ✗ $1${NC}"; } +err() { echo -e "${RED} ✗ $1${NC}"; exit 1; } echo "" echo "=== Ban Yaro — Ersteinrichtung DS1621 ===" echo "" # ---------------------------------------------------------- -# 0. SSH-Port prüfen BEVOR wir irgendwas versuchen +# 0. SSH-Port prüfen # ---------------------------------------------------------- echo "→ Prüfe SSH-Erreichbarkeit (${DS_IP}:${DS_SSH_PORT})..." if ! nc -z -w3 "$DS_IP" "$DS_SSH_PORT" 2>/dev/null; then - err "DS nicht erreichbar auf Port ${DS_SSH_PORT}!" echo "" - echo " Mögliche Ursachen:" - echo " • SSH-Port in der Fritz!Box ist geschlossen" - echo " • DS-Firewall blockiert Port ${DS_SSH_PORT}" - echo " • DS ist offline" - echo "" - echo " → SSH-Port öffnen, dann erneut ausführen." - echo "" - exit 1 + err "DS nicht erreichbar auf Port ${DS_SSH_PORT}! + Ursachen: SSH-Port in Fritz!Box geschlossen, DS offline + → Port öffnen, dann erneut ausführen." fi ok "SSH-Port ${DS_SSH_PORT} erreichbar" -# SSH-Verbindung selbst testen if ! ssh -q -o ConnectTimeout=5 -o BatchMode=yes "$DS_HOST" exit 2>/dev/null; then - err "SSH-Verbindung zu '${DS_HOST}' fehlgeschlagen!" - echo "" - echo " Prüfe: ssh ${DS_HOST} (muss ohne Passwort funktionieren)" - echo "" - exit 1 + err "SSH-Verbindung fehlgeschlagen — prüfe: ssh ${DS_HOST}" fi ok "SSH-Verbindung funktioniert" @@ -66,27 +53,27 @@ ssh "$DS_HOST" " mkdir -p '${DS_PATH}/data/media/dogs' mkdir -p '${DS_PATH}/data/media/diary' mkdir -p '${DS_PATH}/data/media/poison' - echo ' Verzeichnisstruktur:' - find '${DS_PATH}/data' -type d | sed 's/^/ /' " ok "Verzeichnisse angelegt" # ---------------------------------------------------------- -# 2. Repo klonen oder aktualisieren +# 2. Dateien per rsync übertragen (kein git auf DS nötig) # ---------------------------------------------------------- echo "" -echo "→ Repository..." +echo "→ Dateien übertragen (rsync)..." -ssh "$DS_HOST" " - if [ -d '${DS_PATH}/.git' ]; then - echo ' Existiert bereits — aktualisiere...' - cd '${DS_PATH}' && git pull - else - echo ' Klone von ${REPO_URL}...' - git clone '${REPO_URL}' '${DS_PATH}' - fi -" -ok "Repository bereit" +rsync -az --delete \ + --exclude='.git' \ + --exclude='data/' \ + --exclude='backend/venv/' \ + --exclude='backend/__pycache__/' \ + --exclude='backend/*.pyc' \ + --exclude='.env' \ + --exclude='*.db' \ + --exclude='.DS_Store' \ + "${ROOT}/" "${DS_HOST}:${DS_PATH}/" + +ok "Dateien übertragen" # ---------------------------------------------------------- # 3. .env anlegen @@ -94,46 +81,43 @@ ok "Repository bereit" echo "" echo "→ Konfiguration (.env)..." -ssh "$DS_HOST" " - if [ -f '${DS_PATH}/.env' ]; then - echo ' .env existiert bereits — wird nicht überschrieben.' - else - cp '${DS_PATH}/.env.example' '${DS_PATH}/.env' - echo ' .env angelegt aus .env.example' - fi -" +ENV_EXISTS=$(ssh "$DS_HOST" "[ -f '${DS_PATH}/.env' ] && echo yes || echo no") -# Prüfen ob JWT_SECRET noch der Default ist -JWT_CHECK=$(ssh "$DS_HOST" "grep 'JWT_SECRET' '${DS_PATH}/.env' | grep -c 'bitte-aendern'" 2>/dev/null || true) -if [ "$JWT_CHECK" -gt "0" ]; then - warn ".env muss noch angepasst werden!" +if [ "$ENV_EXISTS" = "yes" ]; then + ok ".env existiert bereits" +else + ssh "$DS_HOST" "cp '${DS_PATH}/.env.example' '${DS_PATH}/.env'" + warn ".env angelegt — muss noch angepasst werden!" +fi + +# Prüfen ob JWT_SECRET noch Default ist +JWT_UNSET=$(ssh "$DS_HOST" "grep -c 'bitte-aendern' '${DS_PATH}/.env' 2>/dev/null || echo 0") + +if [ "$JWT_UNSET" -gt "0" ]; then echo "" - echo " Mindestens setzen:" + warn "JWT_SECRET ist noch nicht gesetzt!" echo "" - echo " ssh ${DS_HOST}" - echo " nano ${DS_PATH}/.env" - echo "" - echo " ┌─────────────────────────────────────────────────────┐" - echo " │ JWT_SECRET= │" - echo " │ KI_MODE=local │" - echo " │ KI_LOCAL_URL=http://10.47.11.10:1234/v1 │" - echo " └─────────────────────────────────────────────────────┘" + echo " ┌──────────────────────────────────────────────┐" + echo " │ Mindestens setzen: │" + echo " │ JWT_SECRET= │" + echo " │ KI_MODE=local │" + echo " └──────────────────────────────────────────────┘" echo "" read -r -p " .env jetzt bearbeiten? [J/n] " REPLY - if [[ "${REPLY}" =~ ^[Jj]$ ]] || [[ -z "${REPLY}" ]]; then - ssh -t "$DS_HOST" "nano '${DS_PATH}/.env'" + if [[ "${REPLY}" =~ ^[Jj]$|^$ ]]; then + ssh -t "$DS_HOST" "vi '${DS_PATH}/.env'" else - warn "Nicht vergessen: .env vor dem nächsten Start anpassen!" + warn "Nicht vergessen: .env vor dem Start anpassen!" fi else ok ".env konfiguriert" fi # ---------------------------------------------------------- -# 4. Docker-Image bauen und starten +# 4. Docker bauen und starten # ---------------------------------------------------------- echo "" -echo "→ Docker build (kann 2-3 Minuten dauern)..." +echo "→ Docker build (dauert 2-3 Minuten)..." ssh "$DS_HOST" " cd '${DS_PATH}' && @@ -147,33 +131,30 @@ ok "Container gestartet" # ---------------------------------------------------------- echo "" echo "→ Warte auf App-Start..." -sleep 4 +sleep 5 + +STATUS=$(ssh "$DS_HOST" \ + "sudo docker ps --filter name=ban-yaro --format '{{.Status}}'" 2>/dev/null || true) -STATUS=$(ssh "$DS_HOST" "sudo docker ps --filter name=ban-yaro --format '{{.Status}}'" 2>/dev/null || true) if echo "$STATUS" | grep -q "Up"; then - ok "Container läuft: ${STATUS}" + ok "Container läuft — ${STATUS}" else - err "Container-Status: ${STATUS}" - echo " → Logs prüfen: make logs" + warn "Container-Status: '${STATUS}' — Logs prüfen: make logs" fi # ---------------------------------------------------------- -# 6. Zusammenfassung +# 6. Fertig # ---------------------------------------------------------- echo "" -echo "==========================================" -echo "" +echo "==================================" ok "Setup abgeschlossen!" echo "" echo " Nächste Schritte:" echo "" -echo " 1. NPM-Eintrag anlegen:" -echo " Host: banyaro.app" -echo " Ziel: http://10.47.11.10:3010" +echo " NPM-Eintrag anlegen:" +echo " Host: banyaro.app" +echo " Ziel: http://10.47.11.10:3010" echo "" -echo " 2. Logs prüfen:" -echo " make logs" -echo "" -echo " 3. App aufrufen:" -echo " https://banyaro.app" +echo " Logs: make logs" +echo " App: https://banyaro.app" echo ""