Platform

Platform overviewArchitectureWorkflow orchestrationGitOps configurationGovernance and AAAAI and MCPKnowledge and contextRuntime and executionEvidence and monitoring

Use cases

All use casesProduction incidentRelease preparationHotfix to productionSecurity scan triage
Why NopsAIIntegrationsSecurity

Resources

All resourcesAI agent governanceMCP governanceMCP securitySelf-hosted platforms
PricingGitHub

Company

How a run worksAboutContactBook a demo

Environment and service configuration

Every environment variable the platform reads, starting with the secrets and service URLs that must exist before GitOps can take over.

ReferenceAdministratorSecurity

Key points

  • Bootstrap environment and deployment secrets are not the long-term source of truth — GitOps is. They exist so the platform can start and reach the point where GitOps loads.
  • JWT_SIGNING_KEY and SERVICE_JWT_SIGNING_KEY must be different secrets so user tokens cannot impersonate services.
  • Compose fails fast on a missing required value rather than starting in a broken state.
  • Production should keep DISPATCHER_TLS_MODE at mtls or tls, never disabled.
  • Rotating SERVICE_JWT_SIGNING_KEY and DISPATCHER_TLS_SECRET together is what prevents retired runners from rejoining a replacement control plane.

Field reference

DATABASE_URLapi, aaastringRequiredNone

PostgreSQL connection string for runtime state, config sync state, auth records, run records, logs, and evidence.

Example

DATABASE_URL=postgres://nopsai:***@db:5432/nopsai?sslmode=disable

Rules
  • Compose fails fast with set DATABASE_URL when it is missing.
Security

Holds every durable product record. Treat as a top-tier secret.

Evidence

docker-compose.yaml

NOPSAI_MASTER_KEYapistringRequiredNone

Root application encryption material for the credential registry and encrypted envelopes.

Example

NOPSAI_MASTER_KEY=<32+ byte random value>

Security

Losing this key makes every stored credential unrecoverable; rotating it requires re-encrypting the registry.

Evidence

config/config.go

JWT_SIGNING_KEYapistringRequiredNone

Signs user, personal-access, service-account, browser, CLI, automation, and hosted MCP tokens.

Example

JWT_SIGNING_KEY=<high-entropy value>

Security

Must be a different secret from SERVICE_JWT_SIGNING_KEY so user tokens cannot impersonate services.

Evidence

config/config.go

SERVICE_JWT_SIGNING_KEYapi, dispatcher, git-bot, runners, agentsstringRequiredNone

Signs internal REST and dispatcher service tokens between platform components.

Example

SERVICE_JWT_SIGNING_KEY=<high-entropy value>

Security

Shared by every component. Rotating it, together with DISPATCHER_TLS_SECRET, is what stops retired runners from rejoining.

Evidence

config/config.go

AAA_SHARED_INTERNAL_TOKENapi, aaastringRequiredNone

Authenticates internal authorization checks from the API to the AAA service.

Example

AAA_SHARED_INTERNAL_TOKEN=<high-entropy value>

Security

Anyone holding this token can ask AAA for authorization decisions directly.

Evidence

config/config.go

NOPSAI_BOOTSTRAP_ADMIN_EMAILapistringRequired[email protected] in Compose

Email address of the first local bootstrap administrator.

Evidence

docker-compose.yaml

NOPSAI_BOOTSTRAP_ADMIN_PASSWORDapistringRequiredNone

Initial password used to create or rotate the first local bootstrap administrator.

Example

NOPSAI_BOOTSTRAP_ADMIN_PASSWORD=<generated value>

Rules
  • Generated Docker Compose installs reject the built-in development admin password.
Security

Rotates on first login by default. See NOPSAI_BOOTSTRAP_ADMIN_MUST_CHANGE_PASSWORD.

Evidence

docker-compose.yaml

NOPSAI_BOOTSTRAP_ADMIN_PASSWORD_FILEapipathOptionalNone

File path form of the bootstrap password, for secret managers that mount files.

Example

