Skip to content

Production Deployment (multi-node)

Neutree Agent Platform — Self-HostInstall the platform on your own Kubernetes cluster — pulling images from a public registry, or fully air-gapped from your own

What one install gives you

The same ./install.sh brings up the platform connected (images pulled from a public registry) or fully air-gapped (from your own registry) — the Install tab covers both. What it installs:

Core platform (always installed)

  • Control plane — agent management, scheduling, user and workspace management
  • Channel gateway — the entry point for external events (webhooks, Slack, etc.) to reach agents
  • Data layer — PostgreSQL (CloudNativePG) + shared NFS
  • Agent workspace runtime — one pod per workspace runs the agent; agents can @ each other, share files, and share a memory store

Optional modules (off by default)

  • Code Sandbox — lets agents run code and serve temporary web previews. Powered by the third-party OpenSandbox, which you install yourself; the platform points at it via OPENSANDBOX_URL
  • Agent Browser — self-hosted browser as a service: agents drive a real browser while users watch live over WebRTC. Ships a bundled TURN relay (coturn) and a published headful Chromium image
  • LDAP — let users sign in with their LDAP account

Prerequisites

Infrastructure

ResourceRequirementNotes
Kubernetesv1.28+ (multi-node), or a single k3s node (single-node profile)3+ workers recommended
Worker nodes4 vCPU / 8GB RAM minimumAgent pods are created per workspace dynamically
Container registryA registry every node can pull from — a public one (connected) or your own private registry (air-gapped)Set REGISTRY to it; fill REGISTRY_USERNAME / REGISTRY_PASSWORD when it needs a login
RWX shared storageA CSI that supports ReadWriteMany (NFS is the most common)Backs the AFS shared directory, 500Gi by default
RWO volume storageAny CSI that can run PostgreSQL (Ceph RBD, vSAN, etc.; the same NFS also works)PostgreSQL data volumes + agent workspace container disks

Network

ItemRequirement
Node IPAt least one worker IP reachable by users (NodePort uses it)
NodePortFree ports in 30000–32767: NAP_NODE_PORT, plus BROWSER_NODE_PORT / SANDBOX_NODE_PORT when the corresponding optional module is enabled
TURN portsWhen the Agent Browser's TURN relay is enabled: open 3478/tcp+udp and 49152-49252/udp on the coturn node
Storage reachabilityAll nodes can mount the two storage classes above (NFS / block-storage CSI, etc.)
Registry reachabilityAll nodes can pull images from the registry above (a public one, or your private registry)

LLM API

The platform does not bundle any model. Depending on the agent types you enable, you must provide protocol-compatible API endpoints:

Agent typeAPI protocol required
CodexOpenAI Responses API (note: not Chat Completions)
Claude CodeAnthropic API
GooseOpenAI Chat Completions API

If your existing model service only supports the OpenAI Chat Completions API, Goose agents can use it directly. To also run Claude Code-style agents against it, put a translating proxy in front that converts the OpenAI Chat protocol to the Anthropic protocol.

kubeconfig permissions

Installation requires cluster-admininstall.sh touches resources that a namespace-scoped admin cannot (CRDs, webhooks, ClusterRoles, StorageClasses, etc.). You can revoke it immediately after install; at steady state the control plane authenticates via its own in-cluster ServiceAccount with tightly scoped permissions (normal read/write within the namespace + cluster-scoped get/list on nodes only).

The operator's kubeconfig is never mounted into any platform pod. If a temporary cluster-admin is not acceptable, here is an equivalent minimal ClusterRole.

Equivalent minimal ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nap-installer
rules:
  - apiGroups: [apiextensions.k8s.io]
    resources: [customresourcedefinitions]
    verbs: [get, list, watch, create, update, patch, delete]
  - apiGroups: [admissionregistration.k8s.io]
    resources: [validatingwebhookconfigurations, mutatingwebhookconfigurations]
    verbs: [get, list, watch, create, update, patch, delete]
  - apiGroups: [""]
    resources: [namespaces]
    verbs: [get, list, create, update, patch]
  - apiGroups: [rbac.authorization.k8s.io]
    resources: [clusterroles, clusterrolebindings, roles, rolebindings]
    verbs: [get, list, watch, create, update, patch, delete]
  - apiGroups: [storage.k8s.io]
    resources: [storageclasses]
    verbs: [get, list, create, update, patch]
  - apiGroups: [postgresql.cnpg.io]
    resources: ["*"]
    verbs: ["*"]
  - apiGroups: [opensandbox.alibaba.com]
    resources: ["*"]
    verbs: ["*"]
  - apiGroups: ["", apps, batch, networking.k8s.io, policy]
    resources: ["*"]
    verbs: ["*"]
  - apiGroups: [""]
    resources: [nodes]
    verbs: [get, list, watch]

This is still close to cluster-admin in practice (*/* on the core/apps/batch groups), but spelling out the resources makes a security review easier.

Once the prerequisites are in place: