Docs/Build & operate
Configuration reference

Configuration variables

A complete reference for Probara service, frontend, agent, maintenance, and deployment environment variables, including code defaults and the variables that Docker Compose and Helm actually wire.

How configuration is resolved

Each Go process reads environment variables directly. A code default only applies after the variable reaches the process; Docker Compose and the Helm chart expose smaller, different subsets of the complete runtime surface.

Code default
The value selected by shared/config when the process environment does not contain the variable.
Docker wiring
A variable explicitly listed beneath a service in docker-compose.yml. The root .env file is used for Compose interpolation, but it is not passed wholesale into containers.
Helm wiring
A chart value rendered into a workload environment. The chart has no general extraEnv escape hatch in the current dev state.
Local-process wiring
Defaults exported by scripts/start-local-services.sh before it launches locally built binaries.

Common service variables

Where a table row below says a variable is “not exposed” by a deployment method, it means there is no dedicated Compose declaration or Helm value for it. In Helm, any such variable can still be injected without template changes via extraEnv (all workloads) or <service>.extraEnv — see Helm values. In Compose, add it to the service environment block explicitly.

VariableCode default / validationUsed byDeployment notes
HTTP_PORTRequired integer; no code defaultEvery Go serviceRequired even for scheduler and alerter, whose operational endpoint is normally the metrics listener.
METRICS_PORTRequired integer; no code defaultEvery Go serviceHosts /healthz, /readyz, and /metrics for scheduler, worker, alerter, and the status service.
LOG_LEVELinfoEvery Go serviceCompose and Helm set this explicitly. Use a supported structured logger level such as debug, info, warn, or error.
POSTGRES_URLEmptyAPI, scheduler, worker, alerter, status page, CLIsRequired by API, scheduler, alerter, and status page. Optional for workers; a worker without it cannot run the notification, AI-RCA or alert-triage (relay and consumer) side consumers.
NATS_URLnats://localhost:4222API, scheduler, worker, alerter, status page updatesScheduler and worker require NATS. API and status live-update paths degrade when it is unavailable; alerter can run synchronous dispatch without it.

API authentication, sessions, and audit

VariableCode default / validationDocker / Helm wiring
ADMIN_JWT_SECRETRequired; validation only rejects an empty value. Use at least 32 random characters.Compose ships an insecure hardcoded default and the Helm values ship a placeholder default; override both for production.
ADMIN_ACCESS_TTL_MINUTES15; integerLocal-process script sets it. Compose and Helm rely on the code default.
ADMIN_REFRESH_TTL_DAYS30; integerLocal-process script sets it. Compose and Helm rely on the code default.
ADMIN_COOKIE_SECUREfalse; booleanLocal-process script sets false. Compose and Helm do not expose it; production HTTPS deployments should wire true.
ADMIN_BCRYPT_COST12; integerNot exposed by Compose or Helm. Also used by the admin creation CLI.
AUDIT_RETENTION_DAYS365; nonnegative integer; 0 keeps records foreverCompose and Helm expose the audit-retention setting; the API owns pruning.

The access cookie is HttpOnly and SameSite=Lax. ADMIN_COOKIE_SECURE controls its Secure attribute. Access and refresh TTL values are only parsed as integers; the loader does not reject zero or negative values, so use deliberate positive settings.

Public URLs and private-location authorization

VariableCode default / validationPurpose and caveats
PUBLIC_BASE_URLEmpty; surrounding whitespace and trailing slash removedExternally reachable API origin used in agent installers, push webhooks, the default OIDC callback, and the MCP OAuth issuer and discovery metadata (derived from the request when empty). Compose and Helm require it for normal deployment.
PUBLIC_NATS_URLEmptyBroker address embedded in private-location deployment instructions. When deployment information is generated, only tls:// and wss:// URLs are accepted; pre-existing URL credentials are rejected.
NATS_LOCATION_AUTH_ISSUER_SEEDEmptyRequired whenever PUBLIC_NATS_URL is nonempty. It must be a NATS account seed for the API-hosted authorization callout.
WORKER_LOCATION_IDEmpty or UUIDPins a worker to one private location. Empty selects the default platform worker fleet.
LOCATION_CREDENTIALEmptyRequired if and only if WORKER_LOCATION_ID is set. Generated credentials are URL-safe base64 for 32 random bytes.