NOPSAI_BOOTSTRAP_ADMIN_PASSWORD_FILE=/run/secrets/bootstrap-admin-password

Evidence

config/config.go

NOPSAI_BOOTSTRAP_ADMIN_MUST_CHANGE_PASSWORDapibooleanOptionaltrue

Forces the bootstrap administrator to rotate the password at first login.

Example

NOPSAI_BOOTSTRAP_ADMIN_MUST_CHANGE_PASSWORD=true

Security

Turning this off leaves a deployment-provisioned password in place indefinitely.

Evidence

docker-compose.yaml

NOPSAI_BOOTSTRAP_ADMIN_ALLOW_DEFAULT_PASSWORDapibooleanOptionalfalse

Allows the built-in development password. Intended for throwaway local environments only.

Example

NOPSAI_BOOTSTRAP_ADMIN_ALLOW_DEFAULT_PASSWORD=false

Security

Must stay false in any environment reachable by more than one person.

Evidence

docker-compose.yaml

NOPSAI_API_URLdispatcher, git-bot, runnersurlRequiredhttp://nopsai:8080 in Compose

Private API callback URL used by components that report back to the control plane.

Example

NOPSAI_API_URL=http://nopsai:8080

Evidence

docker-compose.yaml

AAA_API_URLapiurlRequiredhttp://aaa:8082 in Compose

Private URL of the AAA authorization service.

Example

AAA_API_URL=http://aaa:8082

Evidence

docker-compose.yaml

GIT_BOT_API_URLapiurlRequiredNone

Private git-bot URL used for repository fetch/write and GitHub check-run updates.

Example

GIT_BOT_API_URL=http://git-bot:8083

Evidence

config/config.go

DISPATCHER_GRPC_ADDRESSapi, runners, agentshost:portRequireddispatcher:9090 in Helm, dispatcher:9091 in Compose

Dispatcher gRPC endpoint. Cross-namespace Kubernetes runners normally need the fully qualified dispatcher.<platform-namespace>.svc.cluster.local:9090.

Example

DISPATCHER_GRPC_ADDRESS=dispatcher.nopsai.svc.cluster.local:9090

Rules
  • The dispatcher container itself listens on :9090 unless DISPATCHER_LISTEN_ADDRESS overrides it.
  • Helm reads this from topology.dispatcherGRPCAddress.
Evidence

deploy/helm/nopsai/values.yaml

NOPSAI_LISTEN_ADDRESSapihost:portOptional:8080

Bind address for the API HTTP server.

Example

NOPSAI_LISTEN_ADDRESS=:8080

Evidence

config/config.go

AAA_LISTEN_ADDRESSaaahost:portOptional:8082

Bind address for the AAA service.

Example

AAA_LISTEN_ADDRESS=:8082

Evidence

config/config.go

DISPATCHER_LISTEN_ADDRESSdispatcherhost:portOptional:9090

Bind address for the dispatcher gRPC server.

Example

DISPATCHER_LISTEN_ADDRESS=:9090

Evidence

services/dispatcher/internal/app/app.go

GIT_BOT_LISTEN_ADDRESSgit-bothost:portOptional:8083

Bind address for the git-bot service.

Example

GIT_BOT_LISTEN_ADDRESS=:8083

Evidence

config/config.go

NOPSAI_PUBLIC_URLapiurlOptionalNone

Externally reachable base URL, used in notification links and OIDC redirect construction.

Example

NOPSAI_PUBLIC_URL=https://nopsai.example.com

Evidence

config/config.go

NOPSAI_PLATFORM_IDapi, runnersstringOptionalNone

Ownership boundary that keeps bundled runners and generated runner installs attributed to the same platform.

Example

NOPSAI_PLATFORM_ID=prod-eu

Evidence

config/config.go

DISPATCHER_TLS_MODEdispatcher, runners, agentsstringRequiredNone

Transport mode for dispatcher gRPC.

Example

DISPATCHER_TLS_MODE=mtls

Allowed values

mtls, tls, disabled

Security

Production must not use disabled. Startup gates check this when production gates are required.

Evidence

