doxa-maps/deployment/cloud/entry.sh
Doxa Maps 14a25b6b59 README: Security controls (bundle integrity with the real manifest fields; the v1 backend posture), and PocketBase hooks switched off
Bundle integrity: all 25 bundles carry bundles[].integrity (sha384) and every profiles[].embed.script
already includes integrity + crossorigin=anonymous (checked on main); the section shows the snippet,
what the browser does with it, the CORS header it needs, and check:sri. The container's PocketBase:
locked-by-default collections, the prod dashboard blocked and the dev one admin-only, and hooks OFF,
now true in code: both instances get --hooksDir pointing at a path that never exists, so a pb_hooks/
folder added to the repo can't run. Per-plugin locks and isolated edge functions are stated as not
built.
2026-09-27 21:43:05 +00:00

87 lines
3.8 KiB
Bash
Executable file

#!/bin/bash
# dx-maps cloud dev server, run by the image's /boot.sh from the cloned repo (see Dockerfile).
# 1. install, 2. pull BRANCH every PULL_INTERVAL s (Vite hot-reloads what changed),
# 3. serve: Vite alone, or behind an OIDC sign-in when OIDC_ISSUER is set.
set -u
cd /app/repo
BRANCH="${BRANCH:-main}"; PORT="${PORT:-5173}"
echo "$(date -u +%FT%TZ) START at $(git rev-parse --short HEAD)" | tee -a /tmp/pull.log
bun install --frozen-lockfile || bun install
(
while true; do
sleep "${PULL_INTERVAL:-15}"
OLD=$(git rev-parse HEAD)
if git fetch -q --depth 1 origin "$BRANCH"; then
NEW=$(git rev-parse FETCH_HEAD)
if [ "$OLD" != "$NEW" ]; then
git reset -q --hard FETCH_HEAD
echo "$(date -u +%FT%TZ) PULLED ${OLD:0:8} -> ${NEW:0:8}" >> /tmp/pull.log
fi
fi
done
) &
CONFIG=/app/repo/deployment/cloud/vite.cloud.config.mjs
if [ -z "${OIDC_ISSUER:-}" ]; then
# Open, like a laptop: no sign-in.
export VITE_HOST=0.0.0.0 VITE_PORT="$PORT"
exec bun x vite --config "$CONFIG"
fi
# OIDC gate: oauth2-proxy owns the public port; Vite listens on localhost behind it, so the Plugin
# Studio, every map and the hot-reload websocket are all behind the same sign-in.
: "${OIDC_CLIENT_ID:?}" "${OIDC_CLIENT_SECRET:?}" "${OIDC_REDIRECT_URL:?}"
if [ -z "${OIDC_ALLOWED_GROUPS:-}" ]; then
echo "refusing to start: set OIDC_ALLOWED_GROUPS (comma-separated). With open sign-up, anyone could log in." >&2
exit 1
fi
ALLOW=(); IFS=',' read -ra G <<< "$OIDC_ALLOWED_GROUPS"
for g in "${G[@]}"; do g="${g// /}"; [ -n "$g" ] && ALLOW+=(--allowed-group="$g"); done
# Secrets reach oauth2-proxy through its environment, never its command line.
export OAUTH2_PROXY_CLIENT_SECRET="$OIDC_CLIENT_SECRET"
export OAUTH2_PROXY_COOKIE_SECRET="${OIDC_COOKIE_SECRET:-$(head -c 32 /dev/urandom | base64 | tr -d '=+/' | head -c 32)}"
# Backend: PocketBase DEV (/pb/, signed-in) and PROD (/api-prod/, public API only). Schema = the
# migrations in the repo; data = the /data volume. The superuser comes from env, never printed.
MIG=/app/repo/backend/pocketbase/pb_migrations; mkdir -p "$MIG" /data/pb-dev /data/pb-prod /data/cdn
for inst in dev prod; do
if [ -n "${PB_SUPERUSER_EMAIL:-}" ] && [ -n "${PB_SUPERUSER_PASSWORD:-}" ]; then
pocketbase superuser upsert "$PB_SUPERUSER_EMAIL" "$PB_SUPERUSER_PASSWORD" --dir "/data/pb-$inst" >/dev/null 2>&1 \
&& echo "[pb-$inst] superuser set" || echo "[pb-$inst] superuser upsert failed"
fi
done
# Server-side JS hooks OFF: point --hooksDir at a path that never exists, so a pb_hooks/ folder
# added to the repo can't run code in either instance (v1 has no per-plugin isolation for hooks).
NOHOOKS=/var/empty/pb_hooks_disabled
pocketbase serve --http 127.0.0.1:8090 --dir /data/pb-dev --migrationsDir "$MIG" --hooksDir "$NOHOOKS" &
pocketbase serve --http 127.0.0.1:8091 --dir /data/pb-prod --migrationsDir "$MIG" --hooksDir "$NOHOOKS" &
bun /app/repo/deployment/cloud/admin.mjs &
VITE_HOST=127.0.0.1 VITE_PORT=5174 bun x vite --config "$CONFIG" &
oauth2-proxy \
--provider=oidc \
--oidc-issuer-url="$OIDC_ISSUER" \
--client-id="$OIDC_CLIENT_ID" \
--redirect-url="$OIDC_REDIRECT_URL" \
--code-challenge-method=S256 \
--scope="${OIDC_SCOPE:-openid profile email groups}" \
--oidc-groups-claim="${OIDC_GROUPS_CLAIM:-groups}" \
"${ALLOW[@]}" \
--email-domain='*' \
--provider-display-name="${OIDC_DISPLAY_NAME:-your identity provider}" \
--upstream=http://127.0.0.1:5174/ \
--upstream=http://127.0.0.1:5175/cdn/ \
--upstream=http://127.0.0.1:5175/api-prod/ \
--upstream=http://127.0.0.1:5175/pb/ \
--upstream=http://127.0.0.1:5175/admin/ \
--skip-auth-route='^/cdn/' \
--skip-auth-route='^/api-prod/api/' \
--http-address="0.0.0.0:$PORT" \
--reverse-proxy=true \
--cookie-secure=true \
--cookie-samesite=lax &
wait -n
exit $?