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.
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
| Value | Secret? | Reaches the browser? |
|---|---|---|
| VAPID public key | Public | Yes — served via client-config |
| VAPID private key | Secret | Never |
| Interaction-token secret | Secret | Never |
| Push-platform token | Secret | Never |
| Editor token | Secret | Never |
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
| Var | Purpose | Secret? | Cluster: use _SECRET_NAME? |
|---|---|---|---|
NOTIFY_CHANNELS_ENABLED | Comma-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_ENABLED | Enable web push in notify-sender. | No | — |
NOTIFY_WEBPUSH_VAPID_PUBLIC_KEY | The 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_KEY | The VAPID private key used to sign pushes. | Yes | Yes — set NOTIFY_WEBPUSH_VAPID_PRIVATE_KEY_SECRET_NAME to pull from Key Vault instead of a literal. |
NOTIFY_WEBPUSH_ALLOW_AUTO_VAPID | Local-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_RUN | When 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 | — |
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.
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.
| Var | Purpose | Secret? | Cluster: use _SECRET_NAME? |
|---|---|---|---|
NOTIFY_WEBPUSH_INTERACTION_TOKEN_SECRET | Signing secret for interaction tokens. REQUIRED. | Yes | Yes — use NOTIFY_WEBPUSH_INTERACTION_TOKEN_SECRET_NAME to pull from Key Vault. |
NOTIFY_WEBPUSH_INTERACTION_TOKEN_TTL | Go duration; lifetime of the browser-telemetry token. Defaults to 720h (30 days, the retention window). Must outlive realistic delayed clicks. | No | — |
Target URL allowlist
| Var | Purpose | Secret? |
|---|---|---|
NOTIFY_WEBPUSH_ALLOWED_TARGET_HOSTS | Comma-separated host allowlist a rendered target_url (and action target_url) may point to. Example: casino.example.com,promo.example.com. | No |
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.
| Var | Purpose | Secret? | Cluster: use _SECRET_NAME? |
|---|---|---|---|
NOTIFY_API_PUSH_PLATFORM_CALLERS_JSON | Structured caller policy. | Yes | Yes — 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"]
}
]
}
| Field | Meaning |
|---|---|
allowed_routes | Each entry is a "METHOD /full/path" string. |
allowed_source_apps | Matched against the X-Source-App request header. |
tenant_ids | Optional scope — when present, the caller may only act for those tenants (enforced on tenant-bearing routes). |
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.
| Var | Purpose | Secret? | Cluster: use _SECRET_NAME? |
|---|---|---|---|
INAPP_EDITOR_API_AUTH_TOKEN | Editor auth token for /api/v1/tenants/, template CRUD, admin send, and activity routes. | Yes | Yes — use INAPP_EDITOR_API_AUTH_TOKEN_SECRET_NAME to pull from Key Vault. |
Retention
| Var | Purpose | Default |
|---|---|---|
NOTIFY_SENDER_WEBPUSH_RETENTION_DAYS | Retention 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
| Secret | Env var (literal) | Key Vault override (_SECRET_NAME) |
|---|---|---|
| VAPID public key | NOTIFY_WEBPUSH_VAPID_PUBLIC_KEY | NOTIFY_WEBPUSH_VAPID_PUBLIC_KEY_SECRET_NAME |
| VAPID private key | NOTIFY_WEBPUSH_VAPID_PRIVATE_KEY | NOTIFY_WEBPUSH_VAPID_PRIVATE_KEY_SECRET_NAME |
| Interaction-token secret | NOTIFY_WEBPUSH_INTERACTION_TOKEN_SECRET | NOTIFY_WEBPUSH_INTERACTION_TOKEN_SECRET_NAME |
| Caller policy JSON | NOTIFY_API_PUSH_PLATFORM_CALLERS_JSON | NOTIFY_API_PUSH_PLATFORM_CALLERS_JSON_SECRET_NAME |
| Editor token | INAPP_EDITOR_API_AUTH_TOKEN | INAPP_EDITOR_API_AUTH_TOKEN_SECRET_NAME |
See also
- Push Service Environment Config — per-environment vars integrators configure on their own backends
- Integration Guide
- API Reference