OIDC single sign-on

VariableDefault / validationDescription
OIDC_ENABLEDfalse; booleanEnables platform-wide OIDC discovery and login.
OIDC_ISSUER_URLRequired when enabledIssuer URL used for OIDC discovery.
OIDC_CLIENT_IDRequired when enabledRegistered OAuth/OIDC client identifier.
OIDC_CLIENT_SECRETRequired when enabledConfidential client secret; store in a secret manager or Kubernetes Secret.
OIDC_REDIRECT_URLDefaults to PUBLIC_BASE_URL + /api/v1/auth/oidc/callbackMust be supplied explicitly if PUBLIC_BASE_URL is empty.
OIDC_SCOPESopenid profile emailWhitespace-separated scopes. Add groups when using OIDC group mappings — many IdPs (Okta among them) only emit the groups claim when the scope is requested.
OIDC_GROUPS_CLAIMgroupsID-token claim read for group→role mappings. The mapping rules themselves live in the database (Settings → Access → OIDC group mappings), not in environment variables.
OIDC_PROVIDER_LABELSSOHuman-readable login-provider label.
OIDC_JIT_PROVISIONtrue; booleanCreates a local user record for a valid first-time OIDC identity.
OIDC_JIT_DEFAULT_ROLEviewer; one of admin, editor, viewerDefault tenant role for JIT users. Ignored whenever any OIDC group mappings exist — mapped roles replace the JIT defaults entirely.
OIDC_JIT_DEFAULT_TENANT_ID00000000-0000-0000-0000-000000000001Tenant receiving JIT users. The loader does not validate UUID syntax; verify it refers to the intended tenant.

Compose includes development-oriented Dex defaults under its optional profile. Helm exposes the platform OIDC settings and stores the client secret separately. In production, register an exact HTTPS callback and choose the least-privileged JIT role.

Encryption-at-rest keys

VariableFormatBehavior
PROBARA_SECRETS_KEYBase64 encoding of exactly 32 bytesVersion 1 key for encrypted channel, monitor and location credentials (and any retired AI provider key kept for rollback).
PROBARA_SECRETS_KEY_V2 … PROBARA_SECRETS_KEY_V100Each is base64 encoding of exactly 32 bytesOptional rotation keys. The highest configured version encrypts new writes; older keys remain available for decryption.
Generate a 32-byte base key
openssl rand -base64 32

API queues, local AI, mesh, and artifacts

