Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ DEPLOYMENT_MODE="local"
# Optional build-time release identifier. Use the same value for every replica
# in one rollout; when omitted, each build generates a unique identifier.
NEXT_DEPLOYMENT_ID=""
# Optional build-time override of the Next.js output mode ("standalone" or
# "export"). Unset defaults to the standard output on Vercel (its build
# adapter cannot consume standalone output) and "standalone" elsewhere.
NEXT_OUTPUT_MODE=""
# Auto-injected by Vercel during its builds; do not set manually. It switches
# the Next.js output mode away from standalone because Vercel's build adapter
# cannot consume standalone output.
VERCEL=""
ALLOW_INSECURE_LOCAL_PRODUCTION="false"
# Retained to opt deployment-gated media/image proxy surfaces into HTTP.
ALLOW_LOCAL_NETWORK_PROXY=""
Expand Down
15 changes: 8 additions & 7 deletions docs/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,14 @@ corepack pnpm byok:generate

## Deployment safety

| Variable | Purpose |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DEPLOYMENT_MODE` | Selects local or hosted deployment safeguards and shared-store expectations. It does not block user-configured HTTP or private-network targets. |
| `NEXT_DEPLOYMENT_ID` | Optional build-time release ID shared by every replica in one rollout; drives Next.js version-skew protection and PWA cache rotation. |
| `ALLOW_INSECURE_LOCAL_PRODUCTION` | Explicitly allows production `local` mode without `ACCESS_PASSWORD`. Use only for private deployments that are not exposed to the internet. |
| `ALLOW_LOCAL_NETWORK_PROXY` | Allows HTTP on deployment-gated media/image proxy surfaces. Private addresses themselves are no longer blocked; provider, search, RAG, plugin, and MCP policies do not depend on this flag. |
| `TRUST_PROXY_HEADERS` | Trust forwarded proxy headers only when the hosting platform strips spoofed values. |
| Variable | Purpose |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DEPLOYMENT_MODE` | Selects local or hosted deployment safeguards and shared-store expectations. It does not block user-configured HTTP or private-network targets. |
| `NEXT_DEPLOYMENT_ID` | Optional build-time release ID shared by every replica in one rollout; drives Next.js version-skew protection and PWA cache rotation. |
| `NEXT_OUTPUT_MODE` | Optional build-time override of the Next.js output mode (`standalone` or `export`). Unset defaults to the standard output on Vercel, whose build adapter cannot consume standalone builds, and `standalone` for Docker and self-hosted builds. |
| `ALLOW_INSECURE_LOCAL_PRODUCTION` | Explicitly allows production `local` mode without `ACCESS_PASSWORD`. Use only for private deployments that are not exposed to the internet. |
| `ALLOW_LOCAL_NETWORK_PROXY` | Allows HTTP on deployment-gated media/image proxy surfaces. Private addresses themselves are no longer blocked; provider, search, RAG, plugin, and MCP policies do not depend on this flag. |
| `TRUST_PROXY_HEADERS` | Trust forwarded proxy headers only when the hosting platform strips spoofed values. |

`TRUST_PROXY_HEADERS` affects request identity used by deployment diagnostics
and rate limiting. Leave it `false` unless Neo Chat is behind a trusted proxy
Expand Down
15 changes: 14 additions & 1 deletion next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,27 @@ function getDeploymentId(phase: string): string {
return resolveDeploymentId(process.env, fallbackDeploymentId);
}

function resolveOutputMode(): NextConfig["output"] {
// Vercel's build adapter expects .next/next-server.js.nft.json, which
// standalone builds do not emit; Vercel packages functions itself, so it
// keeps the default output while Docker and self-hosted builds use
// standalone. NEXT_OUTPUT_MODE overrides the platform default explicitly.
const override = process.env.NEXT_OUTPUT_MODE?.trim();
if (override && override !== "standalone" && override !== "export") {
console.warn(`Ignoring unsupported NEXT_OUTPUT_MODE: "${override}"`);
}
if (override === "standalone" || override === "export") return override;
return process.env.VERCEL ? undefined : "standalone";
}

function createNextConfig(phase: string): NextConfig {
const deploymentId = getDeploymentId(phase);
const isE2EServer =
phase === PHASE_DEVELOPMENT_SERVER && process.env.NEO_CHAT_E2E === "1";

return {
/* config options here */
output: "standalone",
output: resolveOutputMode(),
...(isE2EServer && {
distDir: ".next-e2e",
typescript: { tsconfigPath: "tsconfig.e2e.json" },
Expand Down
2 changes: 2 additions & 0 deletions src/__tests__/envExample.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const REQUIRED_ENV_KEYS = [
"BYOK_ALLOW_EPHEMERAL_KEY",
"DEPLOYMENT_MODE",
"NEXT_DEPLOYMENT_ID",
"NEXT_OUTPUT_MODE",
"VERCEL",
"ALLOW_INSECURE_LOCAL_PRODUCTION",
"ALLOW_LOCAL_NETWORK_PROXY",
"TRUST_PROXY_HEADERS",
Expand Down