Skip to main content

Kubernetes (Helm)

The rikoo Helm chart deploys the api, the worker, the parsing sidecar and the tool sandbox on a cluster, with PostgreSQL, Redis and object storage either bundled or pointed at managed services. Schema migrations run as a Job at install time and before every upgrade.

The chart lives in a public repository, Rikoo-app/rikoo-k8s, under the MIT license. The container images it deploys are in a private registry: you need the registry address and credentials from the Rikoo team (see Overview).

Prerequisites​

  • Kubernetes 1.27 or later, and Helm 3.14 or later.
  • A network plugin that enforces NetworkPolicies, such as Cilium or Calico. The sandbox relies on them to cut its network; see Sandbox isolation.
  • A default StorageClass, if you keep the bundled stores: they claim 20 GiB for PostgreSQL, 8 GiB for Redis and 50 GiB for MinIO.
  • For a public address: an ingress controller and cert-manager, or equivalents.
  • Capacity: with the default values, the pods request about 2.2 vCPU and 4 GiB of memory, with memory limits adding up to about 11 GiB.

Install​

The steps follow the examples/minimal-installation folder of the chart repository: every store bundled, all credentials in one Secret created beforehand.

1. Get the chart​

git clone https://github.com/Rikoo-app/rikoo-k8s.git
cd rikoo-k8s/examples/minimal-installation
helm dependency update ../../charts/rikoo

2. Create the namespace and the registry secret​

kubectl create namespace rikoo
kubectl -n rikoo create secret docker-registry rikoo-registry \
--docker-server=<registry> --docker-username=<user> --docker-password=<token>

3. Create the application secret​

Generate the vault's sealing key pair. The chart never generates it, and losing the private key makes every stored secret unreadable.

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out sealing.private
openssl pkey -in sealing.private -pubout -out sealing.public

Then edit secret.yaml and replace every placeholder:

KeyValue
widget-signing-key, totp-key, sandbox-token-secretRandom strings of at least 32 characters, for example from openssl rand -hex 24
sealing.pub, sealing.keyThe contents of sealing.public and sealing.private
POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DBCredentials of the bundled PostgreSQL
rootUser, rootPasswordCredentials of the bundled MinIO
kubectl -n rikoo apply -f secret.yaml

In a GitOps pipeline, produce this Secret with an external secrets operator rather than committing it.

4. Install the chart​

helm install rikoo ../../charts/rikoo -n rikoo -f values.yaml \
--set rikoo.image.registry=<registry>/<namespace> \
--set rikoo.image.tag=v0.2.0

Both rikoo.image.registry and rikoo.image.tag are required; the chart refuses to render without them.

5. Check​

kubectl -n rikoo get pods
kubectl -n rikoo port-forward svc/rikoo-api 3000:http
curl -fsS http://localhost:3000/api/v1/health

Open http://localhost:3000 and create the first account: while no organization exists, it may register and becomes Owner of the first organization.

Expose it​

The with-ingress.yaml overlay of the same folder adds an ingress with TLS, assuming ingress-nginx, cert-manager and a ClusterIssuer named letsencrypt. Replace its example hosts, rikoo.example.com and s3.rikoo.example.com, with yours. The overlay also:

  • sets rikoo.publicUrl to the public address and rikoo.trustProxyHops to 1, since the ingress controller is one proxy in front of the api;
  • gives the bundled MinIO a public route, because browsers upload attachments straight to object storage at the address in s3.browserEndpoint;
  • turns proxy buffering off and raises timeouts to one hour: answers stream as server-sent events. With another ingress controller, apply the same settings.
helm upgrade --install rikoo ../../charts/rikoo -n rikoo \
-f values.yaml -f with-ingress.yaml \
--set rikoo.image.registry=<registry>/<namespace> --set rikoo.image.tag=v0.2.0

Use managed stores​

Each bundled store can be replaced by a managed service. The examples/external-components folder has one overlay per store.

StoreValuesRequirements
PostgreSQLpostgresql.deploy: false, then postgresql.url, or host, port and auth.*The vector (pgvector) and citext extensions. The migrating role must be allowed to create extensions and roles.
Redisredis.deploy: false, then redis.url, or host, port and databasemaxmemory-policy noeviction: evicting a key loses queued jobs.
Object storages3.deploy: false, then endpoint, browserEndpoint, region, bucket, forcePathStyle and the key pairAny S3-compatible service.

To make PostgreSQL row-level security filter tenant queries, give the application a second, non-owner role through postgresql.appUrl. Without it, tenant queries use the owner connection.

Configure​

The chart sets what it can from its own values. Any other product setting goes into a checked map: rikoo.settings (read by the api and the worker), rikoo.api.settings or rikoo.worker.settings. The chart checks each name against the list of variables the product reads, and refuses to render a name the product does not know, a secret written in clear, or a value in the wrong format.

The complete list of variables, with their format and the service that reads them, is in charts/rikoo/VARIABLES.md.

Enterprise edition​

Deploy Enterprise images (ask for the tag with your license), then store the license in a Secret and point rikoo.license.deploymentLicense at it:

kubectl -n rikoo create secret generic rikoo-license \
--from-literal=RIKOO_DEPLOYMENT_LICENSE='<license>'
rikoo:
license:
deploymentLicense:
secretKeyRef:
name: rikoo-license
key: RIKOO_DEPLOYMENT_LICENSE

See Enterprise license for what the license unlocks.

Sandbox isolation​

The embedded tools run in the mcp-sandbox pods, confined by three NetworkPolicies: the workspace reaches only the browser, the browser leaves only through the mcp-egress proxy, which applies the same anti-SSRF guard as the worker, and the api reaches none of them. The workspace container drops every capability except the four it needs to switch to the conversation's system identity (SETUID, SETGID, CHOWN, DAC_OVERRIDE), with a read-only root filesystem and the RuntimeDefault seccomp profile.

Policies are only enforced by a network plugin that supports them. On a cluster without one, the sandbox workspace can reach the network: install such a plugin, or turn the sandbox off with rikoo.sandbox.enabled: false. Runs keep working without it; the embedded tools return an error.

The Docker Compose stack adds a dedicated seccomp profile and supports gVisor; the chart does not offer either yet.

Upgrade​

Back up the database, then run the same command with the new tag:

helm upgrade --install rikoo ../../charts/rikoo -n rikoo -f values.yaml \
--set rikoo.image.registry=<registry>/<namespace> --set rikoo.image.tag=<new tag>

The migrations Job runs before the new pods. If it fails, the release does not roll out: read kubectl -n rikoo logs job/rikoo-migrations. helm rollback returns to the previous images but does not reverse migrations; restore the database backup when a release has to be undone.

Uninstall​

helm uninstall rikoo -n rikoo

The chart keeps what cannot be recreated: its Secrets are marked helm.sh/resource-policy: keep, and the bundled PostgreSQL volume is retained. Delete them by hand, with the namespace, only when you mean to lose the data.

Try it on a laptop​

The examples/local-kind folder runs the chart on a local kind cluster, with images built from the Rikoo source repository. Its README walks through the steps and includes a check that the sandbox network is really cut.