Files
timemaster/server-update.sh
T
patrickandClaude Sonnet 5.5 7e165d37b6
Security Audit / Python Dependency Audit (push) Canceled after 0s
Security Audit / Node.js Dependency Audit (push) Canceled after 0s
Security Audit / Frontend Build (tsc + vite) (push) Canceled after 0s
feat(deploy): deploy.sh + lokale Host-Konfig, server-update/setup_server übernehmen Unit und sudoers aus dem Repo
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 09:40:35 +01:00

103 lines
4.9 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# =============================================================================
# server-update.sh – AUF dem jeweiligen Server ausführen (nicht lokal!)
#
# Aktualisiert GENAU DIESEN Server eigenständig aus dem Gitea-Repo:
# git pull → alembic upgrade head → service restart → health-check
#
# Jeder Server macht sich selbst – kein Cross-Server-SSH, kein "both".
# 137 und 164 sind komplett entkoppelt.
#
# Frontend: wird NICHT hier gebaut (kein Node auf den Servern, dist ist
# gitignored). Frontend liefert der Dev-Rechner separat per push-frontend.sh.
# Lokal aufrufbar über: ./deploy.sh <dev|prod> [--frontend]
#
# Usage (auf dem Server):
# cd /opt/timemaster && ./server-update.sh
# ./server-update.sh --no-migrate # nur pull + restart
# =============================================================================
set -euo pipefail
REMOTE="/opt/timemaster"
SERVICE="timemaster"
HEALTH_URL="http://localhost:8000/health"
GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'; NC='\033[0m'
log() { echo -e "${GREEN}==>${NC} $*"; }
warn() { echo -e "${YELLOW}[!]${NC} $*"; }
die() { echo -e "${RED}[FEHLER]${NC} $*" >&2; exit 1; }
DO_MIGRATE=true
[[ "${1:-}" == "--no-migrate" ]] && DO_MIGRATE=false
# ── Sicherstellen, dass wir wirklich auf einem Server sind ────────────────────
[[ -d "$REMOTE/backend/venv" ]] || die "venv fehlt ($REMOTE/backend/venv) – falscher Host? Dieses Skript läuft AUF dem Server."
cd "$REMOTE"
git config --global --add safe.directory "$REMOTE" 2>/dev/null || true
# ── 1. Repo aktualisieren ─────────────────────────────────────────────────────
# Guard gegen "laufendes Skript editiert sich selbst": zuerst nur pullen, dann
# die frisch gezogene Version neu starten (Marker verhindert Doppel-Pull).
if [[ -z "${_SU_REEXEC:-}" ]]; then
log "git pull --ff-only origin main"
if ! git pull --ff-only origin main; then
die "git pull fehlgeschlagen. Arbeitsbaum sauber? ('git status' prüfen, ggf. 'git stash')."
fi
log "Jetzt auf: $(git log --oneline -1)"
export _SU_REEXEC=1
exec bash "$REMOTE/server-update.sh" "$@" # frische Version übernimmt ab hier
fi
# ── 2. Migration ──────────────────────────────────────────────────────────────
if $DO_MIGRATE; then
log "alembic upgrade head"
( cd "$REMOTE/backend" && source venv/bin/activate && alembic upgrade head ) \
|| die "Migration fehlgeschlagen – Service wird NICHT neugestartet (Schema evtl. inkonsistent)."
else
warn "Migration übersprungen (--no-migrate)"
fi
# ── 2b. Systemkonfiguration aus dem Repo (idempotent) ─────────────────────────
id timemaster >/dev/null 2>&1 || { log "Systemuser timemaster anlegen"; useradd --system --no-create-home --shell /usr/sbin/nologin timemaster; }
[[ -f backend/.env ]] && { chown root:timemaster backend/.env; chmod 640 backend/.env; }
UNIT_CHANGED=false
if ! cmp -s "$REMOTE/timemaster.service" /etc/systemd/system/timemaster.service; then
log "systemd-Unit aus Repo übernehmen"
install -m 644 "$REMOTE/timemaster.service" /etc/systemd/system/timemaster.service
UNIT_CHANGED=true
fi
if command -v visudo >/dev/null && ! cmp -s "$REMOTE/timemaster.sudoers" /etc/sudoers.d/timemaster 2>/dev/null; then
log "sudo-Regel aus Repo übernehmen"
install -d -m 755 /etc/sudoers.d
install -m 440 "$REMOTE/timemaster.sudoers" /etc/sudoers.d/timemaster.new
visudo -cf /etc/sudoers.d/timemaster.new >/dev/null && mv /etc/sudoers.d/timemaster.new /etc/sudoers.d/timemaster \
|| { rm -f /etc/sudoers.d/timemaster.new; warn "sudoers ungültig – nicht übernommen"; }
elif ! command -v visudo >/dev/null; then
warn "sudo nicht installiert – TLS-Erneuerung aus der App nicht möglich (apt install sudo)"
fi
$UNIT_CHANGED && systemctl daemon-reload
# ── 3. Service neustarten ─────────────────────────────────────────────────────
log "systemctl restart $SERVICE"
systemctl restart "$SERVICE"
sleep 2
state="$(systemctl is-active "$SERVICE" || true)"
[[ "$state" == "active" ]] || { journalctl -u "$SERVICE" -n 30 --no-pager; die "Service nicht aktiv ($state)."; }
log "Service aktiv"
# ── 4. Health-Check (mehrere Versuche – Worker brauchen kurz zum Starten) ─────
health_ok=false
for attempt in 1 2 3 4 5; do
if curl -sf --max-time 10 "$HEALTH_URL" >/dev/null; then
health_ok=true; break
fi
sleep 2
done
if $health_ok; then
log "Health OK ($HEALTH_URL)"
else
warn "Health-Check fehlgeschlagen – Logs prüfen: journalctl -u $SERVICE -n 50"
fi
log "✓ Update abgeschlossen auf $(hostname)"