Skip to content

Plan & Provision Infrastructure

This guide covers everything you need to plan, bring, and provision before kindo-cli can install Kindo on top. Work through the four sections in order — pick a size, confirm each component meets spec, plan DNS and firewall, then tick every box on the team-scoped checklist before handing off to the CLI. Provision with your own tooling on any provider — AWS, GCP, Azure, on-prem, OpenShift, or Rancher — the install is cloud-agnostic; only the component spec matters.

Sizing drives everything downstream: node count, database class, RAM and vCPU targets for managed services, and the service-quota requests you need to file with your cloud provider. Pick the smallest tier that matches your expected active users — you can scale up later, but it is cheaper to start right.

Node counts are shown as the recommended max per node group. Two groups (primary + agents) run at this sizing, so totals are 2× per-group.

SizeUse caseKubernetes nodes (per group)PostgreSQL (main / auxiliary)RedisRabbitMQTotal cluster capacity
Medium50 to 200 active users6 nodes × 8 vCPU, 16 GB RAM (c6i.2xlarge)main: 2 vCPU, 8 GB (db.m6i.large) / aux: 2 vCPU, 8 GB (db.t4g.large)3.09 GB (cache.t3.medium)2 vCPU, 8 GB RAM (mq.m5.large)96 vCPU, 192 GB RAM
Large200 to 1,000 active users10 nodes × 16 vCPU, 32 GB RAM (c6i.4xlarge)main: 4 vCPU, 16 GB (db.m6i.xlarge) / aux: 2 vCPU, 8 GB (db.m6i.large)6.38 GB (cache.m6g.large)4 vCPU, 16 GB RAM (mq.m5.xlarge)320 vCPU, 640 GB RAM

Kindo is a Helm-installed application. As long as the components below meet spec and are reachable from the cluster, the CLI install is cloud-agnostic. Every row is a hard requirement unless otherwise noted — if one is missing or misconfigured, the install will fail.

AttributeRequirement
Version1.32 or higher
NetworkingCNI with NetworkPolicy support (Calico, Cilium, Flannel)
StorageDynamic volume provisioning, default StorageClass, ReadWriteOnce volumes
IngressAn ingress controller installed (NGINX, Traefik, ALB Controller, or equivalent). Gateway API is also supported.
TLScert-manager installed, or certificates provisioned out-of-band
RBACEnabled (required)
Metricsmetrics-server installed (required for HPA and kubectl top)
SizingMedium: 6 nodes × 8 vCPU, 16 GB RAM (c6i.2xlarge), Large: 10 nodes × 16 vCPU, 32 GB RAM (c6i.4xlarge). Node counts are the recommended max per group; two groups (primary + agents) run at this sizing.

GPU nodes are only required if you plan to self-host models. Labels nvidia.com/gpu=true and accelerator=<model> let Helm schedule model workloads onto them.

Kindo deployments include an in-cluster observability stack — ClickHouse for telemetry storage (with Keeper for replication quorum), the OTel Collector, and HyperDX as the query UI. kindo-cli installs all of it as peripheries (see Install with kindo-cli), and it runs entirely inside the cluster with no managed database or external service. It consumes real cluster capacity, so plan for it here alongside the components you bring.

AttributeRequirement
Block storage~670 Gi of persistent volumes at default sizing — 2 × 300 Gi (ClickHouse replicas), 3 × 20 Gi (Keeper), 10 Gi (HyperDX-bundled MongoDB) — provisioned from your StorageClass
Compute~6 vCPU and ~19 Gi of memory requests across the ClickStack pods, on top of the node sizing above
Node fitClickHouse pods have a 16 Gi memory limit — they fit on Large-tier nodes (32 GB); Medium-tier nodes (16 GB) require down-tuned ClickHouse resources
Node lifecycleSchedule ClickHouse and Keeper on on-demand nodes, not spot instances — both are stateful, and Keeper is quorum-based
Availability zonesEnsure nodes can run in every zone your StorageClass provisions volumes in — a volume pinned to a zone with no schedulable node leaves its pod unschedulable

