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

Runners and the dispatcher

How runners register, how work is routed to them, and what happens when one disconnects or is ejected.

ReferenceAdministratorOperator

Key points

  • Runner registration is trusted by service JWT and TLS material plus the ejected-runner blocklist.
  • Routing tables use the effective view: paused or unreachable runner IDs stay visible for diagnosis, but only reachable dispatch-enabled runners are treated as dispatchable targets.
  • An ordinary network disconnect keeps the registration available for reconnect. A reconnected runner keeps last_disconnected_at and shows as recovered or degraded during the recovery window.
  • Deliberate removal disconnects the runner, clears dispatcher status, and adds its ID to ejected_runner_ids.
  • An explicit empty runner_scopes value means all scopes.
  • Generated installs preserve the friendly name as runner_name and use a unique suffixed RUNNER_ID for dispatcher identity.

Field reference

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

Examples

Generate a Docker runner install commandbash
curl -s "$NOPSAI_URL/v1/system/dispatcher/runner-bootstrap-command?scopes=platform/production" \
  -H "Authorization: Bearer $NOPSAI_TOKEN"
Result

A one-line install command carrying the runner identity, scopes, and dispatcher connection material.

How it works

The System dispatcher workspace separates compact overview metrics, a runtime-filtered table-first fleet view, route editing with the effective routing table, and install command generation. Runner detail appears below the fleet table only after an operator selects a runner.

The GitOps-owned configured route map and the live effective routing view are different things. The configured map is desired state; the effective view is derived from registered runner scopes and runtime status.

Replacing a control plane while keeping the old SERVICE_JWT_SIGNING_KEY and DISPATCHER_TLS_SECRET lets old runner definitions authenticate again unless their IDs are carried forward in ejected_runner_ids. Rotate those secrets before exposing a fresh dispatcher when old runners must not join.

Implementation evidence

  • services/dispatcher/internal/app/app.go

    Dispatcher listen address and registration handling.

  • services/nopsai/routes.go

    Dispatcher management and install-generation routes.