Skip to main content

Configuration & Secrets

This page lists every environment variable Notify reads, the structured caller-policy JSON, where each platform secret lives (env literal vs Key Vault secret-name), the target-host allowlist, and the retention window. It is for platform operators provisioning Notify.

Integrators who need per-environment vars for their own backends should read Push Service Environment Config instead.

Secrets live server-side only

Browsers only ever receive the VAPID public key (served via GET /api/v1/webpush/client-config). The VAPID private key and interaction-token secret stay on Notify only (backend or Key Vault).

Push-platform and editor bearer tokens are shared by value across two sides: Notify stores the canonical policy (NOTIFY_API_PUSH_PLATFORM_CALLERS_JSON) and editor secret (INAPP_EDITOR_API_AUTH_TOKEN); each product backend holds its own copy of the matching bearer token. None of these reach the browser.

Secret vs public at a glance

ValueSecret?Reaches the browser?
VAPID public keyPublicYes — served via client-config
VAPID private keySecretNever
Interaction-token secretSecretNever
Push-platform tokenSecretNever
Editor tokenSecretNever
Key Vault plumbing

Whenever a *_SECRET_NAME env var is set, Notify expects KEY_VAULT_URL to be configured so startup can resolve that secret. That applies to both notify-api and notify-sender.

Enablement, VAPID, and delivery

VarPurposeSecret?Cluster: use _SECRET_NAME?
NOTIFY_CHANNELS_ENABLEDComma-separated channel list. Must include WEB_PUSH for notify-api to register the web-push routes; keep IN_APP enabled for editor routes such as /api/v1/tenants/. Typical value: WEB_PUSH,IN_APP.No
NOTIFY_SENDER_WEBPUSH_ENABLEDEnable web push in notify-sender.No
NOTIFY_WEBPUSH_VAPID_PUBLIC_KEYThe VAPID public key; served to browsers via client-config.No (public)Yes — set NOTIFY_WEBPUSH_VAPID_PUBLIC_KEY_SECRET_NAME when the public key is stored in Key Vault.
NOTIFY_WEBPUSH_VAPID_PRIVATE_KEYThe VAPID private key used to sign pushes.YesYes — set NOTIFY_WEBPUSH_VAPID_PRIVATE_KEY_SECRET_NAME to pull from Key Vault instead of a literal.
NOTIFY_WEBPUSH_ALLOW_AUTO_VAPIDLocal-dev only: auto-generate temporary VAPID keys when none are configured. Does NOT make GET /api/v1/webpush/client-config ready.No
WEB_PUSH_DRY_RUNWhen true, delivery is skipped. GET /api/v1/webpush/client-config stays PUSH_ENV_NOT_READY until dry-run is off and usable VAPID keys exist.No
VAPID key shape

Generate a matching pair with go run ./cmd/webpush-keygen in notify/. The public key is ~87 URL-safe base64 characters (65 decoded bytes); the private key is ~43 characters (32 bytes). Do not swap them — notify rejects a private key in the public slot at startup, and browsers reject it at subscribe time.

danger

NOTIFY_WEBPUSH_ALLOW_AUTO_VAPID is local-dev only — auto-generates temporary VAPID keys when none are configured (lost on restart). Never enable it in shared or prod environments. And WEB_PUSH_DRY_RUN must be false anywhere real browser delivery is expected; while it is true, no push is actually sent.

Interaction token

Notify signs interaction tokens into outbound payloads and validates them on POST /api/v1/service/webpush/events/browser. The token only routes idempotent, non-mutating telemetry.

VarPurposeSecret?Cluster: use _SECRET_NAME?
NOTIFY_WEBPUSH_INTERACTION_TOKEN_SECRETSigning secret for interaction tokens. REQUIRED.YesYes — use NOTIFY_WEBPUSH_INTERACTION_TOKEN_SECRET_NAME to pull from Key Vault.
NOTIFY_WEBPUSH_INTERACTION_TOKEN_TTLGo duration; lifetime of the browser-telemetry token. Defaults to 720h (30 days, the retention window). Must outlive realistic delayed clicks.No

