Skip to main content
Deploy the 4MINDS platform to your own Kubernetes cluster with a single helm install. The umbrella chart carries every service and datastore, and its own hooks do all in-cluster orchestration (OpenBao init/unseal, DB migrations, Kafka topics), so no external installer binary is required. You configure the deployment through one values file: copy the values template at the bottom of this page to a file of your choice (this guide calls it my-values.yaml, but the name is arbitrary) and fill in your hostname, inference endpoints, and options.
The prerequisite commands below use Amazon EKS as the worked example (eksctl, EBS CSI, IRSA). On another Kubernetes distribution, substitute the equivalent steps: a default StorageClass, a CSI driver, an ingress controller, and (for KMS auto-unseal) a cloud KMS key + workload identity.

What you’ll do

  1. Prerequisites (Steps 0-7): confirm your IAM permissions (Step 0), then prepare the cluster and platform plumbing the chart does not create (cluster/OIDC, storage, ingress, namespace, TLS, image pull, and, only for production KMS unseal, a KMS key + IAM role).
  2. Configure: copy the values template from this page into your own values file and fill it in.
  3. Install: log in to the Marketplace ECR, pull the chart, and helm install with your values.
  4. Verify: confirm pods are Running and the UI answers.
Sections after that cover upgrades, uninstall, and troubleshooting.

Before you start

Required CLI tools. Install any that are missing before you begin (each link points to its official install guide):
  • aws: the AWS CLI. Authenticate it to the account that owns the cluster.
  • kubectl: the Kubernetes CLI.
  • helm: v3.8+ (OCI registry support required).
  • eksctl: only for the Amazon EKS example steps.
  • openssl: only if you want a self-signed test cert.
Verify each is on your PATH with <tool> version (e.g. aws --version, helm version) before continuing. Set these environment variables. Every command below references them:
Then confirm none are empty:
Copy-paste tip. If a multi-line command (with a trailing \) breaks in your shell, paste it as a single line instead.

Prerequisites

Step 0: IAM permissions for the deployer

What this does: confirms the IAM identity (user or role) you run these steps as has every permission the prerequisites need, so you never hit an AccessDenied mid-deployment. Sort this out before anything else. Across the steps below you (or eksctl on your behalf) create an EKS cluster, CloudFormation stacks, IAM roles/policies, an OIDC provider, EC2/networking resources, an EBS CSI addon, a KMS key, and you authenticate to the Marketplace ECR. That is a broad, privileged set of actions. Simplest path (recommended for a one-time deploy): run as an identity with the AWS-managed policies below attached. This is the least-friction option and is what most first deployments use:
eksctl drives everything through CloudFormation, which in turn creates IAM roles. There is no smaller managed policy that covers cluster creation end-to-end. This is why broad IAM/CloudFormation access is needed for the initial provisioning.
Least-privilege path (locked-down orgs): if org policy forbids the broad managed policies, attach a custom policy granting exactly these actions. Scope Resource down to your account/cluster where you can:
Marketplace subscription is separate from IAM. Before pulling the chart, the account must be subscribed to the 4MINDS product on AWS Marketplace. Managing that subscription needs aws-marketplace:Subscribe / aws-marketplace:ViewSubscriptions (or Marketplace console access) — an account/billing permission, not something the deploy identity uses at runtime.
kubectl / helm permissions are Kubernetes RBAC, not IAM. As the cluster creator you are automatically system:masters (cluster-admin), so every kubectl and helm step in this guide just works. If someone else deploys into a cluster they did not create, grant them cluster-admin (or map their IAM identity in the aws-auth configmap / an EKS access entry).

Step 1: EKS cluster with OIDC