config/config.go

DISPATCHER_TLS_SECRETdispatcher, runners, agentsstringConditionalNone

Shared high-entropy TLS or mTLS bootstrap secret. Required unless the mode is disabled.

Example

DISPATCHER_TLS_SECRET=<high-entropy value>

Security

Rotate together with SERVICE_JWT_SIGNING_KEY before exposing a fresh dispatcher, otherwise old runner definitions can authenticate again.

Evidence

config/config.go

DISPATCHER_TLS_SERVER_NAMErunners, agentsstringOptionalHost from DISPATCHER_GRPC_ADDRESS

Server name presented during TLS verification when it differs from the dial address.

Example

DISPATCHER_TLS_SERVER_NAME=dispatcher.nopsai.svc

Evidence

config/config.go

DISPATCHER_ROUTINGdispatchermap<string,string[]>OptionalNone

Configured route map from scope to runner IDs. GitOps owns this; the live view is derived from registered runners.

Example

DISPATCHER_ROUTING=platform/production=runner-a,runner-b

Evidence

config/config.go

RUNTIMErunnerstringOptionaldocker

Execution runtime the runner provides. Hybrid deployments use a comma-separated list.

Example

RUNTIME=docker,kubernetes

Allowed values

docker, kubernetes

Evidence

config/config.go

RUNNER_IDrunnerstringRequiredGenerated with a unique suffix

Dispatcher identity for this runner. Generated installs add a unique suffix to the friendly name.

Example

RUNNER_ID=eu-build-01-7f2a

Rules
  • Deliberate runner removal adds this ID to ejected_runner_ids and blocks reconnection.
Evidence

config/config.go

RUNNER_NAMErunnerstringOptionalNone

Friendly name preserved by generated installs and shown in the dispatcher fleet view.

Example

RUNNER_NAME=eu-build-01

RUNNER_SCOPESrunnerstringOptionalAll scopes

Scopes this runner accepts work for. An explicit empty value means all scopes.

Example

RUNNER_SCOPES=platform/production,platform/staging

Evidence

config/config.go

RUNNER_CAPACITYrunnerintegerOptionalRunner default

Number of concurrent runs this runner advertises to the dispatcher.

Example

RUNNER_CAPACITY=4

Evidence

config/config.go

DOCKER_NETWORK_NAMEdocker runnerstringOptionalDocker bridge

Network joined by step containers. Blank, bridge, or default keeps normal egress; none disables step networking; any other value joins that network.

Example

DOCKER_NETWORK_NAME=none

Allowed values

bridge, default, none, <custom network name>

Security

Use none when step workloads must run without egress, or a dedicated network for controlled egress.

Evidence

config/config.go

RUNTIME_POOLSkubernetes runnermapOptionalNone

Named Kubernetes runtime pools selectable through pipeline or step runtime_pool.

Example

RUNTIME_POOLS=gpu:node-role=gpu

Evidence

config/config.go

KUBERNETES_NAMESPACEkubernetes runnerstringOptionalRunner namespace

Namespace where the runner creates agent pods, step pods, and workspace PVCs.

Example

KUBERNETES_NAMESPACE=nopsai-runners

Evidence

config/config.go

KUBERNETES_SERVICE_ACCOUNTkubernetes runnerstringOptionalChart-managed runner service account

RBAC-bearing service account used by the runner Deployment and agent pods.

Example

KUBERNETES_SERVICE_ACCOUNT=nopsai-runner

Evidence

deploy/helm/nopsai

KUBERNETES_WORKLOAD_SERVICE_ACCOUNTkubernetes runnerstringOptionalChart-managed no-RBAC service account

Separate service account for step pods, deliberately without cluster permissions.

Example

KUBERNETES_WORKLOAD_SERVICE_ACCOUNT=nopsai-workload

Security

Keeping step pods on a no-RBAC account is what stops workload code from calling the Kubernetes API.

Evidence

deploy/helm/nopsai

KUBERNETES_IMAGE_PULL_SECRETSkubernetes runnerstring[]OptionalNone