VariableCode defaultUse / deployment status
ALERT_STREAMALERTSLoaded by the API but not used by a current API runtime path.
ALERT_SUBJECTalertsAPI alert live-update subscriber subject.
ALERT_CONSUMER_NAMEapi-alertsLoaded but not currently used.
CHECK_JOB_STREAMCHECK_JOBSNATS authorization permissions and job topology. Compose and Helm pass the scheduler stream to API.
CHECK_JOB_SUBJECTcheck.jobsOn-demand check publication. Compose and Helm pass the scheduler/worker subject to API; keep all three aligned.
CHECK_RESULT_SUBJECTcheck.resultsPrivate-location result permission and result contract.
AI_RCA_SUBJECTai.rca.jobsAI root-cause job publication; must match worker.
MESH_PROBE_INTERVAL_SECONDS30; positive integerMirrors scheduler cadence so API staleness calculations agree.
MESH_PROBE_TIMEOUT_SECONDS5; positive integerMirrors scheduler probe timeout.
SYNTHETIC_BROWSER_ARTIFACTS_DIROS temporary directory + probara/synthetic-browser-artifactsAPI reads and workers write browser artifacts. Compose shares a volume; Helm currently does not.
Local AI variableDefault / validationRead by and deployment wiring
LOCAL_AI_DISABLEDfalseAPI, worker, alerter and the inference service. true overrides every workspace switch, and the service then loads no model (readiness answers 503); the alerter only reads it to stop suspected-cause follow-ups. Compose forwards the shell value to all four; Helm renders true on API, worker and alerter when localAI.enabled=false and no localAI.externalUrl is set.
LOCAL_AI_URLhttp://127.0.0.1:8090; http(s)://host[:port] with no path, query or credentialsAPI and worker. Compose sets http://local-ai:8090; Helm sets http://<release>-local-ai:8090 or localAI.externalUrl; the local-process stack uses the default (the container is published on loopback).
LOCAL_AI_TOKENAt least 16 charactersAPI, worker and the inference service, which must all hold the same value. Surrounding whitespace, such as the trailing newline of a Secret created from a file, is ignored on every side. The service refuses to start without a valid token; API and worker start anyway and report local AI as not configured correctly. See token handling for Compose, local and Helm defaults.
LOCAL_AI_TIMEOUT_SECONDS90; 1–300API and worker request timeout. An out-of-range value stops startup. Helm: localAI.timeoutSeconds.
LOCAL_AI_THREADS4; 1–4Inference service only: CPU threads for the single inference process. The model is CPU-validated at 4. Compose defaults to 4 and the Make targets to min(host CPUs, 4); Helm: localAI.threads.
LOCAL_AI_QUEUE_CAPACITY4; 1–32Inference service only: batches allowed to wait behind the one executing; beyond that the service answers 429. Helm: localAI.queueCapacity.
LOCAL_AI_QUEUE_TIMEOUT_SECONDS60; above 0, at most 300Inference service only: how long a waiting batch may wait for the executing slot before a 429. A full 50-decision batch takes about 15–20 seconds on 4 CPU threads; keep it below LOCAL_AI_TIMEOUT_SECONDS so a queued caller gets a retryable 429 rather than its own timeout (Helm enforces this). Compose forwards the shell value (default 60); Helm: localAI.queueTimeoutSeconds.
LOCAL_AI_MAX_INFERENCE_SECONDS120; above 0, at most 600Inference service only: a batch still running after this long is treated as wedged, and /healthz and /readyz answer 503 until it finishes, so the Kubernetes liveness probe restarts the pod. Compose forwards the shell value (default 120) and marks the container unhealthy; Docker does not restart an unhealthy container by itself. Helm: localAI.maxInferenceSeconds.
LOCAL_AI_IMAGE, LOCAL_AI_CPUSghcr.io/yassinebenameur/probara-local-ai:latest; 4Compose interpolation only: the image to pull (built from ai-service/ when the pull fails) and the container CPU limit. latest is pushed only by stable releases, so on the prerelease line set LOCAL_AI_IMAGE to an :alpha or version tag, or Compose builds the image locally (Git LFS head weights required); a local build keeps the tag, so rebuild it (docker compose build local-ai) after an ai-service/ change. Docker requires the CPU limit to be at most the host CPU count. The Make targets and scripts/start-local-services.sh default it to min(host CPUs, 4).

Local AI uses one evaluated Probara checkpoint, served by the installation-owned inference service (ai-service/), for every AI surface: incident analysis, automatic alert triage and dependency suggestions. Range errors in the service variables stop the service at startup; Helm checks threads, queueCapacity, queueTimeoutSeconds, maxInferenceSeconds and timeoutSeconds (and that the queue timeout is below the client timeout) at render time instead. Workspace rows store only effective enablement: explicit enabled/disabled settings are preserved and absent settings default enabled. External providers and LLM_* execution are retired; old columns are retained for rollback. Explanations come from measured evidence and maintained templates.

Scheduler and result-ingest variables

