diff --git a/Dockerfile b/Dockerfile
index c0da1eb..0b09aa3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -44,6 +44,11 @@ ENV NEXT_PUBLIC_AUTHENTIK_ENABLED=$NEXT_PUBLIC_AUTHENTIK_ENABLED
# also needs to be a build arg, not just a runtime env var (unlike STORAGE_ENDPOINT).
ARG STORAGE_PUBLIC_URL
ENV STORAGE_PUBLIC_URL=$STORAGE_PUBLIC_URL
+# lib/storage.ts's getPublicUrl() is called from client components to render photo
+#
tags — a plain (non-NEXT_PUBLIC_) env var is never inlined into the browser
+# bundle, so it must be duplicated under a NEXT_PUBLIC_ name to reach the client.
+ARG NEXT_PUBLIC_STORAGE_PUBLIC_URL
+ENV NEXT_PUBLIC_STORAGE_PUBLIC_URL=$NEXT_PUBLIC_STORAGE_PUBLIC_URL
RUN pnpm --filter web build
# ---- runtime ----
diff --git a/apps/web/lib/storage.ts b/apps/web/lib/storage.ts
index b50a828..e66cf9d 100644
--- a/apps/web/lib/storage.ts
+++ b/apps/web/lib/storage.ts
@@ -4,6 +4,9 @@ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const bucket = process.env["STORAGE_BUCKET"] || "epicure-uploads";
const endpoint = process.env["STORAGE_ENDPOINT"] || "http://localhost:9000";
const publicUrl = process.env["STORAGE_PUBLIC_URL"] || "http://localhost:9000";
+// getPublicUrl() below runs in the browser too — non-NEXT_PUBLIC_ vars are never
+// inlined into the client bundle, so it needs its own NEXT_PUBLIC_ copy of the value.
+const clientPublicUrl = process.env.NEXT_PUBLIC_STORAGE_PUBLIC_URL || "http://localhost:9000";
const credentials = {
accessKeyId: process.env["STORAGE_ACCESS_KEY"] ?? "minioadmin",
@@ -39,5 +42,5 @@ export async function deleteObject(key: string): Promise {
}
export function getPublicUrl(key: string): string {
- return `${publicUrl}/${bucket}/${key}`;
+ return `${clientPublicUrl}/${bucket}/${key}`;
}
diff --git a/compose.prod.yml b/compose.prod.yml
index 0c226a3..c0fadc4 100644
--- a/compose.prod.yml
+++ b/compose.prod.yml
@@ -85,6 +85,7 @@ services:
NEXT_PUBLIC_DISCORD_ENABLED: ${NEXT_PUBLIC_DISCORD_ENABLED}
NEXT_PUBLIC_AUTHENTIK_ENABLED: ${NEXT_PUBLIC_AUTHENTIK_ENABLED}
STORAGE_PUBLIC_URL: ${STORAGE_PUBLIC_URL}
+ NEXT_PUBLIC_STORAGE_PUBLIC_URL: ${STORAGE_PUBLIC_URL}
restart: always
environment:
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}