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

Add a Docker runner

Generate a one-time install command from the control plane and start a runner container on the same Docker network.

TutorialNew userAdministratorOperator

What you will do

  • The control plane generates the install. You never assemble runner identity, service tokens, or TLS material by hand.
  • GET /v1/system/dispatcher/runner-bootstrap-command returns a one-time command; its token expires in 10 minutes and is consumed by the first successful download.
  • Query parameters choose identity and placement: runner_id, runner_name, runner_scopes, runner_capacity, runner_network_mode (bridge, host, or auto), and runner_image.
  • In bridge mode the generated docker run joins the network named by DOCKER_NETWORK_NAME, which is nopsai-net for the local stack.
  • The container runs with --restart always, mounts /var/run/docker.sock, and carries RUNNER_ID, RUNNER_SCOPES, RUNNER_CAPACITY, DISPATCHER_GRPC_ADDRESS, NOPSAI_API_URL, and the service JWT and TLS values as environment.
  • An explicitly empty runner_scopes value means all scopes; omitting the parameter falls back to the configured default, then to prod.
  • The install script stops early when the runner image cannot be pulled, or when the image architecture does not match the Docker host.

Before you start

Control plane
A running API that has completed first-install setupcurl -s localhost:8080/healthz
Token
An administrator token in NOPSAI_TOKENcurl -s -H "Authorization: Bearer $NOPSAI_TOKEN" localhost:8080/v1/auth/me
Runner host
A host with Docker and access to /var/run/docker.sockdocker info --format "{{.Architecture}}"
Runner image
The runner image tag available locally or pullable on that hostdocker image inspect ghcr.io/nopsai/nopsai-docker-runner:dev >/dev/null && echo present

Steps

  1. 01

    Generate the install command

    Ask the control plane for a bootstrap command for the runner you want. Scopes decide which work this runner may be given; capacity decides how many runs it accepts at once.

    Important
    • The command expires 10 minutes after it is generated and is consumed by the first successful download. Generate a new one per host.
    Request a bootstrap commandbash
    curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" \
      "http://localhost:8080/v1/system/dispatcher/runner-bootstrap-command?runner_id=runner-local-1&runner_scopes=prod&runner_capacity=2&runner_network_mode=bridge" \
      | jq -r .bootstrap_command
    Result

    A single-line command that downloads a one-time install script with a bearer token and runs it.

    Replace before running
    • runner_id and runner_scopes should match how you intend to route work.
  2. 02

    Run it on the runner host

    Paste the generated command on the Docker host that will execute pipeline work. For the local stack, that is the same workstation running Compose.

    Expected result
    • The script prints the runner ID, dispatcher address, and network mode, pulls the runner image if it is missing, starts the container, and tails its first log lines.
    Verify
    • docker ps --filter "label=nopsai.io/runner-id" --format "{{.Names}} {{.Status}}"
  3. 03

    Confirm the runner is on the same network

    A bridge-mode runner must sit on nopsai-net to reach the dispatcher by name. This is the failure most often mistaken for a credentials problem.

    List attached containersbash
    docker network inspect nopsai-net --format '{{range .Containers}}{{.Name}}\n{{end}}'
    Verify
    • The runner container appears in the list alongside the control-plane containers.
  4. 04

    Confirm registration with the dispatcher

    Registration is what makes the runner dispatchable. Check it from the API or from System, then the dispatcher workspace.

    Read dispatcher statusbash
    curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" http://localhost:8080/v1/system/dispatcher | jq
    Expected result
    • The runner appears with its ID, scopes, and capacity, reachable and dispatch-enabled.
    Verify
    • If it does not appear, follow the container logs: docker logs -f <runner container>.

How it works

Prefer the bootstrap command over hand-written Compose for a first runner: it carries the dispatcher address, service JWT settings, and TLS material that the control plane currently considers correct, and it fails loudly when one of them is not configured.

GET /v1/system/dispatcher/runner-compose returns the same install as a Compose service fragment when you would rather keep the runner in a Compose file than as a standalone container.

When the dispatcher address in the response is not reachable from the runner host, fix the address before installing. The generated command reports the address it will use, and the response carries warnings when the control plane had to derive it from the request.

Host network mode exists for the case where the host can reach the dispatcher but bridge containers cannot. It is the right answer on some VM setups and the wrong answer on a normal local install.

Limits

Current behavior
  • One bootstrap command installs one runner. A second host needs its own command and its own runner ID.

Implementation evidence

  • services/nopsai/internal/runnerinstall/docker.go

    Install spec, generated docker run, network placement, and one-time token behavior.

  • services/nopsai/routes.go

    Dispatcher install and status routes.