Infrastructure-owned pull secrets attached to runner and step pods for private registries.

Example

KUBERNETES_IMAGE_PULL_SECRETS=regcred

Evidence

config/config.go

KUBERNETES_STORAGE_CLASSkubernetes runnerstringOptionalCluster default

Storage class used for the agent-owned workspace PVC.

Example

KUBERNETES_STORAGE_CLASS=fast-ssd

KUBERNETES_DEFAULT_WORKSPACE_SIZEkubernetes runnerstringOptionalChart default

Requested size of the run workspace PVC.

Example

KUBERNETES_DEFAULT_WORKSPACE_SIZE=20Gi

KUBERNETES_AFFINITY_ENABLEDkubernetes runnerbooleanOptionalChart default

Whether step pods in a run are scheduled onto the same node by default.

Example

KUBERNETES_AFFINITY_ENABLED=true

Overridden by

pipeline affinity_enabled

KUBERNETES_CLEANUP_FINISHED_PODSkubernetes runnerbooleanOptionalChart default

Whether finished step pods are deleted after their status is reported.

Example

KUBERNETES_CLEANUP_FINISHED_PODS=true

NOPSAI_REGISTRY_DOCKER_CONFIG_B64docker runnerstringOptionalNone

Base64 Docker config delivered at runner bootstrap so Docker runners can build per-image RegistryAuth locally.

Example

NOPSAI_REGISTRY_DOCKER_CONFIG_B64=<base64 docker config json>

Rules
  • The legacy /v1/internal/registry-auth/docker broker route has been removed.
Security

Keeps registry credentials on the runner instead of brokering them per image pull.

Evidence

doc/runner-registry-auth.md

SYSTEM_LOGS_PROVIDERapistringOptionalNone

Provider used to read live platform logs. Hybrid deployments use a comma-separated list.

Example

SYSTEM_LOGS_PROVIDER=docker,kubernetes

Allowed values

docker, kubernetes

Evidence

config/config.go

SYSTEM_LOGS_DOCKER_HOSTapiurlConditionaltcp://docker-socket-proxy:2375 in Compose

Restricted Docker endpoint used for System Logs. Required for the docker provider.

Example

SYSTEM_LOGS_DOCKER_HOST=tcp://docker-socket-proxy:2375

Security

Point this at the restricted socket proxy, never the raw Docker socket. The proxy allow-lists the reads System Logs needs.

Evidence

docker-compose.yaml

SYSTEM_LOGS_KUBERNETES_NAMESPACEapistringOptionalPlatform namespace

Namespace searched for platform pods when the kubernetes provider is used.

Example

SYSTEM_LOGS_KUBERNETES_NAMESPACE=nopsai

SYSTEM_LOGS_KUBERNETES_LABEL_SELECTORapistringOptionalNone

Label selector limiting which pods appear as System Logs sources.

Example

SYSTEM_LOGS_KUBERNETES_LABEL_SELECTOR=app.kubernetes.io/part-of=nopsai

FINAL_OUTPUT_PDF_RENDERER_URLapiurlConditionalhttp://gotenberg:3000 in Compose

Gotenberg endpoint used to render PDF final outputs. Required for type: pdf.

Example

FINAL_OUTPUT_PDF_RENDERER_URL=http://gotenberg:3000

Evidence

docker-compose.yaml

FINAL_OUTPUT_PDF_TIMEOUT_SECONDSapiintegerOptional45

Timeout applied to a single PDF render request.

Example

FINAL_OUTPUT_PDF_TIMEOUT_SECONDS=45

Evidence

config.yml

RUNTIME_OUTPUT_MAX_BYTESapi, agentintegerOptional65536

Maximum size of a single runtime output value written under /nopsai/outputs.

Example

RUNTIME_OUTPUT_MAX_BYTES=65536

Evidence

config.yml

DEFAULT_PIPELINE_TIMEOUTapidurationOptionalNone

Fallback whole-run timeout applied when a pipeline does not declare timeout.

Example

DEFAULT_PIPELINE_TIMEOUT=2h