Target URL allowlist

VarPurposeSecret?
NOTIFY_WEBPUSH_ALLOWED_TARGET_HOSTSComma-separated host allowlist a rendered target_url (and action target_url) may point to. Example: casino.example.com,promo.example.com.No
Empty vs set behavior

When NOTIFY_WEBPUSH_ALLOWED_TARGET_HOSTS is empty, a scheme-only policy applies: any https host is allowed, and dangerous schemes (like javascript:) are ALWAYS rejected regardless. Set it to restrict deliveries to known product hosts. If a consumer uses a cross-origin /open handoff, keep its own WEBPUSH_ALLOWED_TARGET_HOSTS aligned with these hosts.

Push-platform auth (server side)

These vars define what Notify validates incoming bridge calls against.

VarPurposeSecret?Cluster: use _SECRET_NAME?
NOTIFY_API_PUSH_PLATFORM_CALLERS_JSONStructured caller policy.YesYes — use NOTIFY_API_PUSH_PLATFORM_CALLERS_JSON_SECRET_NAME to pull from Key Vault.

Caller policy JSON

{
"callers": [
{
"caller_id": "product-ui-backend",
"token": "replace-me",
"allowed_routes": [
"GET /api/v1/webpush/client-config",
"POST /api/v1/service/webpush/subscriptions",
"POST /api/v1/service/webpush/subscriptions/deactivate",
"POST /api/v1/service/webpush/events/browser",
"POST /api/v1/service/webpush/events/semantic"
],
"allowed_source_apps": ["product_ui"],
"tenant_ids": ["optional-scope"]
}
]
}
FieldMeaning
allowed_routesEach entry is a "METHOD /full/path" string.
allowed_source_appsMatched against the X-Source-App request header.
tenant_idsOptional scope — when present, the caller may only act for those tenants (enforced on tenant-bearing routes).
Shared local compose

The shared local compose ships a policy that only allows lumio_admin_dashboard. A second backend must extend that JSON before its calls are accepted.

For GET /api/v1/tenants/, template CRUD, POST /webpush/send, and GET /webpush/activity (admin authoring). Never use this token on browser lifecycle routes.

VarPurposeSecret?Cluster: use _SECRET_NAME?
INAPP_EDITOR_API_AUTH_TOKENEditor auth token for /api/v1/tenants/, template CRUD, admin send, and activity routes.YesYes — use INAPP_EDITOR_API_AUTH_TOKEN_SECRET_NAME to pull from Key Vault.

Retention

VarPurposeDefault
NOTIFY_SENDER_WEBPUSH_RETENTION_DAYSRetention window for push collections.30

Retention applies to the notifications_webpush and interaction_events_webpush collections via TTL indexes. notify-api also enforces a 30-day interaction-event TTL at startup.

Where secrets live

SecretEnv var (literal)Key Vault override (_SECRET_NAME)
VAPID public keyNOTIFY_WEBPUSH_VAPID_PUBLIC_KEYNOTIFY_WEBPUSH_VAPID_PUBLIC_KEY_SECRET_NAME
VAPID private keyNOTIFY_WEBPUSH_VAPID_PRIVATE_KEYNOTIFY_WEBPUSH_VAPID_PRIVATE_KEY_SECRET_NAME
Interaction-token secretNOTIFY_WEBPUSH_INTERACTION_TOKEN_SECRETNOTIFY_WEBPUSH_INTERACTION_TOKEN_SECRET_NAME
Caller policy JSONNOTIFY_API_PUSH_PLATFORM_CALLERS_JSONNOTIFY_API_PUSH_PLATFORM_CALLERS_JSON_SECRET_NAME
Editor tokenINAPP_EDITOR_API_AUTH_TOKENINAPP_EDITOR_API_AUTH_TOKEN_SECRET_NAME

See also