#!/usr/bin/env bash set -Eeuo pipefail # Usage: # ./deploy.sh (benoetigt sudo fuer chown; npm/composer als dein User) # sudo ./deploy.sh (empfohlen: SUDO_USER bekommt public/build vor dem Vite-Build) # Optional env vars: # APP_DIR=/web/einkauf (Standard; anpassen wenn die App woanders liegt) # PHP_BIN=/usr/bin/php # COMPOSER_BIN=/usr/bin/composer (optional; sonst PATH oder uebliche Pfade) # NPM_BIN=/usr/bin/npm # RUN_SEED=true # # Rechte: Nur storage, bootstrap/cache und public/build gehen an www-data. # Code + vendor bleiben beim Deploy-User — sonst schlagen npm/vite/composer fehl (EACCES). # Bei sudo ./deploy.sh ist der Build-User SUDO_USER (z. B. stefanz). APP_DIR="${APP_DIR:-/web/einkauf}" PHP_BIN="${PHP_BIN:-/usr/bin/php}" NPM_BIN="${NPM_BIN:-/usr/bin/npm}" RUN_SEED="${RUN_SEED:-false}" if [ -n "${COMPOSER_BIN:-}" ]; then : elif command -v composer >/dev/null 2>&1; then COMPOSER_BIN="$(command -v composer)" elif [ -x /usr/bin/composer ]; then COMPOSER_BIN=/usr/bin/composer elif [ -x /usr/local/bin/composer ]; then COMPOSER_BIN=/usr/local/bin/composer else echo "Fehler: composer nicht gefunden (PATH, /usr/bin/composer, /usr/local/bin/composer)." >&2 echo "Installiere Composer oder setze z. B. COMPOSER_BIN=/pfad/zu/composer" >&2 exit 1 fi cd "${APP_DIR}" if [ "$(id -u)" -eq 0 ] && [ -n "${SUDO_USER:-}" ]; then DEPLOY_OWNER="${SUDO_USER}" else DEPLOY_OWNER="$(id -un)" fi chown_path_for_build() { local p="${1:?}" [ -e "$p" ] || return 0 if [ "$(id -u)" -eq 0 ]; then chown -R "${DEPLOY_OWNER}:${DEPLOY_OWNER}" "$p" elif command -v sudo >/dev/null 2>&1; then sudo chown -R "${DEPLOY_OWNER}:${DEPLOY_OWNER}" "$p" else echo "Warnung: kann ${p} nicht chownen — ggf. sudo nutzen oder manuell: chown -R ${DEPLOY_OWNER} ${p}" >&2 fi } echo "==> Deploy startet in ${APP_DIR}" if [ ! -f "artisan" ]; then echo "Fehler: artisan nicht gefunden in ${APP_DIR}" >&2 exit 1 fi echo "==> Wartungsmodus aktivieren" "${PHP_BIN}" artisan down --refresh=15 --retry=60 --secret="deploy-bypass" || true cleanup() { echo "==> Wartungsmodus deaktivieren" "${PHP_BIN}" artisan up || true } trap cleanup EXIT echo "==> Code aktualisieren" git fetch --all --prune git reset --hard origin/main echo "==> PHP-Abhaengigkeiten installieren" "${COMPOSER_BIN}" install --no-dev --prefer-dist --optimize-autoloader --no-interaction echo "==> Frontend: Schreibrechte (Vite leert public/build)" mkdir -p "${APP_DIR}/public/build" chown_path_for_build "${APP_DIR}/public/build" chown_path_for_build "${APP_DIR}/node_modules" echo "==> Frontend-Abhaengigkeiten installieren" "${NPM_BIN}" ci echo "==> Frontend builden" "${NPM_BIN}" run build echo "==> Datenbank migrieren" "${PHP_BIN}" artisan migrate --force if [ "${RUN_SEED}" = "true" ]; then echo "==> Seeder ausfuehren" "${PHP_BIN}" artisan db:seed --force fi echo "==> Storage-Link sicherstellen" "${PHP_BIN}" artisan storage:link || true echo "==> Caches aufbauen" "${PHP_BIN}" artisan optimize:clear "${PHP_BIN}" artisan config:cache "${PHP_BIN}" artisan route:cache "${PHP_BIN}" artisan view:cache echo "==> Rechte setzen (www-data nur wo noetig)" if [ "$(id -u)" -eq 0 ]; then DO_CHOWN=(chown -R) DO_CHMOD=(chmod -R) DO_FIND=(find) else DO_CHOWN=(sudo chown -R) DO_CHMOD=(sudo chmod -R) DO_FIND=(sudo find) fi "${DO_CHOWN[@]}" www-data:www-data "${APP_DIR}/storage" "${APP_DIR}/bootstrap/cache" "${APP_DIR}/public/build" "${DO_CHMOD[@]}" 775 "${APP_DIR}/storage" "${APP_DIR}/bootstrap/cache" "${DO_FIND[@]}" "${APP_DIR}/public/build" -type d -exec chmod 755 {} + 2>/dev/null || true "${DO_FIND[@]}" "${APP_DIR}/public/build" -type f -exec chmod 644 {} + 2>/dev/null || true echo "==> Deploy erfolgreich"