Evidence

config/config.go

DATA_BACKUP_DIRapipathOptional/data/backups

Directory where product backups are written as gzip-compressed JSON Lines files.

Example

DATA_BACKUP_DIR=/data/backups

Rules
  • The default Compose topology does not mount this path as durable storage.
Evidence

config/config.go

METRICS_REQUIRE_AUTHapibooleanOptionalfalse

Whether GET /metrics requires a bearer token. Public by default for scraper compatibility.

Example

METRICS_REQUIRE_AUTH=true

Security

Enable when the metrics endpoint is reachable outside the cluster network.

Evidence

config/config.go

NOPSAI_REQUIRE_PRODUCTION_GATESapibooleanOptionalfalse

Enforces the production startup gates, refusing to start on an unsafe configuration.

Example

NOPSAI_REQUIRE_PRODUCTION_GATES=true

Security

Turn this on in production so weak transport and default credentials fail startup instead of running.

Evidence

pkg/startupgates/startupgates.go

AUTO_REMOVAL_AGENT_CONTAINERdocker runnerbooleanOptionaltrue

Whether the per-run agent container is removed after the run completes.

Example

AUTO_REMOVAL_AGENT_CONTAINER=false

Evidence

config/config.go

LOG_LEVELall servicesstringOptionalinfo

Minimum severity written to service logs.

Example

LOG_LEVEL=debug

Allowed values

debug, info, warn, error

Evidence

config/config.go

LOG_FORMATall servicesstringOptionaljson

Service log encoding.

Example

LOG_FORMAT=console

Evidence

config/config.go

NOPSAI_ENVIRONMENTall servicesstringOptionallocal

Environment label attached to logs, metrics, and audit metadata.

Example

NOPSAI_ENVIRONMENT=production

Evidence

config/config.go

AUTH_PROVIDER_LOCAL_ENABLEDapibooleanOptionaltrue

Whether local username and password login is offered.

Example

AUTH_PROVIDER_LOCAL_ENABLED=false

Rules
  • Can only be disabled while external authentication is enabled with at least one enabled provider.
  • The protected break-glass administrator remains available regardless.
Evidence

config/config.go

JWT_EXPIRY_MINUTESapiintegerOptionalPlatform default

Lifetime of an issued access token.

Example

JWT_EXPIRY_MINUTES=60

Evidence

config/config.go

REFRESH_TOKEN_TTL_MINUTESapiintegerOptionalPlatform default

Lifetime of a refresh token.

Example

REFRESH_TOKEN_TTL_MINUTES=10080

Evidence

config/config.go

IDLE_TIMEOUT_MINUTESapiintegerOptionalPlatform default

Idle period after which a browser session is ended.

Example

IDLE_TIMEOUT_MINUTES=30

Evidence

config/config.go

RATE_LIMIT_LOGIN_PER_MINUTEapiintegerOptionalPlatform default

Login attempts accepted per minute before requests are throttled.

Example

RATE_LIMIT_LOGIN_PER_MINUTE=10

Security

Together with the lockout settings, this is the brute-force control for local login.

Evidence

config/config.go

LOGIN_LOCKOUT_THRESHOLDapiintegerOptionalPlatform default

Failed attempts within the lockout window before an account is locked.

Example

LOGIN_LOCKOUT_THRESHOLD=5

Evidence

config/config.go

LOGIN_LOCKOUT_WINDOW_MINUTESapiintegerOptionalPlatform default

Window over which failed login attempts are counted.

Example

LOGIN_LOCKOUT_WINDOW_MINUTES=15

Evidence

config/config.go

JWT_ISSUERapistringOptionalPlatform default

Issuer claim written into user and API tokens.

Example

JWT_ISSUER=https://nopsai.example.com

Evidence

config/config.go

JWT_AUDIENCEapistringOptionalPlatform default

Audience claim written into user and API tokens.

Example

JWT_AUDIENCE=nopsai-api

Evidence

config/config.go

JWT_RSA_KEY_PATHapipathOptionalNone

RSA private key path for asymmetric token signing instead of the shared HMAC key.

