diff --git a/docker/Dockerfile b/docker/Dockerfile index 5ce4c97..d366ac9 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -17,15 +17,25 @@ WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . -# Only NEXT_PUBLIC_* vars are baked into the client bundle at build time. -# All server-side secrets are injected at runtime via docker-compose env_file. +# NEXT_PUBLIC_* vars are baked into the client bundle at build time. +# All other server-side secrets are injected at runtime via docker-compose +# env_file — except the three below, which withSentryConfig (next.config.ts) +# needs during `npm run build` itself to upload source maps. They never reach +# the final runner stage (discarded with this builder stage), so they don't +# leak into the shipped image's runtime environment. ARG NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY ARG NEXT_PUBLIC_SUPABASE_URL ARG NEXT_PUBLIC_SENTRY_DSN +ARG SENTRY_ORG +ARG SENTRY_PROJECT +ARG SENTRY_AUTH_TOKEN ENV NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=$NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY ENV NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL ENV NEXT_PUBLIC_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN +ENV SENTRY_ORG=$SENTRY_ORG +ENV SENTRY_PROJECT=$SENTRY_PROJECT +ENV SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN ENV NEXT_TELEMETRY_DISABLED=1 RUN npx prisma generate diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index bb184df..b677114 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -12,11 +12,18 @@ services: context: .. dockerfile: docker/Dockerfile args: - # Only public vars needed at build time (baked into client bundle). + # Public vars needed at build time (baked into client bundle). # Docker Compose reads these from docker/.env automatically. NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY} NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL} NEXT_PUBLIC_SENTRY_DSN: ${NEXT_PUBLIC_SENTRY_DSN} + # Sentry/GlitchTip source-map upload also runs during `npm run build` + # (withSentryConfig in next.config.ts), so it needs these as build + # args too — env_file below only reaches the running container, not + # the build stage. Leave unset to keep sourcemap upload disabled. + SENTRY_ORG: ${SENTRY_ORG} + SENTRY_PROJECT: ${SENTRY_PROJECT} + SENTRY_AUTH_TOKEN: ${SENTRY_AUTH_TOKEN} image: pawfeed:latest container_name: pawfeed restart: unless-stopped diff --git a/src/proxy.ts b/src/proxy.ts index afd5c0b..0881733 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -41,6 +41,18 @@ function getSupabaseHostname(): string { return "*.supabase.co"; } +function getGlitchtipHostname(): string { + const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN; + if (dsn) { + try { + return new URL(dsn).hostname; + } catch { + /* fall through */ + } + } + return "glitchtip.pawfeed.org"; +} + export default clerkMiddleware( async (auth, request) => { const { pathname } = request.nextUrl; @@ -82,15 +94,16 @@ export default clerkMiddleware( reportOnly: true, reportTo: "/api/csp-report", directives: { - "img-src": [`https://${getSupabaseHostname()}`, "https://image.mux.com"], + "img-src": [`https://${getSupabaseHostname()}`, "https://image.mux.com", "blob:"], "connect-src": [ `https://${getSupabaseHostname()}`, + `https://${getGlitchtipHostname()}`, "https://stream.mux.com", "https://image.mux.com", "https://litix.io", "https://storage.googleapis.com", ], - "media-src": ["self", "blob:", "https://stream.mux.com"], + "media-src": ["self", "blob:", "https://stream.mux.com", "https://*.edgemv.mux.com"], "font-src": ["self", "data:"], "frame-ancestors": ["none"], "object-src": ["none"],