Decisions to make before install:

  • Disk size. Persistent volumes can be expanded later (where the StorageClass supports it) but never shrunk. The 300 Gi default per ClickHouse replica leaves headroom for longer retention or enabling more telemetry signals later; size down deliberately if the cluster is small.
  • Retention. Telemetry tables carry a 7-day TTL by default, so storage does not grow unbounded. Retention is a Helm value the operator can raise at install or on any later upgrade.
AttributeRequirement
Version17.0 or higher (17.4 recommended)
Storage100 GB SSD minimum; scale with data volume
Concurrent connections200+
EncryptionAt-rest and in-transit required for production
HA (production)Streaming replication or managed service with automatic failover
BackupsDaily automated backups, 7+ day retention
Sizing (main)Medium: 2 vCPU, 8 GB RAM (db.m6i.large), Large: 4 vCPU, 16 GB RAM (db.m6i.xlarge)
Sizing (auxiliary)Medium: 2 vCPU, 8 GB RAM (db.t4g.large), Large: 2 vCPU, 8 GB RAM (db.m6i.large)
AttributeRequirement
Version7.0 or higher (7.2 recommended)
Concurrent connections100+
ModeStandalone (single primary, no shards)
SizingMedium: 3.09 GB (cache.t3.medium), Large: 6.38 GB (cache.m6g.large)

Cloud provider compatibility:

  • AWS ElastiCache — Cluster Mode Disabled with num_node_groups = 1, replicas_per_node_group = 0. Engine version 7.0+. Cluster Mode Enabled with 2+ shards is not supported.
  • Azure Cache for Redis — Basic or Standard tier (single-node, non-clustered). Premium/Enterprise clustered tiers with 2+ shards are not supported.
  • Google Cloud Memorystore — Basic tier (standalone instance). Redis Cluster mode is not supported.

Verify your Redis mode before proceeding:

Terminal window
redis-cli INFO server | grep redis_mode
# redis_mode:standalone -> compatible
# redis_mode:sentinel -> not supported
# redis_mode:cluster -> not supported
AttributeRequirement
Version3.13 or higher
Disk20 GB minimum across all sizes
Management pluginEnabled
HA (production)3+ node cluster with quorum queues, or managed service (e.g., Amazon MQ)
SizingMedium: 2 vCPU, 8 GB RAM (mq.m5.large), Large: 4 vCPU, 16 GB RAM (mq.m5.xlarge)

Any S3 API-compatible store: AWS S3, Google Cloud Storage (S3 compatibility), Azure Blob (S3 compatibility), MinIO, or Ceph.

BucketPurposeAccess
kindo-uploadsUser file uploadsPrivate

Provision the buckets (or equivalent naming) with server-side encryption and block-public-access enabled.

Qdrant (self-hosted or managed) — deploy into Kubernetes, or point at a managed Qdrant endpoint. Kindo creates the collection automatically on first call with the correct vector size for your embedding model — no manual setup required, and no re-indexing work if you change embedding models later.

Either (a) cert-manager configured against an ACME issuer (Let’s Encrypt) or a private CA, or (b) pre-issued wildcard certificate for *.kindo.example.com loaded as a Kubernetes Secret. kindo-cli references the certificate by name — it does not issue or rotate it for you.

A running ingress controller in the cluster with:

  • Class name known to you (e.g., nginx, alb, traefik) — you’ll pass it to kindo-cli.
  • Inbound 443 (HTTPS) open; 80 allowed for HTTP→HTTPS redirect.
  • Outbound 443 to the public internet (or your private AI endpoints), plus access to PostgreSQL (5432), Redis (6379), and RabbitMQ (5672) as applicable. :::

Any email service that supports the SMTP protocol — a self-hosted SMTP server, or managed providers like Amazon SES, SendGrid, or Mailgun that expose SMTP credentials. Used for transactional email (invites, password reset, alerts).

Kindo provisions 13 ingress hostnames across a single load balancer. Pick a parent domain you control (examples use kindo.company.com) and create A or CNAME records for each subdomain through your ingress controller. A wildcard TLS certificate covering *.kindo.company.com is the simplest option; with AWS Route53 + external-dns, records are created automatically from pod annotations.

