Deploy via rsync statt git auf DS — kein git auf DS nötig

This commit is contained in:
rene 2026-04-12 16:50:36 +02:00
parent 4499055b99
commit 43c63f0e59
2 changed files with 141 additions and 141 deletions

145
Makefile
View file

@ -1,10 +1,9 @@
# ============================================================== # ==============================================================
# BAN YARO — Makefile # BAN YARO — Makefile
# Alle häufigen Operationen mit kurzen Befehlen. # Deploy-Strategie: rsync vom Mac zur DS (kein git auf DS nötig)
# Verwendung: make <ziel> # Git wird nur lokal auf dem Mac und für Forgejo-Backup genutzt.
# ============================================================== # ==============================================================
# Konfiguration
DS_HOST := ds DS_HOST := ds
DS_IP := 10.47.11.10 DS_IP := 10.47.11.10
DS_SSH_PORT := 22 DS_SSH_PORT := 22
@ -12,108 +11,128 @@ DS_PATH := /volume1/docker/ban-yaro
CONTAINER := ban-yaro CONTAINER := ban-yaro
GIT_REMOTE := origin GIT_REMOTE := origin
.PHONY: help deploy push pull logs logs-f shell db restart stop status build \ # rsync: was NICHT auf die DS übertragen wird
clean-cache dev lint check-ssh 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: check-ssh:
@if ! nc -z -w3 $(DS_IP) $(DS_SSH_PORT) 2>/dev/null; then \ @if ! nc -z -w3 $(DS_IP) $(DS_SSH_PORT) 2>/dev/null; then \
echo ""; \ echo ""; \
echo " ✗ DS nicht erreichbar ($(DS_IP):$(DS_SSH_PORT))"; \ echo " ✗ DS nicht erreichbar ($(DS_IP):$(DS_SSH_PORT))"; \
echo ""; \ echo ""; \
echo " SSH-Port $(DS_SSH_PORT) ist geschlossen oder DS ist offline."; \ echo " SSH-Port $(DS_SSH_PORT) ist geschlossen oder DS offline."; \
echo " → Port in der Fritz!Box / DS-Firewall öffnen, dann erneut versuchen."; \ echo " → Port in Fritz!Box / DS-Firewall öffnen, dann erneut versuchen."; \
echo ""; \ echo ""; \
exit 1; \ exit 1; \
fi fi
# ---------------------------------------------------------- # ----------------------------------------------------------
# Standard: Hilfe anzeigen # Hilfe
# ---------------------------------------------------------- # ----------------------------------------------------------
help: help:
@echo "" @echo ""
@echo " Ban Yaro — verfügbare Befehle:" @echo " Ban Yaro — verfügbare Befehle:"
@echo "" @echo ""
@echo " make deploy Push zu Git + Rebuild auf DS (häufigster Befehl)" @echo " make deploy Sync + Rebuild + Neustart (häufigster Befehl)"
@echo " make push Nur Git push (ohne DS-Deploy)" @echo " make sync Nur Dateien zur DS übertragen (ohne Rebuild)"
@echo " make pull Nur auf DS pullen + neustarten (ohne Git push)" @echo " make push Nur Git push zu Forgejo (Backup/Versionierung)"
@echo " make restart Container neustarten (ohne Rebuild)" @echo " make restart Container neustarten (kein Rebuild)"
@echo " make build Nur Docker-Image neu bauen (ohne Start)" @echo " make build Docker neu bauen (ohne Neustart)"
@echo " make stop Container stoppen" @echo " make stop Container stoppen"
@echo " make status Container-Status auf DS anzeigen" @echo " make status Container-Status anzeigen"
@echo "" @echo ""
@echo " make logs Letzte 100 Log-Zeilen" @echo " make logs Letzte 100 Zeilen"
@echo " make logs-f Log-Stream (live)" @echo " make logs-f Live-Log-Stream"
@echo " make shell Bash-Shell im Container" @echo " make shell Bash im Container"
@echo " make db SQLite-Shell auf DS" @echo " make db SQLite-Shell"
@echo "" @echo ""
@echo " make dev Lokaler Entwicklungsserver (ohne Docker)" @echo " make dev Lokaler Dev-Server auf Mac (Port 8001)"
@echo " make clean-cache Service Worker + Browser-Cache leeren (Push)" @echo " make clean-cache SW-Cache-Version erhöhen + restart"
@echo "" @echo ""
# ---------------------------------------------------------- # ----------------------------------------------------------
# DEPLOY: Git push → DS pull → Rebuild → Neustart # DEPLOY — der Haupt-Befehl
# Das ist der Befehl den du am meisten nutzen wirst. # 1. Git push (Backup)
# 2. rsync zum DS
# 3. Docker rebuild + restart
# ---------------------------------------------------------- # ----------------------------------------------------------
deploy: check-ssh deploy: check-ssh
@echo "→ Git push..." @echo "→ Git push (Backup)..."
@git push $(GIT_REMOTE) main @git push $(GIT_REMOTE) main
@echo "→ DS: pull + rebuild + restart..." @echo "→ Sync zu DS..."
@ssh $(DS_HOST) "cd $(DS_PATH) && \ @rsync -az --delete $(RSYNC_EXCLUDE) \
git pull && \ ./ $(DS_HOST):$(DS_PATH)/
@echo "→ Docker rebuild + restart..."
@ssh $(DS_HOST) " \
cd $(DS_PATH) && \
sudo docker compose down && \ sudo docker compose down && \
sudo docker compose build --no-cache && \ sudo docker compose build --no-cache && \
sudo docker compose up -d && \ sudo docker compose up -d"
echo '✓ Deploy fertig.' && \ @echo ""
sudo docker compose logs --tail=20" @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: push:
git push $(GIT_REMOTE) main git push $(GIT_REMOTE) main
# ---------------------------------------------------------- # ----------------------------------------------------------
# NUR auf DS deployen (ohne neuen Git push) # RESTART — kein Rebuild, nur Container neu starten
# z.B. wenn jemand anderes gepusht hat # Nach sync von reinen Frontend-Änderungen ausreichend
# ----------------------------------------------------------
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: check-ssh restart: check-ssh
@ssh $(DS_HOST) "cd $(DS_PATH) && \ @ssh $(DS_HOST) " \
sudo docker compose restart $(CONTAINER) && \ cd $(DS_PATH) && \
echo '✓ Container neugestartet.'" sudo docker compose restart $(CONTAINER)"
@echo " ✓ Neugestartet."
# ---------------------------------------------------------- # ----------------------------------------------------------
# Nur bauen (kein Start) # BUILD — nur Docker-Image neu bauen
# ---------------------------------------------------------- # ----------------------------------------------------------
build: check-ssh build: check-ssh
@ssh $(DS_HOST) "cd $(DS_PATH) && \ @ssh $(DS_HOST) " \
cd $(DS_PATH) && \
sudo docker compose build --no-cache" sudo docker compose build --no-cache"
# ---------------------------------------------------------- # ----------------------------------------------------------
# Stoppen # STOP
# ---------------------------------------------------------- # ----------------------------------------------------------
stop: check-ssh stop: check-ssh
@ssh $(DS_HOST) "cd $(DS_PATH) && sudo docker compose down" @ssh $(DS_HOST) "cd $(DS_PATH) && sudo docker compose down"
@echo " ✓ Gestoppt."
# ---------------------------------------------------------- # ----------------------------------------------------------
# Status # STATUS
# ---------------------------------------------------------- # ----------------------------------------------------------
status: check-ssh status: check-ssh
@ssh $(DS_HOST) "sudo docker ps --filter name=$(CONTAINER) --format \ @ssh $(DS_HOST) "sudo docker ps \
'table {{.Names}}\t{{.Status}}\t{{.Ports}}'" --filter name=$(CONTAINER) \
--format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"
# ---------------------------------------------------------- # ----------------------------------------------------------
# LOGS # LOGS
@ -131,15 +150,14 @@ shell: check-ssh
@ssh -t $(DS_HOST) "sudo docker exec -it $(CONTAINER) bash" @ssh -t $(DS_HOST) "sudo docker exec -it $(CONTAINER) bash"
# ---------------------------------------------------------- # ----------------------------------------------------------
# SQLite direkt öffnen # SQLite
# ---------------------------------------------------------- # ----------------------------------------------------------
db: check-ssh db: check-ssh
@ssh -t $(DS_HOST) "sudo docker exec -it $(CONTAINER) \ @ssh -t $(DS_HOST) "sudo docker exec -it $(CONTAINER) \
sqlite3 /data/banyaro.db" sqlite3 /data/banyaro.db"
# ---------------------------------------------------------- # ----------------------------------------------------------
# Lokale Entwicklung (ohne Docker, direkt auf Mac) # DEV — lokaler Server auf Mac (kein Docker, kein DS)
# Voraussetzung: Python-Venv in backend/venv/
# ---------------------------------------------------------- # ----------------------------------------------------------
dev: dev:
@cd backend && \ @cd backend && \
@ -152,12 +170,13 @@ dev:
uvicorn main:app --reload --port 8001 uvicorn main:app --reload --port 8001
# ---------------------------------------------------------- # ----------------------------------------------------------
# Service-Worker-Cache auf DS forciert leeren # CACHE leeren — SW-Version erhöhen, dann restart
# (nach größeren CSS/JS-Änderungen sinnvoll) # Nach größeren CSS/JS-Änderungen wenn SW gecacht hat
# ---------------------------------------------------------- # ----------------------------------------------------------
clean-cache: clean-cache: check-ssh
@ssh $(DS_HOST) "cd $(DS_PATH) && \ @NEW_VER="by-v$$(date +%s)"; \
sudo docker exec $(CONTAINER) \ ssh $(DS_HOST) " \
sed -i 's/by-v[0-9]*/by-v'$$(date +%s)'/g' /app/static/sw.js && \ sed -i \"s/by-v[0-9]*/$$NEW_VER/g\" \
echo '✓ Cache-Version aktualisiert.'" $(DS_PATH)/backend/static/sw.js"
@$(MAKE) restart @$(MAKE) restart
@echo " ✓ Cache-Version erhöht."

