Environment Variables
Every environment variable across the gateway, detection engine, and dashboard, with cross-service connection notes.
This page covers all environment variables across all three PromptShield services.
Shared secrets
These values must be identical on both sides of a connection.
| Secret | Set on (service A) | Must match (service B) |
|---|---|---|
| Engine API key | PROMPTSHIELD_API_KEY (engine) | ENGINE_API_KEY (dashboard) and PROMPTSHIELD_ENGINE_API_KEY (gateway) |
| Gateway admin token | PROMPTSHIELD_ADMIN_TOKEN (gateway) | GATEWAY_ADMIN_TOKEN (dashboard) |
| Audit ingest secret | AUDIT_INGEST_SECRET (dashboard) | AUDIT_INGEST_SECRET (gateway direct push) |
The engine API key has three different variable names — one per service — because each service owns its own namespace. They must all carry the same value.
Gateway
Core
| Variable | Default | Description |
|---|---|---|
PROMPTSHIELD_PORT | 8080 | Port the gateway listens on |
PROMPTSHIELD_PROVIDER | gemini | Upstream provider: gemini | openai | anthropic | openai-compatible | selfhosted |
PROMPTSHIELD_PROVIDERS | — | Comma-separated list for multi-provider routing, e.g. anthropic,openai,gemini. First entry is the fallback. |
PROMPTSHIELD_UPSTREAM_URL | provider default | Override the upstream base URL (single-provider mode only) |
PROMPTSHIELD_CHAT_ROUTE | /v1/chat/completions | Inbound route path |
PROMPTSHIELD_POLICY_PATH | config/policy.yaml | Path to the policy YAML file |
PROMPTSHIELD_ALLOW_DEFAULT_POLICY | false | Allow startup with a default allow-all policy when the policy file is missing. Unsafe in production. |
Detection engine
| Variable | Default | Description |
|---|---|---|
PROMPTSHIELD_ENGINE_URL | none | Detection engine URL (e.g. http://localhost:4321). none = gateway mode, no scanning. |
PROMPTSHIELD_ENGINE_API_KEY | — | Bearer token sent to the engine. Must match PROMPTSHIELD_API_KEY in the engine. Required when PROMPTSHIELD_ALLOW_UNAUTH=false on the engine (the default). |
API keys
| Variable | Description |
|---|---|
PROMPTSHIELD_UPSTREAM_API_KEY | Global key fallback (single-provider mode) |
GEMINI_API_KEY | Gemini API key |
OPENAI_API_KEY | OpenAI API key |
ANTHROPIC_API_KEY | Anthropic API key |
SELFHOSTED_API_KEY | Optional key for self-hosted endpoints |
Multiple keys are supported via comma-separated values — the gateway rotates through them in round-robin order.
Model selection
No default model. Set one via env var or pass model in every request.
| Variable | Description |
|---|---|
PROMPTSHIELD_MODEL | Global override — takes priority over all per-provider model vars |
PROMPTSHIELD_GEMINI_MODEL | Model for gemini |
PROMPTSHIELD_OPENAI_MODEL | Model for openai |
PROMPTSHIELD_ANTHROPIC_MODEL | Model for anthropic |
PROMPTSHIELD_SELFHOSTED_MODEL | Model for selfhosted |
PROMPTSHIELD_OPENAI_COMPATIBLE_MODEL | Model for openai-compatible |
Multi-provider routing
| Variable | Description |
|---|---|
PROMPTSHIELD_MODEL_ROUTES | Custom model-to-provider routing, e.g. llama3=selfhosted,mistral=openai-compatible |
PROMPTSHIELD_GEMINI_UPSTREAM_URL | Override Gemini base URL |
PROMPTSHIELD_OPENAI_UPSTREAM_URL | Override OpenAI base URL |
PROMPTSHIELD_ANTHROPIC_UPSTREAM_URL | Override Anthropic base URL |
PROMPTSHIELD_SELFHOSTED_UPSTREAM_URL | Self-hosted endpoint URL |
PROMPTSHIELD_OPENAI_COMPATIBLE_UPSTREAM_URL | OpenAI-compatible endpoint URL |
Admin API
| Variable | Default | Description |
|---|---|---|
PROMPTSHIELD_ADMIN_TOKEN | — | Authenticates /admin/config and /admin/policy requests. Must match GATEWAY_ADMIN_TOKEN in the dashboard. Use a strong random value in production. |
Audit log (standalone mode)
| Variable | Default | Description |
|---|---|---|
PROMPTSHIELD_AUDIT_URL | — | Dashboard server URL for direct audit push, e.g. http://localhost:3000. Leave unset when using docker-compose (log-fwd handles audit forwarding). |
AUDIT_INGEST_SECRET | — | Shared secret for the audit ingest endpoint. Required when PROMPTSHIELD_AUDIT_URL is set. Must match AUDIT_INGEST_SECRET in the dashboard. |
Security and metrics
| Variable | Default | Description |
|---|---|---|
PROMPTSHIELD_EXPOSE_METRICS_ON_MAIN_PORT | false | Expose unauthenticated /metrics on the public listener. Unsafe. Prefer PROMPTSHIELD_METRICS_ADDR. |
PROMPTSHIELD_METRICS_ADDR | — | Internal-only bind address for /metrics, e.g. 127.0.0.1:9090 |
PROMPTSHIELD_TRUST_GATEWAY_CIDRS | — | Comma-separated CIDRs of trusted upstream forwarders (e.g. a reverse proxy in front of the gateway) whose X-Real-IP header is honored. Loopback is always trusted. Example: 10.0.0.0/8,192.168.0.0/16. |
TLS
Set both or neither. Setting one without the other is a startup error.
| Variable | Description |
|---|---|
PROMPTSHIELD_TLS_CERT | Path to TLS certificate (PEM) |
PROMPTSHIELD_TLS_KEY | Path to TLS private key (PEM) |
Detection engine
| Variable | Default | Description |
|---|---|---|
PROMPTSHIELD_ENGINE_PORT | 4321 | Port the engine listens on |
PROMPTSHIELD_ENGINE_HOST | 0.0.0.0 | Host the engine binds to |
PROMPTSHIELD_LOG_LEVEL | INFO | Log level: DEBUG | INFO | WARNING | ERROR |
PROMPTSHIELD_API_KEY | — | Bearer token clients must send. Must match ENGINE_API_KEY (dashboard) and PROMPTSHIELD_ENGINE_API_KEY (gateway). Leave empty only when PROMPTSHIELD_ALLOW_UNAUTH=true. |
PROMPTSHIELD_ALLOW_UNAUTH | false | Allow unauthenticated requests. Only for local development. |
Dashboard
Dashboard server (apps/server)
| Variable | Default | Required | Description |
|---|---|---|---|
DATABASE_URL | — | Yes | PostgreSQL connection string |
BETTER_AUTH_SECRET | — | Yes | Auth signing secret (min 32 chars) |
BETTER_AUTH_URL | http://localhost:3000 | Yes | Public URL of the auth server |
CORS_ORIGIN | http://localhost:8000 | Yes | Allowed CORS origin (the web app URL) |
ENGINE_URL | http://localhost:4321 | No | Detection engine base URL |
ENGINE_API_KEY | — | No* | Bearer token for engine requests. *Required when PROMPTSHIELD_ALLOW_UNAUTH=false on the engine (the default). Must match PROMPTSHIELD_API_KEY in the engine. |
GATEWAY_URL | http://localhost:8080 | No | Gateway base URL for health checks and admin calls |
GATEWAY_ADMIN_TOKEN | — | No | Token for gateway admin API calls. Must match PROMPTSHIELD_ADMIN_TOKEN on the gateway. |
GATEWAY_CONFIG_SOURCE | local_env | No | local_env reads from GATEWAY_ENV_PATH; gateway_api calls the gateway admin API |
GATEWAY_CONFIG_ENDPOINT | /admin/config | No | Gateway admin config endpoint path |
POLICY_SOURCE | local_file | No | local_file reads/writes POLICY_FILE_PATH; gateway_api uses the gateway admin API |
GATEWAY_POLICY_ENDPOINT | /admin/policy | No | Gateway admin policy endpoint path |
POLICY_FILE_PATH | ../../config/policy.yaml | No | Path to policy YAML (when POLICY_SOURCE=local_file) |
POLICY_ALLOWED_DIRS | — | No | Comma-separated absolute paths allowed for policy file operations |
GATEWAY_ENV_PATH | ../../config/gateway.env | No | Path to gateway env file (when GATEWAY_CONFIG_SOURCE=local_env) |
AUDIT_INGEST_SECRET | — | Yes | Shared secret validating audit ingest requests from log-fwd or gateway direct push |
CONFIG_ADMIN_EMAILS | — | No | Comma-separated emails allowed to call config-mutating endpoints |
Web app (apps/web)
| Variable | Default | Description |
|---|---|---|
VITE_SERVER_URL | http://localhost:3000 | Dashboard server URL (browser-side). Must be reachable from the user's browser. |
Audit log forwarding (log-fwd sidecar)
| Variable | Default | Description |
|---|---|---|
AUDIT_SERVER_URL | http://localhost:3000 | Dashboard URL the log-fwd sidecar POSTs audit lines to |
AUDIT_INGEST_SECRET | — | Shared secret (must match the dashboard server's AUDIT_INGEST_SECRET) |
GATEWAY_LOG_SOURCE | file | Log source: docker tails container logs, file tails a log file, stdin reads stdin |
GATEWAY_CONTAINER_NAME | promptshield-gateway | Docker container to tail when GATEWAY_LOG_SOURCE=docker |
GATEWAY_LOG_FILE | ../../gateway-logs/promptshield.log | Log file to tail when GATEWAY_LOG_SOURCE=file |
Docker Compose injected variables
When running with docker-compose, the following variables are set automatically and do not need to be in .env.local:
| Variable | Injected value | Notes |
|---|---|---|
DATABASE_URL | Built from POSTGRES_PASSWORD | Injected into the server service |
BETTER_AUTH_URL | http://localhost:3000 | Injected into the server service |
CORS_ORIGIN | http://localhost:8000 | Injected into the server service |
ENGINE_URL | http://promptshield-engine:4321 | Container-network address |
ENGINE_API_KEY | ${ENGINE_API_KEY:?set in .env.local} | Required. Compose fails fast if missing. Must match engine PROMPTSHIELD_API_KEY. |
GATEWAY_URL | http://promptshield-gateway:8080 | Container-network address |
VITE_SERVER_URL | http://localhost:3000 | Browser-facing; stays as localhost |
AUDIT_SERVER_URL | http://ps-server:3000 | Docker-network dashboard address for the log-fwd sidecar |
GATEWAY_LOG_SOURCE | docker | Docker mode tails the gateway container logs |
GATEWAY_LOG_FILE | /gateway-logs/promptshield.log | File path used when GATEWAY_LOG_SOURCE=file inside the sidecar |
Common misconfigurations
Dashboard cannot reach the detection engine (401)
Symptom: /internal/engine/health returns 401 or "Engine unreachable".
Cause: ENGINE_API_KEY is not set in the dashboard server environment. The engine defaults to PROMPTSHIELD_ALLOW_UNAUTH=false.
Fix: Add ENGINE_API_KEY=<value> to promptshield/.env.local. The value must equal PROMPTSHIELD_API_KEY on the engine. In docker-compose, the value is injected automatically from .env.local.
Gateway cannot reach the detection engine (401)
Symptom: Requests pass through unscanned; gateway logs show engine 401.
Cause: PROMPTSHIELD_ENGINE_API_KEY is missing from the gateway environment.
Fix: Add PROMPTSHIELD_ENGINE_API_KEY=<value> to promptshield-gateway/.env. Value must equal PROMPTSHIELD_API_KEY on the engine.
Dashboard admin calls to gateway fail (403)
Symptom: Policy or config saves from the dashboard return 403.
Cause: GATEWAY_ADMIN_TOKEN (dashboard) does not match PROMPTSHIELD_ADMIN_TOKEN (gateway).
Fix: Ensure both carry the same value. For docker-compose dev, set GATEWAY_ADMIN_TOKEN=dev-gateway-admin-token in promptshield/.env.local and PROMPTSHIELD_ADMIN_TOKEN=dev-gateway-admin-token in promptshield-gateway/.env.local.
Audit logs not appearing in the dashboard
Symptom: Dashboard shows no audit events despite traffic flowing through the gateway.
Cause: The audit path is broken, or AUDIT_INGEST_SECRET doesn't match on both sides.
Docker Compose fix: Confirm the log-fwd service is running (docker compose --profile logs up). Check that AUDIT_INGEST_SECRET in promptshield/.env.local matches the value passed to the log-fwd container (both default to dev-ingest-secret).
Standalone fix: Set PROMPTSHIELD_AUDIT_URL=http://localhost:3000 and AUDIT_INGEST_SECRET=<value> in promptshield-gateway/.env. The secret must match AUDIT_INGEST_SECRET in the dashboard.