values.yaml. Use oc in place of kubectl on OpenShift.
Install
Use one namespace per installation. For an existing installation, follow Upgrade or Move from the CLI.1
Download the build
From installation releases, download and verify
2501-<build>.tgz and values.example.yaml.2
Prepare image access
Configure access to 2501’s registry, or copy the build’s images into your registry.
3
Prepare the namespace
Set
NS=ai-2501 in your shell, then run kubectl create namespace "$NS".4
Configure the installation
Write your values and create the required secrets below.
5
Apply and verify
Choose the kubectl, Helm or ArgoCD path below, then complete Check.
Write your values.yaml
Copyvalues.example.yaml to values.yaml. This minimal example uses Kubernetes, a supplied PostgreSQL database and a certificate secret:
Without LLM settings, add the model in Command Center after installation. Identity and LLM settings initialize the first installation; change them in Command Center afterwards. See the configuration reference for all values.
When initializing the first model, set optional
llm.contextLength to its supported context size. Change an existing model in Command Center after installation.
Images from your registry, or no internet access
Copy the images of the build into your registry under the same paths, then point the chart at it, with its login secret if it needs one. The chart keeps naming each image by its digest, which is the same in every registry; the executor images the engine starts come from the same place:Create the secrets
Create each secret once, in the namespace, and never put its value in Git. The pods wait until every secret they read exists.helm install ai2501 ./2501-<build>.tgz -n "$NS" -f values.yaml --dry-run=client prints the commands for your values, installing nothing; these are for the defaults:
commandCenter.host when using tls.mode: secret. Your secret manager can create the same names and keys instead. Pods wait for missing secrets.
The default names and keys are:
Use the printed commands for the chosen values if these defaults change. See the secret reference for other optional secrets.
Apply
Render, review and apply the complete file. The same pruning flags make removed resources visible in the diff:With Helm or ArgoCD
The chart is also available atoci://ghcr.io/2501-ai/charts/2501. Verify the chart before installing it.
- Helm
- ArgoCD
Use the same namespace, values and pre-created secrets:To install the verified build from the registry instead:
Your site’s values
Apply changes throughvalues.yaml so they survive upgrades. Expand the relevant recipe; the configuration reference lists the remaining options.
HTTPS to the engine
HTTPS to the engine
The engine serves plain HTTP, reached only inside the cluster through its Service. To serve it over HTTPS only, create its certificate once. It must name Command Center trusts this certificate. Restart both services after renewal.
ai-2501-engine, ai-2501-engine.<namespace>.svc and ai-2501-engine.<namespace>.svc.cluster.local (<stackName>-engine with another stackName): one your CA issues, or a self-signed one:Your PostgreSQL
Your PostgreSQL
Your Elasticsearch
Your Elasticsearch
Create Trust a corporate certificate with
es-credentials with ELASTICSEARCH_USERNAME and ELASTICSEARCH_PASSWORD:caBundle. For an existing installation, also enable Elasticsearch in Command Center as described in Operations.Storage and sizing
Storage and sizing
For the volumes of the PostgreSQL and Elasticsearch 2501 provides:Set
storageClass, database.size and elasticsearch.size before creating volumes. Bound claims cannot change storage class or shrink. Choose sizing.preset for the installation’s capacity; reserve additional namespace capacity for task and plugin containers.Executors in another namespace
To give executor and hosted MCP server pods their own quotas and network rules, create the namespace, then:executors.namespace. The chart places executor permissions and the hosted MCP policy there. With this setting, rendered objects name their namespaces: omit -n "$NS" from the file’s diff and apply commands.
Additional installation settings
Put non-secret settings inengine.extraEnv. For secret values, create an engine-extra-env Secret and restart the engine after changing it. For example, MCP_OAUTH_ALLOW_PRIVATE_PROVIDERS: "true" allows OAuth identity providers on private addresses, still over HTTPS.
Put them in engine.extraEnv in your values.yaml, which works on Docker Swarm too, or, for a secret value, in a Secret named engine-extra-env in the namespace. The engine reads that Secret when it starts and the chart never writes it. Create or change it, then restart the engine:
Check
https://<your host>.
The bootstrap Job has backoffLimit: 10. After it reaches that limit, fix the cause shown in the logs and delete the failed Job:
Command Center keeps previous pods serving during the rollout until new pods become ready. The
/ready endpoint checks the database once at startup to confirm the required migrations. The engine is replaced during upgrades, so allow running work to finish first.
The chart gives the engine the engine-executor service account and a Role in the executor namespace. The Role grants these permissions:
At startup, the engine checks
pods create/get/list/delete, pods/attach create/get and secrets create permissions. Missing permissions stop startup. If the cluster does not answer within 10 seconds, the engine logs a warning and starts without the check. A timed-out check is not proof of access. In the executor namespace, verify pod access, pods/attach create/get and Secret creation:
kube when it runs in Kubernetes and docker otherwise. Set EXECUTOR_MCP_BACKEND to kube or docker to force a backend. Executor MCP handshakes allow 20 seconds by default (MCP_HANDSHAKE_TIMEOUT_MS=20000), and satellite silence allows 40 seconds (SATELLITE_SILENCE_MS). An executor that misses its handshake deadline gets one retry in a fresh pod. Investigate image pulls, scheduling and connectivity before raising these limits. Engine termination has a 150-second grace period; finish running work before upgrades.
Hosted MCP servers
Hosted plugins run as non-root pods withRuntimeDefault seccomp and all Linux capabilities dropped. Their security settings meet the restricted Pod Security Standard. Service account token mounting is disabled. The chart supplies namespace-scoped permissions and a policy allowing DNS and public destinations, while blocking private and link-local destinations.
Your network plugin must enforce NetworkPolicy. Add an explicit policy exception for required internal services or NodeLocal DNSCache. Review the network plugin’s startup enforcement before using untrusted images. On EKS with the Amazon VPC CNI, set NETWORK_POLICY_ENFORCING_MODE=strict to enforce policy from pod startup. Ensure image pull secrets and namespace quotas cover these pods.
Target hosted MCP exceptions with app.kubernetes.io/managed-by: 2501-mcp-hosted. Allow only the required destination and ports. For NodeLocal DNSCache, use your actual DNS address, including a link-local address when configured; the default private-address block also blocks it.
Each hosted pod requests 0.25 CPU, 512 MiB memory and 64 MiB ephemeral storage; its limits are 0.5 CPU, 512 MiB and 256 MiB. Each engine runs at most 32 hosted servers. The image must work as UID 65532, or the arbitrary UID assigned by OpenShift. Reserve quota for these pods and inspect admission errors such as exceeded quota when startup fails.
Set these overrides under engine.extraEnv in values.yaml when needed:
Centrals
For local Central execution, prepare a dedicated namespace with restricted pod security, image access, scoped pod/attach permissions and network policies. Setengine.extraEnv.CENTRAL_LOCAL_K8S_NAMESPACE to that namespace. The chart does not prepare this separate Central environment for you.
Leave Cluster (optional) at No cluster (default) to use this local environment, or select a registered cluster. Run the Central’s dry run before assigning work; a successful check does not validate task credentials.
Prepare local Central execution
Prepare local Central execution
This example uses The service account also needs permission to read its own pod in the installation namespace. Check this especially if executors use a separate namespace. Allow only the internal destinations your Central tools require; the example permits cluster DNS and public destinations.
ai-2501 for the installation and central for task containers. Replace ai-2501 in the binding if your installation uses another namespace. Save the following as central.yaml:1
Apply isolation and permissions
Run
kubectl -n central apply -f central.yaml. Confirm your network plugin enforces the policy; other policies must not grant broader access to these pods.2
Prepare registry access
Create the configured executor image pull secret in
central too. It must allow both the release image and your Central images.3
Select the namespace
Add the values below and reapply the chart. Keep the Central manifest’s namespace unset to use this default.
4
Verify execution
Run the Central’s Test in Dry run and confirm command success and container removal.