VariableCode default / validationCompose / Helm notes
SCHEDULE_INTERVAL_SECONDS2; positive integerCompose and Helm override to 5.
SCHEDULER_BATCH_SIZE500; positive integerNot exposed by Compose or Helm.
CHECK_JOB_STREAMCHECK_JOBSCompose and Helm override to check-jobs.
CHECK_JOB_SUBJECTcheck.jobsCompose and Helm override to check.job.
CHECK_RESULT_STREAMCHECK_RESULTSNot exposed by Compose or Helm.
CHECK_RESULT_SUBJECTcheck.resultsNot exposed by Compose or Helm.
RESULT_INGEST_CONSUMER_NAMEresult-ingestNot exposed by Compose or Helm.
RESULT_INGEST_CONCURRENCY10; positive integerNot exposed by Compose or Helm.
RESULT_INGEST_ENABLEDtrue; booleanNot exposed by Compose or Helm. false means worker results are published but not persisted.
CHECK_JOB_LEGACY_CONSUMERScheck-workers,workerComma-separated old filterless durable consumers deleted at scheduler startup.
RETENTION_CLEANUP_ENABLEDtrue; booleanExposed by Compose and Helm.
RETENTION_CLEANUP_HOUR_UTC2; integer 0–23Exposed by Compose and Helm.
RETENTION_CLEANUP_BATCH_SIZE5000; positive integerExposed by Compose and Helm.
RETENTION_CLEANUP_MAX_ROWS_PER_RUN200000; positive integerExposed by Compose and Helm.
MONITOR_PURGE_ENABLEDtrue; booleanNot exposed by Compose or Helm.
MONITOR_PURGE_INTERVAL_SECONDS30; positive integerNot exposed by Compose or Helm.
MONITOR_PURGE_BATCH_SIZE5000; positive integerNot exposed by Compose or Helm.
MONITOR_PURGE_MAX_ROWS_PER_RUN200000; positive integerNot exposed by Compose or Helm.
MESH_ENABLEDtrue; booleanNot exposed by Compose or Helm.
MESH_PROBE_INTERVAL_SECONDS30; positive integerNot exposed by Compose or Helm.
MESH_PROBE_TIMEOUT_SECONDS5; positive integerNot exposed by Compose or Helm.
MESH_FAILURE_THRESHOLD3; positive integerNot exposed by Compose or Helm.
MESH_SCHEDULE_BATCH_SIZE500; positive integerNot exposed by Compose or Helm.

Worker execution and network-policy variables

VariableCode default / validationNotes
WORKER_CONCURRENCY10; positive integerConcurrent check-job handlers.
NATS_CONSUMER_NAMEcheck-workersCompose and Helm override to worker for the default fleet.
CHECK_JOB_STREAMCHECK_JOBSMust match scheduler.
CHECK_JOB_SUBJECTcheck.jobsMust match scheduler and API.
CHECK_RESULT_STREAMCHECK_RESULTSResult work-queue stream.
CHECK_RESULT_SUBJECTcheck.resultsResult publication subject.
MAX_HTTP_TIMEOUT_SECONDS30; integerLoaded but currently unused outside the configuration object.
MAX_BODY_SIZE_BYTES1048576; positive integerMaximum HTTP response body accepted by the worker.
HTTP_BLOCK_PRIVATE_IPSfalse; booleanWhen enabled, blocks private, loopback, link-local, and reserved destinations across networked check types.
HTTP_ALLOWED_CIDRSEmpty; comma-separated CIDRsNarrow exceptions to the block policy. Entries also admit a private media address that a public SIP peer names in its SDP answer, which a test call with `call.media` otherwise refuses even with blocking off. Any invalid CIDR fails startup.
CHROME_BINAutodetect common Chromium/Chrome namesOverride the browser executable. The worker image sets /usr/bin/chromium-browser.
SIP_LOCALHOST_AS_HOST_GATEWAYfalseRewrites each SIP target host that is localhost or a loopback IP (the monitor host or, under resolution: rfc3263, an SRV target) to host.docker.internal before it is resolved, so a containerized worker can reach a SIP server on the developer machine. Truthy values are 1, true, yes, and on. The Compose worker turns it on. make start-all-local leaves it off: its worker runs on the host, where loopback already reaches the developer machine and the rewrite would break SIP to localhost. Leave it off in production.
SIP_CALL_ENABLEDtrue on platform workers, false on private-location workers (WORKER_LOCATION_ID set)Lets the worker place SIP test calls (method: invite), which are real and possibly billed. A disabled worker fails each one with sip_call: disabled on this worker before sending anything. It also gates call quality (call.media, which sends RTP and RTCP during the hold): there is no separate media switch. A private-location operator opts in with SIP_CALL_ENABLED=true (Helm: worker.locations[].extraEnv). Any value strconv.ParseBool rejects fails startup.
SIP_CALL_ALLOWED_DESTINATIONSEmpty (every destination)Comma-separated regular expressions; a test call is placed only when the called user part (call.number, or the decoded user part of call.target_uri, which may carry no ;parameters or :password) matches one in full (each is anchored), else it fails with policy: destination not allowed by worker policy before sending anything. An invalid expression fails startup.

