admin/scripts/deploy-on-vps.sh
alisaza 45db367588
Some checks failed
Deploy admin to VPS / Rsync and deploy admin (push) Failing after 10s
ci: deploy admin by building on the VPS
act_runner job images have no Docker daemon, so rsync sources and build
with scripts/deploy-on-vps.sh on the target host instead of GHCR/buildx.
2026-09-13 15:42:58 +03:30

99 lines
3.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Build and run admin on the VPS (idempotent).
# Expects app sources in APP_DIR (CI rsync) and a filled APP_DIR/.env.
set -euo pipefail
APP_DIR="${APP_DIR:-/opt/ghabilee-admin}"
SRC_DIR="${SRC_DIR:-$APP_DIR/src}"
IMAGE_TAG="${IMAGE_TAG:-ghabilee-admin:local}"
cd "$APP_DIR"
if [ ! -f "$APP_DIR/.env" ]; then
echo "Missing $APP_DIR/.env — copy from .env.example and fill production values." >&2
exit 2
fi
if [ ! -f "$SRC_DIR/Dockerfile" ]; then
echo "Missing $SRC_DIR/Dockerfile — rsync the repo before deploy." >&2
exit 2
fi
install -m 0644 "$SRC_DIR/deploy/docker-compose.production.yml" "$APP_DIR/docker-compose.yml"
if [ -f "$SRC_DIR/deploy/nginx/backoffice.conf" ]; then
install -m 0644 "$SRC_DIR/deploy/nginx/backoffice.conf" /etc/nginx/sites-available/backoffice
ln -sfn /etc/nginx/sites-available/backoffice /etc/nginx/sites-enabled/backoffice
nginx -t
systemctl reload nginx
fi
# shellcheck disable=SC1091
set -a
# shellcheck disable=SC1090
source "$APP_DIR/.env"
set +a
env_or_empty() {
local key="$1"
printf '%s' "${!key-}"
}
sanitize_api_proxy_target() {
local target
target="$(env_or_empty API_PROXY_TARGET)"
case "$target" in
*127.0.0.1*|*localhost*|*'::1'*)
echo "Warning: refusing loopback API_PROXY_TARGET for production image build" >&2
printf ''
;;
*)
printf '%s' "$target"
;;
esac
}
BUILD_ARGS=(
--build-arg "NEXT_PUBLIC_API_URL=$(env_or_empty NEXT_PUBLIC_API_URL)"
--build-arg "NEXT_PUBLIC_FILE_SERVER_URL=$(env_or_empty NEXT_PUBLIC_FILE_SERVER_URL)"
--build-arg "MAP_API_KEY=$(env_or_empty MAP_API_KEY)"
--build-arg "NEXT_PUBLIC_MAP_API_KEY=$(env_or_empty NEXT_PUBLIC_MAP_API_KEY)"
--build-arg "NEXT_PUBLIC_VAPID_PUBLIC_KEY=$(env_or_empty NEXT_PUBLIC_VAPID_PUBLIC_KEY)"
--build-arg "NEXT_PUBLIC_BASE_PATH=$(env_or_empty NEXT_PUBLIC_BASE_PATH)"
--build-arg "NEXT_PUBLIC_SITE_URL=$(env_or_empty NEXT_PUBLIC_SITE_URL)"
--build-arg "NEXT_PUBLIC_OBSERVABILITY_ENDPOINT=$(env_or_empty NEXT_PUBLIC_OBSERVABILITY_ENDPOINT)"
--build-arg "NEXT_PUBLIC_SENTRY_DSN=$(env_or_empty NEXT_PUBLIC_SENTRY_DSN)"
--build-arg "NEXT_PUBLIC_SENTRY_ENVIRONMENT=$(env_or_empty NEXT_PUBLIC_SENTRY_ENVIRONMENT)"
--build-arg "NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE=$(env_or_empty NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE)"
--build-arg "NEXT_PUBLIC_ARCAPTCHA_SITE_KEY=$(env_or_empty NEXT_PUBLIC_ARCAPTCHA_SITE_KEY)"
--build-arg "SENTRY_AUTH_TOKEN=$(env_or_empty SENTRY_AUTH_TOKEN)"
--build-arg "SENTRY_ORG=$(env_or_empty SENTRY_ORG)"
--build-arg "SENTRY_PROJECT=$(env_or_empty SENTRY_PROJECT)"
--build-arg "API_PROXY_TARGET=$(sanitize_api_proxy_target)"
)
echo "Building ${IMAGE_TAG} on VPS (build arguments redacted)"
docker build \
--platform linux/amd64 \
-t "$IMAGE_TAG" \
"${BUILD_ARGS[@]}" \
"$SRC_DIR"
ADMIN_IMAGE="$IMAGE_TAG" docker compose -f "$APP_DIR/docker-compose.yml" up -d --no-deps ghabilee-admin
for attempt in $(seq 1 36); do
health="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' ghabilee-admin 2>/dev/null || echo missing)"
echo "Admin health ${attempt}/36: ${health}"
if [ "$health" = "healthy" ]; then
docker image prune -af >/dev/null 2>&1 || true
echo "Deploy OK"
exit 0
fi
case "$health" in
unhealthy|exited|dead|missing) exit 1 ;;
esac
sleep 5
done
echo "Timed out waiting for healthy admin container" >&2
exit 1