Example

JWT_RSA_KEY_PATH=/run/secrets/jwt-rsa.pem

Evidence

config/config.go

SERVICE_JWT_ISSUERall servicesstringOptionalPlatform default

Issuer claim for internal service tokens.

Example

SERVICE_JWT_ISSUER=nopsai-internal

Evidence

config/config.go

SERVICE_JWT_AUDIENCEall servicesstringOptionalPlatform default

Audience claim for internal service tokens.

Example

SERVICE_JWT_AUDIENCE=nopsai-services

Evidence

config/config.go

GITHUB_APP_IDapi, git-botstringOptionalNone

GitHub App ID. The long-term source of truth is setting/git-apps/github.yaml.

Example

GITHUB_APP_ID=1234567

Evidence

config/config.go

GITHUB_INSTALLATION_IDapi, git-botstringOptionalNone

Single-installation bootstrap value. Multi-installation setups use the GitOps file instead.

Example

GITHUB_INSTALLATION_ID=87654321

Evidence

config/config.go

GITHUB_PRIVATE_KEY_CREDENTIAL_REFapi, git-botstringOptionalNone

Credential registry reference holding the GitHub App private key.

Example

GITHUB_PRIVATE_KEY_CREDENTIAL_REF=git-apps/github-private-key

Security

Preferred over the legacy inline key and key-path variables.

Evidence

config/config.go

GITHUB_WEBHOOK_CREDENTIAL_REFapi, git-botstringOptionalNone

Credential registry reference holding the GitHub webhook signing secret.

Example

GITHUB_WEBHOOK_CREDENTIAL_REF=git-apps/github-webhook-secret

Evidence

config/config.go

GITHUB_PRIVATE_KEYapi, git-botstringOptionalNone

Legacy inline private key.

Example

GITHUB_PRIVATE_KEY=<legacy inline PEM private key>

Deprecated

Superseded by GITHUB_PRIVATE_KEY_CREDENTIAL_REF

Evidence

config/config.go

GITHUB_PRIVATE_KEY_PATHapi, git-botpathOptionalNone

Legacy private key file path.

Example

GITHUB_PRIVATE_KEY_PATH=/run/secrets/github-app.pem

Deprecated

Superseded by GITHUB_PRIVATE_KEY_CREDENTIAL_REF

Evidence

config/config.go

GITHUB_WEBHOOK_SECRETapi, git-botstringOptionalNone

Legacy inline webhook signing secret.

Example

GITHUB_WEBHOOK_SECRET=<shared secret>

Deprecated

Superseded by GITHUB_WEBHOOK_CREDENTIAL_REF

Evidence

config/config.go

Examples

Helm bootstrap Secret keysyaml
apiVersion: v1
kind: Secret
metadata:
  name: nopsai-bootstrap
stringData:
  database-url: postgres://nopsai:***@nopsai-postgresql:5432/nopsai
  master-key: <32+ byte random value>
  jwt-signing-key: <high-entropy value>
  service-jwt-signing-key: <different high-entropy value>
  aaa-shared-internal-token: <high-entropy value>
  bootstrap-admin-password: <generated value>
  dispatcher-tls-secret: <high-entropy value>
Replace before running
  • Replace every placeholder with a freshly generated value.

How it works

The table below covers every documented variable. Filter by scope to see what a single component actually reads, or use the environment variable index for the same rows grouped for scanning.

Keep bootstrap-only values such as DATABASE_URL, NOPSAI_MASTER_KEY, JWT_SIGNING_KEY, SERVICE_JWT_SIGNING_KEY, AAA_SHARED_INTERNAL_TOKEN, and the bootstrap admin password in deployment secrets or the service environment — not in a configuration repository.

Most product settings move to GitOps once the platform is running. Files under setting/system/ become authoritative for runner topology, authentication, mail, data management, models, MCP, and Agent roles.

Implementation evidence

  • config/config.go

    Config struct with yaml and env tags for every setting.

  • config.yml

    Which values stay bootstrap-only and which move to GitOps.