Skip to content

Latest commit

 

History

History
245 lines (195 loc) · 9.11 KB

File metadata and controls

245 lines (195 loc) · 9.11 KB

Deployment Hardening

Neo Chat is local-first by default. A production self-hosted deployment should decide whether it is running as a private local app or as a hosted internet app, then configure secrets and shared state accordingly.

Local or Private Self-hosted

Use DEPLOYMENT_MODE=local for Docker, LAN, or private deployments that need local provider, RAG, SearXNG, or proxy endpoints.

Recommended settings:

DEPLOYMENT_MODE=local
ACCESS_PASSWORD=choose-a-strong-password
ALLOW_INSECURE_LOCAL_PRODUCTION=false
ALLOW_LOCAL_NETWORK_PROXY=
TRUST_PROXY_HEADERS=false
BYOK_ALLOW_EPHEMERAL_KEY=false
BYOK_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
BYOK_KEY_ID=prod-2026-07

Production local mode now fails closed for /api/* when ACCESS_PASSWORD is empty. Set ALLOW_INSECURE_LOCAL_PRODUCTION=true only for a private deployment that is not exposed to the internet and has another access boundary.

If the deployment has more than one instance, use Upstash for shared request limits, document parse jobs, and server-registered plugins:

RATE_LIMIT_STORE=upstash
DOCUMENT_PARSE_JOB_STORE=upstash
PLUGIN_REGISTRY_STORE=upstash
UPSTASH_REDIS_REST_URL=https://...
UPSTASH_REDIS_REST_TOKEN=...

Hosted Internet Deployment

Use DEPLOYMENT_MODE=hosted when the app is reachable from the public internet. Hosted mode tightens outbound URL policy and CSP. It also requires shared short-lived state so rate limits, document parse jobs, and server-registered plugins behave consistently across instances.

Required hosted settings:

DEPLOYMENT_MODE=hosted
ALLOW_LOCAL_NETWORK_PROXY=false
TRUST_PROXY_HEADERS=false
RATE_LIMIT_STORE=upstash
DOCUMENT_PARSE_JOB_STORE=upstash
PLUGIN_REGISTRY_STORE=upstash
UPSTASH_REDIS_REST_URL=https://...
UPSTASH_REDIS_REST_TOKEN=...
BYOK_ALLOW_EPHEMERAL_KEY=false
BYOK_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
BYOK_KEY_ID=prod-2026-07

Enable TRUST_PROXY_HEADERS=true only when the platform or reverse proxy strips spoofed forwarded headers before requests reach Neo Chat. These headers affect rate-limit identity and public request metadata; trusting user-supplied values can weaken hosted protections.

Vercel Environment Variables

Vercel runs the standard Next.js build output, not the Cloudflare Workers OpenNext output. Import the repository with the Next.js framework preset and use the default output directory.

Recommended project settings:

Install Command: default, or corepack pnpm install --frozen-lockfile
Build Command: pnpm build
Output Directory: default

For public Vercel deployments, use hosted mode and shared stores:

DEPLOYMENT_MODE=hosted
ALLOW_LOCAL_NETWORK_PROXY=false
RATE_LIMIT_STORE=upstash
DOCUMENT_PARSE_JOB_STORE=upstash
PLUGIN_REGISTRY_STORE=upstash
UPSTASH_REDIS_REST_URL=https://...
UPSTASH_REDIS_REST_TOKEN=...
BYOK_ALLOW_EPHEMERAL_KEY=false
BYOK_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
BYOK_KEY_ID=prod-2026-07
NEXT_PUBLIC_SITE_URL=https://your-domain.com

Set these values in the Vercel project under the Production, Preview, or Development environments that need them. Vercel environment variables are available to the build step and to Next.js function execution for that deployment, so NEXT_PUBLIC_SITE_URL should be configured anywhere metadata, Open Graph image URLs, or generated public links must use the deployed domain.

Keep deployment passwords, provider keys, BYOK key material, Upstash credentials, and third-party service tokens out of source control. Configure them as Vercel environment variables instead.

Cloudflare Workers Environment Variables

OpenNext and Cloudflare Workers have separate build-time and runtime configuration surfaces.

For Cloudflare Workers Builds, set:

Build command: pnpm build:worker
Deploy command: pnpm exec opennextjs-cloudflare deploy -- --keep-vars

OpenNext Cloudflare compatibility requires this repository to keep its Edge Middleware entry point at src/middleware.ts. Do not rename it to src/proxy.ts: the proxy entry point is emitted as Node.js middleware by the current Next.js toolchain, which OpenNext Cloudflare does not support. The middleware must also keep /api/access/verify and /api/request-proof/session available as bootstrap routes.

Use Node 22 with Corepack-enabled pnpm@10.30.3 for local, CI, Docker, and Cloudflare build parity. Before deploying Worker changes, run:

pnpm build:worker
pnpm worker:size

pnpm worker:size runs wrangler deploy --dry-run, reads the gzip value from Wrangler's Total Upload report, and checks it against the default 3 MiB budget. The command fails if Wrangler fails, the report cannot be parsed, or the gzip value exceeds the budget. Override with WORKER_GZIP_BUDGET_BYTES only for an intentional budget change.

--keep-vars prevents deployments from replacing runtime variables configured in the Cloudflare dashboard with only the values committed in wrangler.jsonc. The default observability sampling in wrangler.jsonc is production-oriented; temporarily raise sampling while debugging noisy incidents, then lower it again.

Set runtime variables in the Worker dashboard under Settings -> Variables and Secrets. Use plain variables only for non-sensitive deployment defaults:

DEPLOYMENT_MODE=hosted
RATE_LIMIT_STORE=upstash
DOCUMENT_PARSE_JOB_STORE=upstash
PLUGIN_REGISTRY_STORE=upstash
BYOK_ALLOW_EPHEMERAL_KEY=false
NEXT_PUBLIC_SITE_URL=https://your-domain.com

Use secrets for sensitive values:

BYOK_PRIVATE_KEY_PEM
BYOK_KEY_ID
UPSTASH_REDIS_REST_URL
UPSTASH_REDIS_REST_TOKEN
ACCESS_PASSWORD
DEFAULT_PROVIDER_API_KEY
DEFAULT_SEARCH_API_KEY
DEFAULT_RAG_TOKEN
DEFAULT_LLAMA_PARSE_API_KEY
DEFAULT_ELEVENLABS_API_KEY
DEFAULT_MIMO_API_KEY

Workers Builds also has Settings -> Builds -> Variables and Secrets. Values there are available only during the build step. Add NEXT_PUBLIC_* values and any non-public values required by static generation there as well as in runtime variables when the app also needs them after deployment.

Keep personal API keys and deployment secrets out of source control. Deployment-level defaults such as DEFAULT_PROVIDER_API_KEY are shared by every user of that Worker instance. Leave them unset when users should provide their own provider keys in local browser settings.

Hosted mode also disables legacy plugin execution payloads where the browser submits a complete plugin manifest and function definition to the server. Plugin calls must resolve through server-registered plugin ids and function names. Once a plugin is enabled for a chat, runtime tool calls execute automatically without a per-call confirmation modal. See Reliability and Safety Model for tool execution boundaries, context budgeting, and recovery behavior.

Remote MCP servers use the same server-registered plugin path and outbound URL policy. Neo Chat v1 supports only remote streamable-http MCP over HTTPS; hosted deployments block localhost and private-network MCP targets unless ALLOW_LOCAL_NETWORK_PROXY=true is explicitly enabled. Hosted or multi-instance deployments should configure PLUGIN_REGISTRY_STORE=upstash so installed MCP tools resolve consistently across instances.

Deployment Health

Settings includes a deployment health panel backed by /api/health. The route returns non-secret status for BYOK, access password, hosted mode, shared stores, default model, search, RAG/document processing, and voice readiness. Use it after changing environment variables or moving from single-instance local mode to hosted or multi-instance deployments.

/api/health intentionally reports availability and policy state only. It must not expose access passwords, BYOK key material, provider keys, Upstash tokens, or internal Redis URLs. It is a configuration readiness check, not a live canary or external uptime monitor.

Runtime Recovery

Knowledge-base OPFS files and vector records should be treated as durable user data. Use the built-in reconciliation flow after storage errors, interrupted uploads, or manual OPFS changes. It detects missing local files, cleans orphan files, and leaves recoverable metadata instead of silently dropping entries.

Search, RAG, attachment, and tool context should share the central context budget helper so hosted and local deployments behave consistently across model providers with different context limits.

Document parsing uses asynchronous jobs for providers such as Mineru and LlamaParse. In hosted or multi-instance deployments, keep DOCUMENT_PARSE_JOB_STORE=upstash; in-memory job state is only suitable for a single local process. Polling and cancellation require the job secret returned when the job is created.

Access Password Boundary

ACCESS_PASSWORD is a deployment gate for a single private deployment. It is not a user account system. Before offering Neo Chat as a public multi-user SaaS, add account authentication, tenant isolation, server-side secret storage, quotas, audit logs, abuse controls, and provider spend limits.

Dependency Gate

Production changes should pass:

pnpm lint
pnpm typecheck
pnpm test
pnpm build
pnpm audit --audit-level low