Worker AI and asynchronous notifications

VariableCode defaultNotes
AI_RCA_STREAMAI_RCAAI root-cause work-queue stream.
AI_RCA_SUBJECTai.rca.jobsMust match API.
AI_RCA_CONSUMER_NAMEai-rca-workersDurable AI consumer.
AI_TRIAGE_ENABLEDtrue; boolean, invalid values fail startupPlatform kill switch for automatic alert triage, read by the worker, the alerter and the API. On the worker false stops new claims only; queued triages finish as skipped without calling the model. On the alerter false stops every suspected-cause follow-up, including from triages that were already ready. On the API false (or LOCAL_AI_DISABLED=true) keeps SLA reports from listing an alert with no triage as Triage pending. Compose forwards the shell value to all three; Helm renders localAI.triageEnabled into all three.
AI_TRIAGE_STREAMAI_TRIAGEAlert triage work-queue stream (1-hour max age). Must differ from AI_RCA_STREAM, or startup fails.
AI_TRIAGE_SUBJECTai.triage.jobsWorker-internal: the relay publishes and the triage consumer reads it, so the API does not need it. Must differ from AI_RCA_SUBJECT, or startup fails.
AI_TRIAGE_CONSUMER_NAMEai-triage-workersDurable triage consumer.
NOTIFICATIONS_ENABLEDfalseStarts the worker notification consumer only when PostgreSQL is also configured.
NOTIFICATIONS_STREAMNOTIFICATIONSAsync notification work queue.
NOTIFICATIONS_SUBJECT_GLOBalerts.dispatch.>Subject filter shared with alerter.
NOTIFICATIONS_CONSUMER_NAMEnotifications-workerDurable dispatch consumer.

The database-connected worker uses the same LOCAL_AI_* client variables as the API; Compose and Helm wire them to both, and Helm wires SMTP_* through its smtp values block. The AI_RCA_* variables and the AI_TRIAGE_* stream names are not wired, so their code defaults apply; set them through extraEnv only to rename the streams. AI_TRIAGE_ENABLED is wired to the worker, the alerter and the API. Only database-connected platform workers read AI_TRIAGE_*: they run the triage relay and consumer, and location workers never do. Private-location workers receive no database or AI credentials and execute checks independently. Notification-mode variables still require extraEnv.

Alerter and SMTP variables

VariableCode default / validationDescription
ALERT_STREAMALERTSAlert-event stream.
ALERT_SUBJECTalertsAlert-event subject.
ALERT_EVAL_INTERVAL_SECONDS30; positive integerCurrent alert-lifecycle evaluation cadence.
ALERTER_LATENCY_ANOMALY_ENABLEDtrue; booleanEnables latency-anomaly evaluation.
ALERT_REMINDER_INTERVAL_SECONDS3600; positive integerLegacy variable used only by the retired alert-evaluation path; current reminders use each tenant’s alert_reminder_seconds setting.
ALERT_GROUP_WINDOW_SECONDS60; positive integerLegacy grouping-window variable used only by the retired alert-evaluation path; currently unused.
ALERT_GROUP_MAX_CHILDREN5; positive integerLegacy grouped-child limit used only by the retired alert-evaluation path; currently unused. Current lifecycle handling uses group rollup.
ALERT_EMAIL_TOEmptyComma-separated fallback recipients for built-in email.
ALERTER_ASYNC_DISPATCHfalse; booleanPublishes channel dispatch jobs to NATS instead of sending synchronously.
LOCAL_AI_DISABLED / AI_TRIAGE_ENABLEDfalse / true; boolean, invalid values fail startupThe local AI kill switches. The alerter never calls local AI; with LOCAL_AI_DISABLED=true or AI_TRIAGE_ENABLED=false it sends no suspected-cause follow-ups, whatever the workspace settings say.
NOTIFICATIONS_STREAMNOTIFICATIONSMust match worker.
NOTIFICATIONS_SUBJECT_GLOBalerts.dispatch.>Must match worker.

The SMTP_* variables are read identically by three services, and each one needs them for a different reason: the alerter delivers alert email from its evaluation loop, the worker delivers it when asynchronous dispatch is enabled, and the API serves POST /api/v1/alert-channels/{id}/test, which runs the same email plugin in-process. An install that sets SMTP only on the alerter delivers alerts correctly but fails every email channel test with mailer not configured. The Helm smtp values block renders the variables into all three at once; set it there rather than in a single service's extraEnv.