SubdomainComponentExample
app.Next.js frontendapp.kindo.company.com
api.Backend API (also receives webhooks via path rules)api.kindo.company.com
integrations-api.Nango integration APIintegrations-api.kindo.company.com
integrations-connect.Nango OAuth / Connect UIintegrations-connect.kindo.company.com
sso.SSOReady adminsso.kindo.company.com
sso-auth.SSOReady auth endpointsso-auth.kindo.company.com
sso-api.SSOReady APIsso-api.kindo.company.com
sso-app.SSOReady user-facing appsso-app.kindo.company.com
hatchet.Hatchet API (/api) and dashboard (/) on one hosthatchet.kindo.company.com
litellm.LiteLLM model proxylitellm.kindo.company.com
unleash.Unleash feature flag serviceunleash.kindo.company.com
unleash-edge.Unleash Edge (client-facing read cache)unleash-edge.kindo.company.com
hyperdx.HyperDX observability UIhyperdx.kindo.company.com

Open only the ingress entry points to the public internet (or to your corporate network, if Kindo is internal-only).

PortProtocolPurpose
443TCPHTTPS — all user traffic
80TCPHTTP redirect to 443 (optional, recommended)

The cluster needs egress to reach managed infrastructure and external AI providers. If any of these paths are blocked, the install or runtime behaviour will break — check with your network team before you start provisioning.

PortProtocolDestinationPurpose
443TCPAI providers (OpenAI, Anthropic, Azure OpenAI, Groq), container registriesModel inference, embeddings, image pulls
5432TCPPostgreSQL endpointDatabase traffic
6379TCPRedis endpointCache and streaming
5672TCPRabbitMQ endpointMessage queue
25 / 587 / 465TCPEmail providerSMTP

Work through the tables below and tick items off as you gather them. Every row is tagged with the team that typically owns it so the list can be split and distributed across departments — ownership is a suggestion, not a mandate. You are ready to proceed to the next section only once every box is checked.

OwnerItem
PlatformDeployment size chosen (Medium / Large)
Cloud OpsKubernetes cluster target identified (1.32+, 3+ nodes, RBAC enabled, default StorageClass, LoadBalancer support)
DBA / Cloud OpsPostgreSQL plan in place (17.0+, managed service recommended, capacity for six databases: kindo, unleash, litellm, ssoready, hatchet, nango)
DBA / Cloud OpsRedis plan in place (7.0+, standalone mode only, sized per deployment tier)
DBA / Cloud OpsRabbitMQ plan in place (3.13+, management plugin enabled)
Cloud OpsS3-compatible object storage selected (AWS S3, GCS, Azure Blob, MinIO, or Ceph) with the kindo-uploads bucket planned
PlatformVector database plan in place — Qdrant, self-hosted in the cluster or a managed endpoint
NetworkingIngress controller chosen (NGINX, Traefik, or cloud provider equivalent)
Security / NetworkingTLS strategy decided (cert-manager, wildcard cert, or per-subdomain certs)
PlatformEmail provider selected — must be SMTP-protocol-compatible (self-hosted SMTP, SES, SendGrid, Mailgun, or any other provider exposing SMTP credentials)
Cloud OpsGPU node plan written down if self-hosting AI models (see Prepare AI Models)
Cloud OpsIn-cluster observability capacity planned — ~670 Gi of persistent volumes plus ~6 vCPU / ~19 Gi requests at default sizing, disk size and retention decided (see In-cluster observability)

Tools to download (to the operator workstation — no cluster interaction yet)