What this does: creates (or reuses) the Kubernetes cluster. --with-oidc is the only hard requirement; IRSA (used for KMS auto-unseal and the EBS driver) needs it. Skip the create cluster command if you already have a cluster; use your own version / instance type / node count.
If the cluster already exists, just make sure the OIDC provider is associated:
Sizing (guidance, not a requirement). The full platform runs many services plus stateful datastores. A reasonable starting point for the application tier is 3 × m5.2xlarge (8 vCPU / 32 GiB each); scale to your workload.Inference is separate. This chart does NOT run models; it points at OpenAI-compatible endpoints you set in my-values.yaml (llm.*, mlai.embedding, symi-gateway.config, wren-ai). Those can be a managed service or GPU nodes in this same cluster (add a g5/p4 node group and point the endpoints at the in-cluster services).
Models and GPU sizing. The endpoints above serve the models the platform uses. A typical deployment runs these: GPU memory is dominated by the two largest models: GPT-OSS-120B (a sparse MoE model, ~63 GB of weights) and Qwen 3.6 35B FP8. The rest are small by comparison. To serve ~100 concurrent users, plan for 2 × NVIDIA RTX PRO 6000 (96 GB each) for inference without fine-tuning. If fine-tuning workloads must run alongside inference, the requirement increases to 3 × 96 GB RTX PRO 6000.

Step 2: Default StorageClass + EBS CSI driver

What this does: gives stateful services (PostgreSQL, Redis, Kafka, MinIO, Qdrant, OpenBao, mlai) a default StorageClass backed by a working CSI driver. OpenBao persists its vault data on a 2Gi PVC, so this is required even for seal.mode: lab: without persistence, a pod restart re-initializes the vault and drops the seeded secrets.

Step 3: ingress-nginx controller

What this does: installs the NGINX ingress controller. The chart creates an Ingress of class nginx; the controller itself is a prerequisite.

Step 4: Namespace

What this does: creates the namespace everything installs into.

Step 5: TLS secret for your hostname

