diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml index 2685473..373b998 100644 --- a/.gitea/workflows/deploy.yaml +++ b/.gitea/workflows/deploy.yaml @@ -21,7 +21,6 @@ jobs: DEPLOY_USER: ${{ vars.DEPLOY_USER }} DEPLOY_PATH: ${{ vars.DEPLOY_PATH }} DEPLOY_SERVICE: ${{ vars.DEPLOY_SERVICE }} - DEPLOY_OWNER: ${{ vars.DEPLOY_OWNER }} HEALTH_URL: ${{ vars.HEALTH_URL }} # Repository-Secrets (Settings -> Actions -> Secrets) DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} @@ -70,17 +69,47 @@ jobs: chmod 600 ~/.ssh/id_ed25519 chmod 644 ~/.ssh/known_hosts - - name: Dateien uebertragen + - name: Verbindung pruefen run: | - # --delete raeumt geloeschte Dateien auf dem Server weg. Die - # ausgeschlossenen Pfade sind davon ausgenommen (kein --delete-excluded!): - # Konfiguration, Datenbank und node_modules bleiben unangetastet. + ssh -o BatchMode=yes "$DEPLOY_USER@$DEPLOY_HOST" "DEPLOY_PATH='$DEPLOY_PATH' bash -s" <<'PRUEF' + echo "Angemeldet als $(id -un) auf $(hostname)" + for w in rsync npm node systemctl; do + printf ' %-10s %s\n' "$w" "$(command -v $w || echo FEHLT)" + done + echo "Rechte:" + ls -ld "$DEPLOY_PATH" "$DEPLOY_PATH/backend" "$DEPLOY_PATH/data" 2>&1 | sed 's/^/ /' + echo "Schreibtest im Anwendungsverzeichnis:" + if touch "$DEPLOY_PATH/.schreibtest" 2>/dev/null; then + rm -f "$DEPLOY_PATH/.schreibtest"; echo " ok" + else + echo " FEHLGESCHLAGEN - der Deploy-Benutzer darf dort nicht schreiben" + fi + echo "sudo-Rechte:"; sudo -n -l 2>&1 | tail -5 | sed 's/^/ /' + PRUEF + + - name: Dateien uebertragen und abgleichen + run: | + # rsync laeuft NICHT im Runner-Container: dessen Docker-Host verbietet + # den pipe()-Aufruf ("pipe: Permission denied"). Deshalb geht das + # Paket per tar hinueber und der Abgleich passiert auf dem Zielhost. + tar -czf paket.tgz -C quelle --exclude=.git --exclude=.gitea . + + ssh -o BatchMode=yes "$DEPLOY_USER@$DEPLOY_HOST" \ + 'rm -rf /tmp/timer-app-release && mkdir -p /tmp/timer-app-release && tar -xzf - -C /tmp/timer-app-release' \ + < paket.tgz + + # --delete raeumt geloeschte Dateien weg. Die ausgeschlossenen Pfade + # sind davon ausgenommen (kein --delete-excluded!): Konfiguration, + # Datenbank und node_modules bleiben unangetastet. + ssh -o BatchMode=yes "$DEPLOY_USER@$DEPLOY_HOST" \ + "DEPLOY_PATH='$DEPLOY_PATH' bash -euo pipefail -s" > uebertragen.txt <<'SYNC' rsync -rlpt --delete --out-format='%n' \ - --exclude='.git/' --exclude='.gitea/' \ --exclude='.env' --exclude='.env.*' \ --exclude='data/' --exclude='node_modules/' \ - -e 'ssh -o BatchMode=yes' \ - quelle/ "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/" | tee uebertragen.txt + /tmp/timer-app-release/ "$DEPLOY_PATH/" + rm -rf /tmp/timer-app-release + SYNC + cat uebertragen.txt - name: Abhaengigkeiten, Neustart und Health-Check run: | @@ -97,7 +126,6 @@ jobs: ssh -o BatchMode=yes "$DEPLOY_USER@$DEPLOY_HOST" \ "NPM='$NPM' RESTART='$RESTART' \ DEPLOY_PATH='$DEPLOY_PATH' DEPLOY_SERVICE='$DEPLOY_SERVICE' \ - DEPLOY_OWNER='${DEPLOY_OWNER:-timerapp:timerapp}' \ HEALTH_URL='${HEALTH_URL:-http://127.0.0.1:3003/health}' \ bash -euo pipefail -s" <<'REMOTE' SUDO=""; [ "$(id -u)" -eq 0 ] || SUDO="sudo -n" @@ -108,9 +136,6 @@ jobs: $SUDO npm ci --omit=dev --no-audit --no-fund fi - # Alles unter dem Anwendungsverzeichnis gehoert dem Dienstbenutzer. - $SUDO chown -R "$DEPLOY_OWNER" "$DEPLOY_PATH" - if [ "$RESTART" = nein ]; then echo "--- Keine Backend-Aenderung: Neustart nicht noetig" exit 0 diff --git a/DEPLOY.md b/DEPLOY.md index d6b21e6..033e233 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -487,7 +487,9 @@ Stand selbsttaetig auf den Server aus. Der Workflow liegt in ### Was der Workflow tut -1. Uebertraegt die versionierten Dateien per `rsync` nach `/opt/timer-app`. +1. Uebertraegt die versionierten Dateien als tar-Paket auf den Server und + gleicht sie dort per `rsync` gegen `/opt/timer-app` ab. (Im Runner-Container + laesst der Docker-Host rsync nicht laufen - `pipe: Permission denied`.) **Nicht angefasst** werden `backend/.env`, `data/` und `node_modules/` — sie sind vom Abgleich ausgenommen und ueberleben auch das `--delete`, das geloeschte Dateien auf dem Server aufraeumt. @@ -511,14 +513,17 @@ mkdir -p /home/deploy/.ssh && chmod 700 /home/deploy/.ssh echo '' >> /home/deploy/.ssh/authorized_keys chown -R deploy:deploy /home/deploy/.ssh && chmod 600 /home/deploy/.ssh/authorized_keys -# Schreibrecht auf das Anwendungsverzeichnis +# Der Code gehoert dem Deploy-Benutzer, der Dienst liest ihn nur. chown -R deploy:timerapp /opt/timer-app && chmod -R g+rX /opt/timer-app +# WICHTIG: das Datenverzeichnis gehoert dem Dienst - sonst kann die +# Anwendung ihre Datenbank nicht mehr schreiben. +chown -R timerapp:timerapp /opt/timer-app/data && chmod 750 /opt/timer-app/data + # Genau die drei Befehle ohne Passwort - nicht mehr cat > /etc/sudoers.d/deploy-timer-app <<'EOF' deploy ALL=(root) NOPASSWD: /bin/systemctl restart timer-app, \ - /bin/journalctl -u timer-app *, \ - /bin/chown -R timerapp\:timerapp /opt/timer-app + /bin/journalctl -u timer-app * EOF chmod 440 /etc/sudoers.d/deploy-timer-app visudo -c @@ -532,7 +537,6 @@ Im Repo unter **Settings -> Actions** hinterlegen: | Variable | `DEPLOY_USER` | `deploy` | | Variable | `DEPLOY_PATH` | `/opt/timer-app` | | Variable | `DEPLOY_SERVICE` | `timer-app` | -| Variable | `DEPLOY_OWNER` | `timerapp:timerapp` | | Variable | `HEALTH_URL` | `http://127.0.0.1:3003/health` | | Secret | `DEPLOY_SSH_KEY` | privater Deploy-Schluessel (ganze Datei inkl. BEGIN/END-Zeilen) | | Secret | `DEPLOY_KNOWN_HOSTS` | `ssh-keyscan 192.168.1.5` — Zeile(n) fuer den Zielhost |