View file

@ -2,10 +2,9 @@
# ============================================================== # ==============================================================
# BAN YARO — Ersteinrichtung auf der DiskStation # BAN YARO — Ersteinrichtung auf der DiskStation
# #
# Läuft auf deinem MAC und richtet die DS per SSH ein. # Läuft auf deinem MAC, richtet DS per SSH + rsync ein.
# Du musst dieses Skript NICHT auf die DS kopieren. # 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 # Aufruf: bash scripts/setup-ds.sh
# ============================================================== # ==============================================================
@ -15,44 +14,32 @@ DS_HOST="ds"
DS_IP="10.47.11.10" DS_IP="10.47.11.10"
DS_SSH_PORT="22" DS_SSH_PORT="22"
DS_PATH="/volume1/docker/ban-yaro" 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' RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
ok() { echo -e "${GREEN}$1${NC}"; } ok() { echo -e "${GREEN}$1${NC}"; }
warn() { echo -e "${YELLOW}$1${NC}"; } warn() { echo -e "${YELLOW}$1${NC}"; }
err() { echo -e "${RED}$1${NC}"; } err() { echo -e "${RED}$1${NC}"; exit 1; }
echo "" echo ""
echo "=== Ban Yaro — Ersteinrichtung DS1621 ===" echo "=== Ban Yaro — Ersteinrichtung DS1621 ==="
echo "" 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})..." echo "→ Prüfe SSH-Erreichbarkeit (${DS_IP}:${DS_SSH_PORT})..."
if ! nc -z -w3 "$DS_IP" "$DS_SSH_PORT" 2>/dev/null; then if ! nc -z -w3 "$DS_IP" "$DS_SSH_PORT" 2>/dev/null; then
err "DS nicht erreichbar auf Port ${DS_SSH_PORT}!"
echo "" echo ""
echo " Mögliche Ursachen:" err "DS nicht erreichbar auf Port ${DS_SSH_PORT}!
echo " • SSH-Port in der Fritz!Box ist geschlossen" Ursachen: SSH-Port in Fritz!Box geschlossen, DS offline
echo " • DS-Firewall blockiert Port ${DS_SSH_PORT}" → Port öffnen, dann erneut ausführen."
echo " • DS ist offline"
echo ""
echo " → SSH-Port öffnen, dann erneut ausführen."
echo ""
exit 1
fi fi
ok "SSH-Port ${DS_SSH_PORT} erreichbar" 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 if ! ssh -q -o ConnectTimeout=5 -o BatchMode=yes "$DS_HOST" exit 2>/dev/null; then
err "SSH-Verbindung zu '${DS_HOST}' fehlgeschlagen!" err "SSH-Verbindung fehlgeschlagen — prüfe: ssh ${DS_HOST}"
echo ""
echo " Prüfe: ssh ${DS_HOST} (muss ohne Passwort funktionieren)"
echo ""
exit 1
fi fi
ok "SSH-Verbindung funktioniert" ok "SSH-Verbindung funktioniert"
@ -66,27 +53,27 @@ ssh "$DS_HOST" "
mkdir -p '${DS_PATH}/data/media/dogs' mkdir -p '${DS_PATH}/data/media/dogs'
mkdir -p '${DS_PATH}/data/media/diary' mkdir -p '${DS_PATH}/data/media/diary'
mkdir -p '${DS_PATH}/data/media/poison' mkdir -p '${DS_PATH}/data/media/poison'
echo ' Verzeichnisstruktur:'
find '${DS_PATH}/data' -type d | sed 's/^/ /'
" "
ok "Verzeichnisse angelegt" ok "Verzeichnisse angelegt"
# ---------------------------------------------------------- # ----------------------------------------------------------
# 2. Repo klonen oder aktualisieren # 2. Dateien per rsync übertragen (kein git auf DS nötig)
# ---------------------------------------------------------- # ----------------------------------------------------------
echo "" echo ""
echo "→ Repository..." echo "→ Dateien übertragen (rsync)..."
ssh "$DS_HOST" " rsync -az --delete \
if [ -d '${DS_PATH}/.git' ]; then --exclude='.git' \
echo ' Existiert bereits — aktualisiere...' --exclude='data/' \
cd '${DS_PATH}' && git pull --exclude='backend/venv/' \
else --exclude='backend/__pycache__/' \
echo ' Klone von ${REPO_URL}...' --exclude='backend/*.pyc' \
git clone '${REPO_URL}' '${DS_PATH}' --exclude='.env' \
fi --exclude='*.db' \
" --exclude='.DS_Store' \
ok "Repository bereit" "${ROOT}/" "${DS_HOST}:${DS_PATH}/"
ok "Dateien übertragen"
# ---------------------------------------------------------- # ----------------------------------------------------------
# 3. .env anlegen # 3. .env anlegen
@ -94,46 +81,43 @@ ok "Repository bereit"
echo "" echo ""
echo "→ Konfiguration (.env)..." echo "→ Konfiguration (.env)..."
ssh "$DS_HOST" " ENV_EXISTS=$(ssh "$DS_HOST" "[ -f '${DS_PATH}/.env' ] && echo yes || echo no")
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
"
# Prüfen ob JWT_SECRET noch der Default ist if [ "$ENV_EXISTS" = "yes" ]; then
JWT_CHECK=$(ssh "$DS_HOST" "grep 'JWT_SECRET' '${DS_PATH}/.env' | grep -c 'bitte-aendern'" 2>/dev/null || true) ok ".env existiert bereits"
if [ "$JWT_CHECK" -gt "0" ]; then else
warn ".env muss noch angepasst werden!" 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 ""
echo " Mindestens setzen:" warn "JWT_SECRET ist noch nicht gesetzt!"
echo "" echo ""
echo " ssh ${DS_HOST}" echo " ┌──────────────────────────────────────────────┐"
echo " nano ${DS_PATH}/.env" echo " │ Mindestens setzen: │"
echo "" echo " │ JWT_SECRET=<langer-zufaelliger-string> │"
echo " ┌─────────────────────────────────────────────────────┐" echo " │ KI_MODE=local │"
echo " │ JWT_SECRET=<langer-zufaelliger-string> │" echo " └──────────────────────────────────────────────┘"
echo " │ KI_MODE=local │"
echo " │ KI_LOCAL_URL=http://10.47.11.10:1234/v1 │"
echo " └─────────────────────────────────────────────────────┘"
echo "" echo ""
read -r -p " .env jetzt bearbeiten? [J/n] " REPLY read -r -p " .env jetzt bearbeiten? [J/n] " REPLY
if [[ "${REPLY}" =~ ^[Jj]$ ]] || [[ -z "${REPLY}" ]]; then if [[ "${REPLY}" =~ ^[Jj]$|^$ ]]; then
ssh -t "$DS_HOST" "nano '${DS_PATH}/.env'" ssh -t "$DS_HOST" "vi '${DS_PATH}/.env'"
else else
warn "Nicht vergessen: .env vor dem nächsten Start anpassen!" warn "Nicht vergessen: .env vor dem Start anpassen!"
fi fi
else else
ok ".env konfiguriert" ok ".env konfiguriert"
fi fi
# ---------------------------------------------------------- # ----------------------------------------------------------
# 4. Docker-Image bauen und starten # 4. Docker bauen und starten
# ---------------------------------------------------------- # ----------------------------------------------------------
echo "" echo ""
echo "→ Docker build (kann 2-3 Minuten dauern)..." echo "→ Docker build (dauert 2-3 Minuten)..."
ssh "$DS_HOST" " ssh "$DS_HOST" "
cd '${DS_PATH}' && cd '${DS_PATH}' &&
@ -147,33 +131,30 @@ ok "Container gestartet"
# ---------------------------------------------------------- # ----------------------------------------------------------
echo "" echo ""
echo "→ Warte auf App-Start..." 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 if echo "$STATUS" | grep -q "Up"; then
ok "Container läuft: ${STATUS}" ok "Container läuft ${STATUS}"
else else
err "Container-Status: ${STATUS}" warn "Container-Status: '${STATUS}' — Logs prüfen: make logs"
echo " → Logs prüfen: make logs"
fi fi
# ---------------------------------------------------------- # ----------------------------------------------------------
# 6. Zusammenfassung # 6. Fertig
# ---------------------------------------------------------- # ----------------------------------------------------------
echo "" echo ""
echo "==========================================" echo "=================================="
echo ""
ok "Setup abgeschlossen!" ok "Setup abgeschlossen!"
echo "" echo ""
echo " Nächste Schritte:" echo " Nächste Schritte:"
echo "" echo ""
echo " 1. NPM-Eintrag anlegen:" echo " NPM-Eintrag anlegen:"
echo " Host: banyaro.app" echo " Host: banyaro.app"
echo " Ziel: http://10.47.11.10:3010" echo " Ziel: http://10.47.11.10:3010"
echo "" echo ""
echo " 2. Logs prüfen:" echo " Logs: make logs"
echo " make logs" echo " App: https://banyaro.app"
echo ""
echo " 3. App aufrufen:"
echo " https://banyaro.app"
echo "" echo ""