What this does: provides the certificate the Ingress uses to terminate TLS. The Ingress reads the secret named by frontend-backend.ingress.tlsSecretName (default frontend-tls). The host and TLS entry derive from global.hostname automatically, so you only create the secret here. Option A: you already have a cert (ACM-issued, Let’s Encrypt, etc.):
Option B: self-signed (testing/PoC only; browsers will warn):
Trust the self-signed cert on every machine that opens the UI, otherwise the app loads but is unusable.The 4MINDS frontend opens a WebSocket (wss://$HOSTNAME_FQDN) to the backend. Unlike a normal page load, most browsers will not carry a page-level “proceed anyway” exception over to a WebSocket: the wss:// TLS handshake to an untrusted cert simply fails and the connection is dropped, so the UI renders but stays disconnected (live updates, chat, and streaming never arrive).Clicking Advanced → Proceed on the page warning is not reliable across browsers (Safari, in particular, does not reuse that exception for wss://). The only dependable fix is to add the cert to the operating system’s trust store on each client machine, then fully restart the browser.
Add tls.crt to the OS trust store on each client machine (restart the browser afterwards): macOS: add to the System keychain and mark it trusted for SSL:
Or via Keychain Access.app: drag tls.crt into the System keychain, double-click it, expand Trust, and set When using this certificate: Always Trust. Linux (Debian/Ubuntu):
On RHEL/Fedora:
Windows (PowerShell as Administrator):
Firefox keeps its own trust store. Even after the OS import, add the cert under Settings → Privacy & Security → View Certificates → Authorities → Import.
For anything beyond a quick PoC, use a real/trusted certificate (Option A: ACM or Let’s Encrypt). With a trusted cert, no client-side trust step is needed at all and wss:// works out of the box.
Using a different secret name? Set frontend-backend.ingress.tlsSecretName in my-values.yaml to match.

Step 6: Image pull (usually nothing to do)

What this does: lets the cluster pull the images. On AWS Marketplace the images live in the Marketplace ECR and your EKS node IAM role pulls them automatically (attach AmazonEC2ContainerRegistryReadOnly to the node role if it isn’t already). In that case leave global.imagePullSecrets: []. Only if you mirror the images into your own private registry do you create a pull secret and list its name under global.imagePullSecrets.

Step 7: OpenBao KMS auto-unseal (production only)

What this does: sets up AWS KMS + an IRSA role so OpenBao auto-unseals without in-cluster keys. Skip this entire step if you use seal.mode: lab (Shamir keys stored in-cluster, fine for test/PoC).
Then set these in my-values.yaml. The chart binds roleArn onto the OpenBao ServiceAccount as eks.amazonaws.com/role-arn automatically (no manual annotation, survives helm upgrade):
Azure / GCP: set provider: azure (tenantId/vaultName/keyName) or provider: gcp (projectId/locationId/keyRing/cryptoKey) and bind the pod identity via openbao.serviceAccount.annotations (Workload Identity).

Prerequisites summary

Configure

What this does: creates your deployment’s values file. Copy the values template from the bottom of this page into a file (this guide calls it my-values.yaml, but the name is arbitrary) and fill in the required fields: hostname, email, LLM/embedding endpoints, SYMI, wren-ai, seal mode, and any SSO/integrations you use. Everything else has a sensible default. You don’t need the chart on disk yet; you pull it in the Install step. Just save your filled-in values file somewhere and pass its path to helm install with -f.
Use the values template on this page, not the values-customer-template.yaml bundled inside the pulled chart. The bundled file is out of date; the template on this page is the current, supported one.

(Optional) External S3 instead of the bundled MinIO

By default object storage is the in-cluster MinIO and you set nothing. To use AWS S3 (or any S3-compatible endpoint) instead, add to my-values.yaml:
Leave storage.endpoint / secrets.s3* empty to keep the bundled MinIO. If you also set OAuth client secrets, put the S3 keys under the same secrets: block; a second secrets: key silently overrides the first (YAML has no merge). For Azure Blob, set storage.useAzure: "true" and secrets.azureStorageAccountKey in that same block.

Install

What this does: pulls the chart from the AWS Marketplace ECR and deploys the platform with your values. The chart’s hooks then run automatically (OpenBao init+unseal, backend-secret seeding, Kafka topics, the mlai schema migration). No manual steps. 1. Log in to the Marketplace ECR. After subscribing to the product on AWS Marketplace, authenticate Helm to the Marketplace registry:
The Marketplace ECR host is fixed at 709825985650.dkr.ecr.us-east-1.amazonaws.com regardless of $REGION — always use us-east-1 in that URL. --region "$REGION" above only tells the AWS CLI where to fetch the auth token.
2. Pull and unpack the chart. Download the chart into an empty directory and extract it:
3. Install with your values. Point -f at the my-values.yaml you filled in during Configure (use its full path if it lives outside this directory). The namespace was already created in Step 4, so this uses --namespace (not --create-namespace):
The --set global.awsmpServiceAccountName=backend-service flag is required for AWS Marketplace metered billing. Keep it and pass -f my-values.yaml; without your values file the platform comes up unconfigured (no hostname, no inference endpoints).

Verify

What this does: confirms the platform is up and serving.
Then open https://$HOSTNAME_FQDN and sign up (email + password works out of the box; SSO only if you configured a provider).

Upgrades

To upgrade, pull the newer chart version the same way as in Install (log in to the ECR, helm pull with the new --version, unpack), then run the upgrade from the unpacked chart directory with the same flags:
Hooks are idempotent (OpenBao “already initialized”, mlai migration re-verify). Auto-generated secrets (PG/Redis/MinIO/Fernet/Tier/SYMI) are preserved across upgrades via helm.sh/resource-policy: keep.

Uninstall

Deleting PVCs destroys all data (Postgres, Qdrant, MinIO, etc.).

Troubleshooting

Values template

This is the current, supported values template; use this one, not the values-customer-template.yaml inside the pulled chart (that bundled copy is out of date). Copy it into your own values file, fill in the required fields (hostname, email, inference endpoints), and pass it to helm install with -f.
my-values.yaml