Section titled “Tools to download (to the operator workstation — no cluster interaction yet)”
OwnerItem
Platformpython 3.11+ (kindo-cli runtime)
Platformkindo-cli — latest release, provided by Kindo
Platformhelm v4 (latest)
Platformhelmfile v1.2+ (CLI wraps it)
Platformkubectl 1.32+
Platformyq — latest
Platformjq — latest
Platformpsql — latest (optional, needed for kindo db tunnel / prompt / reset after install)
OwnerItem
SecurityKindo container registry credentials received from Kindo
Security / AppDevAt least one AI provider API key obtained (OpenAI, Anthropic, Azure OpenAI, Groq, or self-hosted vLLM)
SecurityVector DB credentials obtained — Qdrant endpoint + API key (if using a managed endpoint)
SecurityEmail provider credentials obtained
Security(Optional) Secrets management strategy decided (External Secrets Operator with AWS Secrets Manager, HashiCorp Vault, Google Secret Manager, or Azure Key Vault)
OwnerItem
NetworkingParent domain confirmed (e.g. kindo.company.com)
NetworkingA or CNAME records planned for: app., api., sso., litellm., unleash., webhooks., hatchet., and hyperdx.
Networking / SecurityInbound firewall rule for 443/TCP (and 80/TCP redirect) approved
Networking / SecurityOutbound firewall rules approved for 443 (external APIs), 5432 (PostgreSQL), 6379 (Redis), 5672 (RabbitMQ), and SMTP ports (25/587/465)
NetworkingCNI type confirmed — flag to Kindo before the install call if it is not AWS VPC CNI (Calico, Cilium, custom — see the caution in Component requirements)
SecurityNetwork posture decided (open / private / restricted)
OwnerItem
Cloud OpsOperator IAM / service account identified — permissions to create Kubernetes Secrets, Deployments, Services, Ingresses, and ConfigMaps across all Kindo namespaces
SecurityOrganization-level guardrails reviewed — SCPs (AWS), org policies (GCP), management group policies (Azure) that might block IAM role creation, resource provisioning, or required tagging
Cloud OpsWorkload identity pattern chosen — IRSA (AWS), Workload Identity (GCP), or Azure Pod Identity — with trust relationships wired for services that need cloud access (e.g. LiteLLM → AWS Bedrock)
PlatformCluster RBAC verified — the operator has permission to create service accounts, role bindings, and cluster-scoped resources needed by the install
OwnerItem
SecurityRegistry allowlist updated to include registry.kindo.ai (or the internal mirror, if air-gapped) — verify image pulls are not blocked by admission controllers
SecurityImage scanning requirements clarified — if your environment blocks unscanned images, coordinate with Kindo for SBOMs or a mirror-and-scan workflow
SecurityEncryption at rest confirmed on PostgreSQL, Redis, S3, and Kubernetes Secrets storage
SecuritySecrets handling policy agreed (rotation cadence, who has read access to kindo-secrets-config)
OwnerItem
PlatformInstall host identified — bastion, jump box, developer laptop, or CI runner — with network reachability to the cluster’s API server
PlatformInstall host has python 3.11+, kindo-cli, helm v4, helmfile v1.2+, kubectl 1.32+, yq, and jq installed and on PATH (plus optional psql for kindo db)
Platformkubectl context for the target cluster is configured and tested (kubectl cluster-info, kubectl auth can-i create namespace --all-namespaces)
SecuritySession recording / audit requirements on the install host confirmed — many regulated envs require this for any privileged shell session
OwnerItem
Platform ownerCapacity plan approved (sizing, GPU nodes, autoscaling limits)
Networking ownerDNS, TLS, firewall, and CNI/ingress plan approved
Security ownerSecrets storage, image source, IAM, and compliance plan approved
Compliance ownerEvidence collection and audit plan approved (if a compliance regime applies)

You’ve finished the infrastructure layer. From here on, kindo-cli takes over. The CLI reads the connection strings you gathered, generates the centralized secrets, installs peripheries (External Secrets Operator, Unleash, OTel), and deploys the Kindo application stack (API, workers, LiteLLM, frontends) via Helm.

Two steps remain before you run kindo install:

  • Prepare your AI models. Decide whether you’re using cloud providers (OpenAI, Anthropic, Bedrock, Azure, Gemini), self-hosted vLLM, or a mix. The model endpoints must be reachable from the cluster before the CLI’s post-install step registers them. This can happen in parallel with the CLI setup.
  • Install the CLI and generate the install contract. kindo config init walks you through a 10-section wizard that writes install-contract.yaml and environment-bindings.yaml. kindo config validate --preflight then deploys a short-lived Job into the cluster to confirm every item on your checklist is actually reachable.