SMTP variableCode defaultImportant behavior
SMTP_HOSTEmptyRequired for usable built-in email delivery.
SMTP_PORT587Integer port.
SMTP_USERNAMEEmptyOptional SMTP authentication username.
SMTP_PASSWORDEmptySMTP authentication secret.
SMTP_FROMSMTP_USERNAME when emptyRequired effective sender address.
SMTP_FROM_NAMEProbara AlertsDisplay name on the From header. The envelope sender stays SMTP_FROM.
SMTP_USE_TLStrue; booleantrue selects direct implicit TLS, not STARTTLS. Verify the provider and port pairing.
APP_BASE_URLEmptyPublic origin of the operator UI. Adds an "open the monitor" link to alert email and every chat, paging and SMS channel; omitted when unset. Read by the same three services. The API also sends MCP sign-ins to the consent screen at this origin (default: the API origin, which is right when the UI and API share one).

The same three services also read the notification egress policy, because each one can deliver through a channel plugin. It is independent of the worker's HTTP_BLOCK_PRIVATE_IPS and, unlike it, blocks by default.

Notification variableCode defaultImportant behavior
NOTIFICATION_BLOCK_PRIVATE_IPStrue; booleanRefuse private, loopback, link-local and reserved destinations for every notification channel. Set false only when channels must reach internal hosts and network policy already contains them.
NOTIFICATION_ALLOWED_CIDRSEmpty; comma-separated CIDRsDestinations that stay reachable while blocking is on, e.g. an internal webhook receiver. Any invalid CIDR fails startup.

Status-page and live-update variables

VariableCode default / validationDescription
STATUS_PAGE_BASE_URLEmptyPublic origin of the status service. Supplies the deep link in visitor push notifications; when empty, the notification opens the page via the service worker scope rather than a guessed host.
STATUS_PAGE_API_BASE_URLEmptyEnables the status service’s restricted API reverse proxy.
STATUS_PAGE_READ_TIMEOUT_SECONDS15Invalid or nonpositive input silently falls back to 15 seconds.
STATUS_PAGE_WRITE_TIMEOUT_SECONDS60Invalid or nonpositive input silently falls back to 60 seconds.
STATUS_PAGE_CACHE_TTL10s Go durationInvalid or nonpositive input falls back to 10 seconds.
STATUS_PAGE_PREVIEW_SECRETEmptyHMAC secret shared with API for one-hour preview tokens. With no secret, preview verification is not enforced.
STATUSPAGE_UPDATES_SUBJECTstatuspage.updatesCore NATS live-invalidation subject shared by API, scheduler, and status service. Also wakes the push sender early; delivery does not depend on it.
STATUS_PAGE_VAPID_PUBLIC_KEYEmptyVAPID application server key for visitor notifications. Published inside every rendered page, so it is not a secret. Generate with go run ./cmd/admin/gen_vapid_keys.
STATUS_PAGE_VAPID_PRIVATE_KEYEmptySigns the push JWT. A credential. Notifications are disabled unless both key halves are set; never generate per process, because replicas would disagree and a restart would invalidate every subscription.
STATUS_PAGE_VAPID_SUBJECTEmptymailto: or https: operator contact for the VAPID sub claim. Some push services reject a missing or malformed value.
STATUS_PAGE_PUSH_ENDPOINT_ALLOWLISTGoogle, Mozilla, Microsoft, Apple push hostsComma-separated host suffixes a stored push endpoint may use. This is an SSRF control; * disables it for a self-hosted push service.
STATUS_PAGE_PUSH_MAX_SUBSCRIPTIONS_PER_PAGE10000Cap on stored subscriptions per status page. Invalid or nonpositive input falls back to the default.
STATUS_PAGE_TRUSTED_PROXYfalseHonor X-Forwarded-For when rate-limiting push subscribes. Off by default because the header is client-settable.

The restricted proxy permits GET under /api/v1/monitors and PATCH under /api/v1/status-pages/…; it is not a general API proxy. Helm currently wires only basic status values and the status base URL, not the API proxy, cache, preview, timeout, or update-subject variables.

