Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/start.sh
T

122 lines
6.8 KiB
Bash
Executable File

#!/bin/sh
set -eu
fail() {
echo "[entrypoint] $1" >&2
exit 1
}
if [ "${1:-}" = "migrate" ]; then
[ "$#" -eq 1 ] || fail "migrate accepts no additional arguments"
[ -n "${DIRECT_URL:-}" ] || fail "DIRECT_URL is required for the one-shot migrator"
[ -z "${DATABASE_URL+x}" ] || fail "DATABASE_URL must not be forwarded to the one-shot migrator"
[ -z "${DATABASE_RUNTIME_ROLE+x}" ] || fail "DATABASE_RUNTIME_ROLE belongs to runtime services, not the migrator"
[ -z "${AUTHENTIK_ADMIN_JIT_DATABASE_URL+x}" ] || fail "AUTHENTIK_ADMIN_JIT_DATABASE_URL belongs only to the web runtime"
if env | grep -Eq '^MIGRATOR_[A-Z0-9_]*='; then
fail "MIGRATOR_* aliases must not be forwarded to the one-shot migrator"
fi
if env | grep -Eq '^SEED_[A-Z0-9_]*='; then
fail "seed credentials and flags must not be forwarded to the one-shot migrator"
fi
# Prisma CLI reads DATABASE_URL. Keep that alias inside this short-lived
# process; the long-lived services never receive the migrator credential.
node /myapp/scripts/verify-migrator-role.mjs
node /myapp/scripts/adopt-prisma-baseline.mjs --adopt
export DATABASE_URL="$DIRECT_URL"
echo "[migrator] prisma migrate deploy"
node /myapp/node_modules/prisma/build/index.js migrate deploy --config prisma.config.ts
echo "[migrator] verify current Prisma schema"
node /myapp/scripts/adopt-prisma-baseline.mjs --verify-current-schema
echo "[migrator] sync permission catalog"
node /myapp/packages/db/dist/deploy-permission-catalog-sync.server.js
exit 0
fi
[ "$#" -eq 0 ] || fail "unsupported entrypoint mode"
[ "${RLS_RUNTIME_MODE:-}" = "required" ] || fail "RLS_RUNTIME_MODE=required is mandatory for the web runtime"
[ -n "${DATABASE_URL:-}" ] || fail "DATABASE_URL is required for the web runtime"
[ -z "${DIRECT_URL+x}" ] || fail "DIRECT_URL must not be forwarded to the web runtime"
[ -z "${MIGRATOR_DATABASE_URL+x}" ] || fail "MIGRATOR_DATABASE_URL must not be forwarded to the web runtime"
case "${WEB_RUNTIME_SURFACE:-}" in
core)
[ "${DATABASE_RUNTIME_ROLE:-}" = "hivegrid_app" ] || fail "DATABASE_RUNTIME_ROLE=hivegrid_app is mandatory for the web runtime"
[ -n "${SESSION_SECRET:-}" ] || fail "SESSION_SECRET is required for the core web runtime"
[ -z "${PORTAL_SESSION_SECRET+x}" ] || fail "PORTAL_SESSION_SECRET is forbidden in the core web runtime"
if [ -n "${AUTHENTIK_ADMIN_JIT_DATABASE_URL:-}" ]; then
node -e '
try {
const url = new URL(process.env.AUTHENTIK_ADMIN_JIT_DATABASE_URL);
const validProtocol = url.protocol === "postgres:" || url.protocol === "postgresql:";
if (!validProtocol || url.username !== "hivegrid_authentik_jit" || !url.password || url.pathname === "/") process.exit(1);
} catch {
process.exit(1);
}
' || fail "AUTHENTIK_ADMIN_JIT_DATABASE_URL must use the dedicated hivegrid_authentik_jit login"
fi
;;
admin)
[ "${DATABASE_RUNTIME_ROLE:-}" = "hivegrid_app" ] || fail "DATABASE_RUNTIME_ROLE=hivegrid_app is mandatory for the admin web runtime"
[ -n "${SESSION_SECRET:-}" ] || fail "SESSION_SECRET is required for the admin web runtime"
[ -z "${PORTAL_SESSION_SECRET+x}" ] || fail "PORTAL_SESSION_SECRET is forbidden in the admin web runtime"
[ "${ADMIN_FALLBACK_LOGIN_ENABLED:-false}" = "false" ] || fail "ADMIN_FALLBACK_LOGIN_ENABLED=false is mandatory for the admin web runtime"
for ADMIN_SSO_KEY in AUTHENTIK_ISSUER_URL AUTHENTIK_ADMIN_CLIENT_ID AUTHENTIK_ADMIN_CLIENT_SECRET AUTHENTIK_ADMIN_JIT_DATABASE_URL AUTHENTIK_ADMIN_REDIRECT_URI; do
eval "ADMIN_SSO_VALUE=\${$ADMIN_SSO_KEY:-}"
[ -n "$ADMIN_SSO_VALUE" ] || fail "$ADMIN_SSO_KEY is required for the admin web runtime"
done
node -e '
try {
const issuer = new URL(process.env.AUTHENTIK_ISSUER_URL);
const redirect = new URL(process.env.AUTHENTIK_ADMIN_REDIRECT_URI);
const jit = new URL(process.env.AUTHENTIK_ADMIN_JIT_DATABASE_URL);
const validIssuer = issuer.protocol === "https:" && !issuer.username && !issuer.password && !issuer.search && !issuer.hash;
const validRedirect =
redirect.protocol === "https:" &&
redirect.hostname === process.env.ADMIN_APP_HOST &&
redirect.pathname === "/auth/admin/callback" &&
!redirect.username &&
!redirect.password &&
!redirect.search &&
!redirect.hash;
const validJit =
(jit.protocol === "postgres:" || jit.protocol === "postgresql:") &&
jit.username === "hivegrid_authentik_jit" &&
Boolean(jit.password) &&
jit.pathname !== "/";
if (!validIssuer || !validRedirect || !validJit) process.exit(1);
} catch {
process.exit(1);
}
' || fail "Admin Authentik or JIT configuration is invalid"
;;
portal)
[ "${DATABASE_RUNTIME_ROLE:-}" = "hivegrid_portal" ] || fail "DATABASE_RUNTIME_ROLE=hivegrid_portal is mandatory for the portal web runtime"
[ -n "${PORTAL_SESSION_SECRET:-}" ] || fail "PORTAL_SESSION_SECRET is required for the portal web runtime"
[ -z "${SESSION_SECRET+x}" ] || fail "SESSION_SECRET is forbidden in the portal web runtime"
[ -z "${AUTHENTIK_ADMIN_JIT_DATABASE_URL+x}" ] || fail "AUTHENTIK_ADMIN_JIT_DATABASE_URL is forbidden in the portal web runtime"
PORTAL_ENV_KEYS="$(env | sed 's/=.*//')"
if printf '%s\n' "$PORTAL_ENV_KEYS" | grep -Eq '^(SESSION_SECRET|ADMIN_SESSION_SECRET|CORE_SESSION_SECRET|COOLIFY|AUTHENTIK_[A-Z0-9_]*|(OAUTH|GOOGLE|MICROSOFT|APPLE)(_[A-Z0-9_]*)?|[A-Z0-9_]*_OAUTH(_[A-Z0-9_]*)?|(BILLING|LAGO|MOLLIE|STRIPE)(_[A-Z0-9_]*)?|(SSH|TRAEFIK|INGRESS|CLOUDFLARE)(_[A-Z0-9_]*)?|PORTAL_SERVER_[A-Z0-9_]*|([A-Z0-9_]*_)?DOMAIN_CONTROLLER(_[A-Z0-9_]*)?)$' ||
printf '%s\n' "$PORTAL_ENV_KEYS" | grep '^COOLIFY_' | grep -Evq '^(COOLIFY_BRANCH|COOLIFY_CONTAINER_NAME|COOLIFY_FQDN|COOLIFY_RESOURCE_UUID|COOLIFY_URL)$'; then
fail "forbidden core session, OAuth, billing, ingress, or domain-controller credential in the portal web runtime"
fi
unset PORTAL_ENV_KEYS
;;
*)
fail "WEB_RUNTIME_SURFACE must be explicitly set to core, admin, or portal"
;;
esac
[ -z "${HIVEGRID_RUNTIME_SURFACE+x}" ] || [ "$HIVEGRID_RUNTIME_SURFACE" = "$WEB_RUNTIME_SURFACE" ] || fail "HIVEGRID_RUNTIME_SURFACE must match WEB_RUNTIME_SURFACE"
export HIVEGRID_RUNTIME_SURFACE="$WEB_RUNTIME_SURFACE"
if env | grep -Eq '^MIGRATOR_[A-Z0-9_]*='; then
fail "MIGRATOR_* credentials must not be forwarded to the web runtime"
fi
[ -z "${MIGRATE_ON_BOOT+x}" ] || fail "MIGRATE_ON_BOOT is forbidden; use the one-shot migrator"
[ -z "${SEED_ON_BOOT+x}" ] || fail "SEED_ON_BOOT is forbidden; use the one-shot migrator"
[ -z "${SEED_ONCE+x}" ] || fail "SEED_ONCE is forbidden in the web runtime"
if env | grep -Eq '^SEED_[A-Z0-9_]*='; then
fail "seed credentials and flags must not be forwarded to the web runtime"
fi
exec node build/server-runtime/server.js