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

Production hardening checklist

What to change before a deployment stops being a local evaluation.

How-toAdministratorSecurity

Key points

  • Set NOPSAI_REQUIRE_PRODUCTION_GATES=true so an unsafe configuration fails startup instead of running.
  • Set DISPATCHER_TLS_MODE to mtls or tls. Never disabled.
  • Generate distinct high-entropy values for JWT_SIGNING_KEY and SERVICE_JWT_SIGNING_KEY.
  • Replace every Compose fallback secret, and leave NOPSAI_BOOTSTRAP_ADMIN_ALLOW_DEFAULT_PASSWORD false.
  • Keep NOPSAI_BOOTSTRAP_ADMIN_MUST_CHANGE_PASSWORD true so the provisioned password rotates at first login.
  • Point SYSTEM_LOGS_DOCKER_HOST at the restricted socket proxy, never the raw Docker socket.
  • Set METRICS_REQUIRE_AUTH=true when /metrics is reachable outside the cluster network.
  • Mount DATA_BACKUP_DIR as durable storage — the default Compose topology does not.

Before you start

Environment
A non-Compose deployment: a release bundle or the Helm chart
Secret store
A place to hold the platform secrets that is not a local .env
Administrator access
Enough access to change system settings and identity configuration

Steps

  1. 01

    Replace every bootstrap value

    The values that make a local install convenient are the ones that make a shared install dangerous. Rotate them all before anyone else connects.

    Important
    • JWT_SIGNING_KEY and SERVICE_JWT_SIGNING_KEY must differ, or a user token can be replayed as a service token.
    Values that must be install-specificbash
    NOPSAI_MASTER_KEY
    JWT_SIGNING_KEY
    SERVICE_JWT_SIGNING_KEY
    AAA_SHARED_INTERNAL_TOKEN
    POSTGRES_PASSWORD
    NOPSAI_BOOTSTRAP_ADMIN_PASSWORD
  2. 02

    Close the network surface

    Only the Git webhook ingress needs to be reachable from outside. The API, dispatcher, and database do not.

    Verify
    • From outside the cluster or host, the dispatcher gRPC port and PostgreSQL port do not answer.
  3. 03

    Move identity off local accounts

    Configure an identity provider and reduce local accounts to break-glass. Provider ID, issuer, and subject are the identity; email is metadata.

    Verify
    • Signing in through the provider produces a session with the expected roles.
  4. 04

    Confirm the startup gates pass

    Production startup gates refuse to start a service that is still carrying development defaults. A clean start is the check.

    Check platform identity and healthbash
    curl -s "$NOPSAI_URL/version" | jq
    curl -s "$NOPSAI_URL/healthz"
    Verify
    • Every service starts, /healthz is ready, and no gate error appears in the system logs.

How it works

Rotate SERVICE_JWT_SIGNING_KEY and DISPATCHER_TLS_SECRET together before exposing a replacement dispatcher. Keeping the old values lets retired runner definitions authenticate again unless their IDs are carried in ejected_runner_ids.

Keep step pods on the no-RBAC workload service account. Merging it with the runner service account gives workload code access to the Kubernetes API.

Review egress: Docker step containers default to bridge networking. Use DOCKER_NETWORK_NAME=none or a dedicated network when workloads should not reach the internet.

Prefer credential references over the legacy inline secret variables for GitHub App keys, webhook secrets, LLM keys, and MCP tokens.

Implementation evidence

  • doc/enterprise-gates.md

    Production startup gates and verification commands.

  • pkg/startupgates/startupgates.go

    What the gates actually check.