Frontend variables

VariableDefaultRuntime behavior
API_PROXY_TARGEThttp://localhost:8080Server-side destination for /api and downloadable agent-binary proxy routes.
NEXT_PUBLIC_API_URL/apiBrowser API base. Compiled into the Next.js client bundle.
NEXT_PUBLIC_STATUS_PAGE_URLEmptyStatus-page link origin; falls back to the current/relative origin or localhost during local use. Compiled into the client bundle.
NEXT_PUBLIC_DEBUG_INGEST_URLEmptyDeveloper-only debug timing sink. If set, monitor IDs and browser timing events are sent to it.
NODE_ENVDocker image sets productionNext.js runtime mode.
PORTDocker image sets 3000Next.js listener port.
HOSTNAMEDocker image sets 0.0.0.0Next.js bind address.

Collector agent settings

The host agent is probara-collector, an OpenTelemetry Collector distribution started as probara-collector --config <path>. Its generated configuration contains no secrets; credentials are supplied through the environment (systemd EnvironmentFile, launchd runner script, or the Windows service registry Environment value).

Environment variableDefaultDescription
PROBARA_API_KEYNone; requiredTenant write-scope API key sent as the Authorization: Bearer header.
PROBARA_AGENT_IDNone; requiredAgent monitor identifier sent as the X-Probara-Agent-Id header.

Discovery collector settings

The Kubernetes discovery collector (probara-discovery-collector) runs in the cluster from the manifest the setup form generates, which sets PROBARA_URL and PROBARA_DISCOVERY_ID and mounts the token Secret at the default PROBARA_DISCOVERY_TOKEN_FILE path; you only need these when writing your own manifest. It reaches the Kubernetes API through the in-cluster KUBERNETES_SERVICE_HOST/KUBERNETES_SERVICE_PORT and the mounted service-account CA and token.

Environment variableDefaultDescription
PROBARA_URLNone; requiredHTTPS origin of the Probara API, with no path, query or credentials; anything else fails startup.
PROBARA_DISCOVERY_IDNone; requiredThe discovery integration UUID.
PROBARA_DISCOVERY_TOKEN_FILE/var/run/probara/tokenFile holding the integration-scoped collector token (the manifest mounts its Secret there).
SSL_CERT_FILEUnset: the image's public CA bundlePEM bundle the collector trusts for the Probara origin; needed only when that origin uses a certificate from an internal CA. The Kubernetes API connection always uses the service-account CA instead.

The collector reads its configuration (active and pending namespaces) at the start of every cycle and waits five minutes between cycles, or the Retry-After delay (1 second to 1 hour) when the API answers 409, 429 or 503; the API sends a 10-second Retry-After with a 409 when a namespace was removed during the scan, and none for a stale revision. A refused request is logged with the HTTP status and up to 512 bytes of the response body, which carries the API's reason (for example rate_limited or inventory_limit). Pending namespaces are scanned after the active ones and stop 30 seconds before the two-minute cycle deadline; each one skipped is logged as Pending namespace <ns> skipped (<reason>): <hint> (see Change namespaces).

Probara origin behind an internal CA: store the CA certificate in a ConfigMap in the collector's namespace (the integration's home namespace, the first one entered at setup), mount it, and point SSL_CERT_FILE at it. A bundle holding only that CA is enough, since the Probara origin is the only peer verified against it. The generated manifest does not include this, so reapply the patch after applying a regenerated manifest (reinstall rotates the token).

bash
kubectl -n <home-namespace> create configmap probara-ca --from-file=ca.crt=internal-ca.pem
kubectl -n <home-namespace> patch deployment probara-discovery-<integration-prefix> -p '{"spec":{"template":{"spec":{
  "volumes":[{"name":"probara-ca","configMap":{"name":"probara-ca"}}],
  "containers":[{"name":"collector",
    "env":[{"name":"SSL_CERT_FILE","value":"/etc/probara-ca/ca.crt"}],
    "volumeMounts":[{"name":"probara-ca","mountPath":"/etc/probara-ca","readOnly":true}]}]}}}}'

Maintenance, build, and test variables

