PromptShield

Environment Variables

Every environment variable across the proxy, 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.

SecretSet on (service A)Must match (service B)
Engine API keyPROMPTSHIELD_API_KEY (engine)ENGINE_API_KEY (dashboard) and PROMPTSHIELD_ENGINE_API_KEY (proxy)
Proxy admin tokenPROXY_ADMIN_TOKEN (proxy)PROXY_ADMIN_TOKEN (dashboard)
Audit ingest secretAUDIT_INGEST_SECRET (dashboard)AUDIT_INGEST_SECRET (proxy 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.


Proxy

Core

VariableDefaultDescription
PROMPTSHIELD_PORT8080Port the proxy listens on
PROMPTSHIELD_PROVIDERgeminiUpstream provider: gemini | openai | anthropic | openai-compatible | selfhosted
PROMPTSHIELD_PROVIDERSComma-separated list for multi-provider routing, e.g. anthropic,openai,gemini. First entry is the fallback.
PROMPTSHIELD_UPSTREAM_URLprovider defaultOverride the upstream base URL (single-provider mode only)
PROMPTSHIELD_CHAT_ROUTE/v1/chat/completionsInbound route path
PROMPTSHIELD_POLICY_PATHconfig/policy.yamlPath to the policy YAML file
PROMPTSHIELD_ALLOW_DEFAULT_POLICYfalseAllow startup with a default allow-all policy when the policy file is missing. Unsafe in production.

Detection engine

VariableDefaultDescription
PROMPTSHIELD_ENGINE_URLnoneDetection engine URL (e.g. http://localhost:4321). none = gateway mode, no scanning.
PROMPTSHIELD_ENGINE_API_KEYBearer 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

VariableDescription
PROMPTSHIELD_UPSTREAM_API_KEYGlobal key fallback (single-provider mode)
GEMINI_API_KEYGemini API key
OPENAI_API_KEYOpenAI API key
ANTHROPIC_API_KEYAnthropic API key
SELFHOSTED_API_KEYOptional key for self-hosted endpoints

Multiple keys are supported via comma-separated values — the proxy rotates through them in round-robin order.

Model selection

No default model. Set one via env var or pass model in every request.

VariableDescription
PROMPTSHIELD_MODELGlobal override — takes priority over all per-provider model vars
PROMPTSHIELD_GEMINI_MODELModel for gemini
PROMPTSHIELD_OPENAI_MODELModel for openai
PROMPTSHIELD_ANTHROPIC_MODELModel for anthropic
PROMPTSHIELD_SELFHOSTED_MODELModel for selfhosted
PROMPTSHIELD_OPENAI_COMPATIBLE_MODELModel for openai-compatible

Multi-provider routing

VariableDescription
PROMPTSHIELD_MODEL_ROUTESCustom model-to-provider routing, e.g. llama3=selfhosted,mistral=openai-compatible
PROMPTSHIELD_GEMINI_UPSTREAM_URLOverride Gemini base URL
PROMPTSHIELD_OPENAI_UPSTREAM_URLOverride OpenAI base URL
PROMPTSHIELD_ANTHROPIC_UPSTREAM_URLOverride Anthropic base URL
PROMPTSHIELD_SELFHOSTED_UPSTREAM_URLSelf-hosted endpoint URL
PROMPTSHIELD_OPENAI_COMPATIBLE_UPSTREAM_URLOpenAI-compatible endpoint URL

Admin API

VariableDefaultDescription
PROXY_ADMIN_TOKENAuthenticates /admin/config and /admin/policy requests. Must match PROXY_ADMIN_TOKEN in the dashboard. Use a strong random value in production.

Audit log (standalone mode)

VariableDefaultDescription
PROMPTSHIELD_AUDIT_URLDashboard server URL for direct audit push, e.g. http://localhost:3000. Leave unset when using docker-compose (log-fwd handles audit forwarding).
AUDIT_INGEST_SECRETShared secret for the audit ingest endpoint. Required when PROMPTSHIELD_AUDIT_URL is set. Must match AUDIT_INGEST_SECRET in the dashboard.

Security and metrics

VariableDefaultDescription
PROMPTSHIELD_EXPOSE_METRICS_ON_MAIN_PORTfalseExpose unauthenticated /metrics on the public listener. Unsafe. Prefer PROMPTSHIELD_METRICS_ADDR.
PROMPTSHIELD_METRICS_ADDRInternal-only bind address for /metrics, e.g. 127.0.0.1:9090
PROMPTSHIELD_TRUST_PROXY_CIDRSComma-separated CIDRs to trust for X-Real-IP headers, e.g. 10.0.0.0/8,192.168.0.0/16. Loopback is always trusted.

TLS

Set both or neither. Setting one without the other is a startup error.

VariableDescription
PROMPTSHIELD_TLS_CERTPath to TLS certificate (PEM)
PROMPTSHIELD_TLS_KEYPath to TLS private key (PEM)

Detection engine

VariableDefaultDescription
PROMPTSHIELD_ENGINE_PORT4321Port the engine listens on
PROMPTSHIELD_ENGINE_HOST0.0.0.0Host the engine binds to
PROMPTSHIELD_LOG_LEVELINFOLog level: DEBUG | INFO | WARNING | ERROR
PROMPTSHIELD_API_KEYBearer token clients must send. Must match ENGINE_API_KEY (dashboard) and PROMPTSHIELD_ENGINE_API_KEY (proxy). Leave empty only when PROMPTSHIELD_ALLOW_UNAUTH=true.
PROMPTSHIELD_ALLOW_UNAUTHfalseAllow unauthenticated requests. Only for local development.

Dashboard

Dashboard server (apps/server)

VariableDefaultRequiredDescription
DATABASE_URLYesPostgreSQL connection string
BETTER_AUTH_SECRETYesAuth signing secret (min 32 chars)
BETTER_AUTH_URLhttp://localhost:3000YesPublic URL of the auth server
CORS_ORIGINhttp://localhost:8000YesAllowed CORS origin (the web app URL)
ENGINE_URLhttp://localhost:4321NoDetection engine base URL
ENGINE_API_KEYNo*Bearer token for engine requests. *Required when PROMPTSHIELD_ALLOW_UNAUTH=false on the engine (the default). Must match PROMPTSHIELD_API_KEY in the engine.
PROXY_URLhttp://localhost:8080NoProxy base URL for health checks and admin calls
PROXY_ADMIN_TOKENNoToken for proxy admin API calls. Must match PROXY_ADMIN_TOKEN in the proxy.
PROXY_CONFIG_SOURCElocal_envNolocal_env reads from PROXY_ENV_PATH; proxy_api calls the proxy admin API
PROXY_CONFIG_ENDPOINT/admin/configNoProxy admin config endpoint path
POLICY_SOURCElocal_fileNolocal_file reads/writes POLICY_FILE_PATH; proxy_api uses the proxy admin API
PROXY_POLICY_ENDPOINT/admin/policyNoProxy admin policy endpoint path
POLICY_FILE_PATH../../config/policy.yamlNoPath to policy YAML (when POLICY_SOURCE=local_file)
POLICY_ALLOWED_DIRSNoComma-separated absolute paths allowed for policy file operations
PROXY_ENV_PATH../../config/proxy.envNoPath to proxy env file (when PROXY_CONFIG_SOURCE=local_env)
AUDIT_INGEST_SECRETYesShared secret validating audit ingest requests from log-fwd or proxy direct push
CONFIG_ADMIN_EMAILSNoComma-separated emails allowed to call config-mutating endpoints

Web app (apps/web)

VariableDefaultDescription
VITE_SERVER_URLhttp://localhost:3000Dashboard server URL (browser-side). Must be reachable from the user's browser.

Audit log forwarding (log-fwd sidecar)

VariableDefaultDescription
AUDIT_SERVER_URLhttp://ps-server:3000Dashboard URL the log-fwd sidecar POSTs audit lines to
AUDIT_INGEST_SECRETShared secret (must match the dashboard server's AUDIT_INGEST_SECRET)
PROXY_LOG_SOURCEdockerLog source: docker tails container logs, file tails a log file, stdin reads stdin
PROXY_CONTAINER_NAMEpromptshield-proxyDocker container to tail when PROXY_LOG_SOURCE=docker
PROXY_LOG_FILE/proxy-logs/promptshield.logLog file to tail when PROXY_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:

VariableInjected valueNotes
DATABASE_URLBuilt from POSTGRES_PASSWORDInjected into the server service
BETTER_AUTH_URLhttp://localhost:3000Injected into the server service
CORS_ORIGINhttp://localhost:8000Injected into the server service
ENGINE_URLhttp://promptshield-engine:4321Container-network address
ENGINE_API_KEY${ENGINE_API_KEY:-dev-engine-key}Falls back to dev-engine-key if not set in .env.local
PROXY_URLhttp://promptshield-proxy:8080Container-network address
VITE_SERVER_URLhttp://localhost:3000Browser-facing; stays as localhost

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.


Proxy cannot reach the detection engine (401)

Symptom: Requests pass through unscanned; proxy logs show engine 401.

Cause: PROMPTSHIELD_ENGINE_API_KEY is missing from the proxy environment.

Fix: Add PROMPTSHIELD_ENGINE_API_KEY=<value> to promptshield-proxy/.env. Value must equal PROMPTSHIELD_API_KEY on the engine.


Dashboard admin calls to proxy fail (403)

Symptom: Policy or config saves from the dashboard return 403.

Cause: PROXY_ADMIN_TOKEN differs between the dashboard and the proxy.

Fix: Ensure both use the same value. In docker-compose, the proxy falls back to dev-proxy-admin-token. Set PROXY_ADMIN_TOKEN=dev-proxy-admin-token in promptshield/.env.local to match.


Audit logs not appearing in the dashboard

Symptom: Dashboard shows no audit events despite traffic flowing through the proxy.

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. 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-proxy/.env. The secret must match AUDIT_INGEST_SECRET in the dashboard.

On this page