VariableDefault / requirementCommand or scope
MIGRATIONS_PATH./migrationsgo run ./cmd/migrate; local workflow supplies ./shared/db/migrations.
ADMIN_USERNAMERequiredgo run ./cmd/admin administrator upsert.
ADMIN_PASSWORDRequiredgo run ./cmd/admin; do not expose in shell history in production.
BOOTSTRAP_DB_USERprobarascripts/bootstrap-local-db.sh.
OCB_VERSIONv0.159.0scripts/build-collector.sh; pinned OpenTelemetry Collector Builder version, must match collector/manifest.yaml.
BUILD_DIR./static/collectorOutput directory for downloadable collector binaries and checksums.txt.
GHCR_OWNERFalls back to GITHUB_REPOSITORY_OWNER; then requiredHelm OCI publication.
GITHUB_REPOSITORY_OWNERGitHub Actions context or shell valueFallback owner used by Helm OCI publication when GHCR_OWNER is empty.
GHCR_HELM_REPOoci://ghcr.io/<owner>/chartsHelm OCI destination.
SEMANTIC_RELEASE_TOKENRequired GitHub Actions secret for release workflowUsed as semantic-release, GHCR/Helm registry, GH_TOKEN, and GITHUB_TOKEN credential. Scope it to the repository/packages required by the workflow.
LAYA_GIT_URL, HF_ENDPOINT, BASE_MODEL_REPO, BASE_MODEL_REVISIONhttps://github.com/NandhaKishorM/laya.git, https://huggingface.co, empty, empty (= base-lock.json)Build args of ai-service/Dockerfile naming where the pinned laya commit and base model are fetched from, for a mirror; the pinned commit and every locked sha256 are still checked. CI reads the first two from repository variables of the same name, and release.yml checks those sources still serve the pins before tagging.
APIhttp://localhost:8080scripts/verify-auth.sh.
ADMIN_USERadminAuthentication verification helper.
ADMIN_PASSchange-meAuthentication verification helper only; never a production default.
VERIFY_SSO0Enable SSO checks in the auth verification helper.
API_URLhttp://localhost:8080Dependency-graph seed helper.
TENANT_IDAuto-select first tenant when supportedSeed/test helpers.
API_KEYPlaceholder in scripts/test-group-creation.shTest helper credential only; never use a production key in a disposable script shell history.
WRITE_PREVIEWEmptyTest-only flag that writes rendered status preview HTML.

GitHub’s PR_TITLE, PR_BODY, TARGET_BRANCH, GITHUB_OUTPUT, and GITHUB_STEP_SUMMARY variables are workflow-internal inputs for release-preview classification, not product runtime configuration. Docker build workflow values such as REGISTRY and IMAGE_PREFIX are likewise CI-owned defaults.

Deployment wiring summary

AreaDocker ComposeHelm chart
Core ports, DB, NATS, log levelWiredWired through values and generated connection URLs
Admin JWT and public API URLRequired interpolationRequired chart validation
OIDCDevelopment Dex-oriented variables wiredPrimary OIDC values and client Secret wired
Encryption keyringNot wiredBase key wired to API/worker/alerter, but not scheduler; rotation keys not exposed
Local AIlocal-ai service (loopback port 8090) wired to API and worker, LOCAL_AI_DISABLED and AI_TRIAGE_ENABLED also to the alerter, AI_TRIAGE_ENABLED also to the API; fixed public development token unless LOCAL_AI_TOKEN is set in the shell or .envlocalAI values: bundled Deployment, Service and NetworkPolicy, or externalUrl; token in local_ai_token; API and platform worker only (the alerter gets only LOCAL_AI_DISABLED and AI_TRIAGE_ENABLED; AI_TRIAGE_ENABLED also reaches the API)
SMTPNot wiredsmtp values block wired to API, worker, and alerter
Notification dispatch modeNot wiredNot wired
Scheduler result ingestCode defaults onlyCode defaults only
Scheduler purge and meshCode defaults onlyCode defaults only
Worker result stream and AI/notification queuesCode defaults onlyCode defaults only
Status cache, proxy, preview, timeout, update subjectPreview only; most defaultsNot wired
Browser artifact sharingShared volumeNo shared volume
Arbitrary extra environmentRequires editing ComposeNo extraEnv; requires chart template change