System Requirements
OpenBox targets Kubernetes as the sole runtime platform. Every service is designed for horizontal scale via HPA — running the platform on bare processes or Docker Compose is not supported. All requirements below assume a K8s cluster ≥ 1.27.
1. Operating Systems
Kubernetes node OS
The chart works on any OS supported by your K8s distribution. Recommended (tested in prod reference):
| OS | Version | Notes |
|---|---|---|
| Amazon Linux 2023 | AL2023 (kernel 6.1+) | EKS Auto Mode default; recommended for AWS |
| Ubuntu Server | 22.04 LTS / 24.04 LTS | Broad tooling support; common for self-managed K8s |
| RHEL / Rocky Linux / AlmaLinux | 8.8+ / 9.x | Enterprise-friendly; SELinux compatible |
| Bottlerocket | 1.20+ | Minimal container-OS for EKS; hardened defaults |
| SUSE Linux Enterprise | 15 SP5+ | Rare but supported |
Not supported:
- Windows nodes — OpenBox has no Windows container images
- macOS as K8s node OS (not a Kubernetes-supported OS in general)
- Alpine as node OS (some ML models need glibc — Alpine musl breaks PyTorch etc.)
Container runtime
- containerd ≥ 1.6 (default in modern K8s ≥ 1.24) — required
- Docker Engine as runtime is NOT supported (removed from K8s 1.24+)
- CRI-O ≥ 1.27 works but is not the reference target
Client / workstation OS
For running kubectl, helm, terraform, aws CLI on your admin workstation:
| OS | Support | Notes |
|---|---|---|
| macOS | 12 Monterey+ (13+ recommended) | Universal via Homebrew |
| Linux | Ubuntu 22.04+ / Fedora 38+ / RHEL 8+ / other modern distros | Native tooling |
| Windows | Windows 11 with WSL2 (Ubuntu recommended) | Native Windows shell not tested |
2. Software Requirements
Kubernetes baseline
| Component | Min version | Notes |
|---|---|---|
| Kubernetes API server | 1.27 | Chart annotation kubeVersion: ">=1.27.0-0" |
| kubelet | 1.27+ | Matches API server |
| CNI plugin | any | Must support NetworkPolicy (AWS VPC CNI / Calico / Cilium) |
| CoreDNS | v1.10+ | Default; other DNS providers untested |
| metrics-server | v0.6+ | Required for HPA |
Required cluster add-ons
| Add-on | Version | Required? | Purpose |
|---|---|---|---|
| metrics-server | 0.6+ | Required | HPA scaling |
| Ingress controller | any | Required | Public HTTPS routing (Istio / NGINX / ALB / Traefik) |
| Default StorageClass | any RWO | Required | Postgres + Redis + Elasticsearch PVCs |
Optional cluster add-ons
| Add-on | Version | When required |
|---|---|---|
| cert-manager | 1.13+ | Automated TLS certs from Let's Encrypt / ACM |
| External Secrets Operator | 0.9+ | Sync secrets from AWS SM / Vault / GCP SM |
| Argo Rollouts | 1.6+ | Canary deploy strategy (else chart falls back to Deployment) |
| Istio | 1.20+ | mTLS mesh + advanced traffic management (chart default) |
| NVIDIA Device Plugin | 0.14+ | Only if using GPU workloads (LlamaFirewall vllm) |
Runtime languages per service
Each service ships as a pre-built container image — you do not install language runtimes on nodes. This table documents what's inside each image for capacity planning + vulnerability tracking:
| Service | Runtime | Version |
|---|---|---|
openbox-backend | Node.js | 20 LTS |
openbox-core (all 5 containers) | Python + Temporal SDK | Python 3.11 / Temporal SDK 1.24 |
openbox-core-codec | Python | 3.11 |
openbox-fe | Node.js | 22 LTS (Next.js SSR) |
identity-service (Keycloak) | OpenJDK | 21 LTS |
opa-app | Go (statically linked) | OPA v0.65+ |
guardrails-api | Python | 3.11 |
model-host-detect-pii / -nsfw / -toxicity | Python + PyTorch | 3.11 / PyTorch 2.4 |
llamafirewall-server | Python | 3.11 |
vllm | Python + CUDA | 3.11 / CUDA 12.4 |
postgresql (Bitnami) | C (Postgres) | PostgreSQL 16+ |
openbox-core-redis | C (Redis) | Redis 7+ |
temporal-server (self-hosted variant) | Go | Temporal v1.24 |
elasticsearch (self-hosted Temporal only) | OpenJDK | ES 7.17.3 / JDK bundled |
Pin image tags in prod (image.tag: 0.1.0) — never :latest.
Client-side tooling
Install on your admin workstation:
| Tool | Min version | Purpose |
|---|---|---|
kubectl | 1.27+ | K8s CLI (match server version ± 1 minor) |
helm | 3.12+ | Chart install/upgrade |
jq | 1.6+ | JSON parsing (for output extraction) |
yq | 4.30+ | YAML parsing |
aws CLI | 2.x | AWS scenarios (S1, S2 Turnkey/Fresh AWS) |
terraform | 1.5+ | S2 Terraform IaC path |
docker | 24+ | S8 Local PoC (Minikube/kind driver) |
minikube or kind | latest | S8 Local PoC |
eksctl | latest | Optional — EKS provisioning (alternative to Terraform/CFN) |
cfn-lint | latest | Optional — validate S2 CloudFormation template |
3. Hardware Requirements
Assumption: Kubernetes cluster with HPA + Cluster Autoscaler (or Karpenter). Per-service resource limits are per pod; total cluster capacity is (pod resource × HPA maxReplicas) + node overhead.
Per-pod resource matrix
Requests are the HPA scheduling floor; limits are the burst ceiling. All values from charts/openbox/values.yaml.
| Service | Req CPU | Req RAM | Lim CPU | Lim RAM | Replicas (min → max) | GPU? |
|---|---|---|---|---|---|---|
| openbox-backend | 500m | 1 Gi | 1500m | 2 Gi | 1 → 8 (HPA @ 70% CPU) | ❌ |
| openbox-core (pod = 5 containers) | 1 vCPU | 2.5 Gi | 5 vCPU | 10 Gi | 1 → 5 | ❌ |
| ↳ each container | 200m | 500 Mi | 1 vCPU | 2 Gi | (× pod) | ❌ |
| openbox-core-codec | 200m | 500 Mi | 1 vCPU | 2 Gi | 1 | ❌ |
| openbox-core-redis | 200m | 521 Mi | 500m | 1 Gi | 1 (StatefulSet) | ❌ |
| openbox-fe | 200m | 512 Mi | 500m | 1 Gi | 2 → 6 | ❌ |
| identity-service (Keycloak) | 200m | 1700 Mi | 500m | 2 Gi | 3 → 5 | ❌ |
| opa-app | 200m | 1.5 Gi | 1 vCPU | 3 Gi | 1 → 5 | ❌ |
| guardrails-api | 500m | 1 Gi | 1 vCPU | 2 Gi | 2 → 10 | ❌ |
| model-host-detect-pii | 1 vCPU | 3.5 Gi | 2 vCPU | 4 Gi | 1 → 10 | ❌ |
| model-host-nsfw | 1 vCPU | 3.5 Gi | 2 vCPU | 4 Gi | 1 → 10 | ❌ |
| model-host-toxicity | 1 vCPU | 3.5 Gi | 2 vCPU | 4 Gi | 1 → 10 | ❌ |
| llamafirewall-server | 200m | 512 Mi | 500m | 1 Gi | 1 → 3 | ❌ |
| vllm (Qwen3-8B) | 2 vCPU | 6 Gi | 3 vCPU | 14 Gi | 1 | ✅ 1 × A10G 24 GB |
| Temporal server (self-hosted) — 4 pods | ~200m each | ~512 Mi each | ~1 vCPU each | ~1 Gi each | 4 (fixed) | ❌ |
| Elasticsearch (self-hosted Temporal) — 3 pods | 250m each | 1 Gi each | 500m each | 1 Gi each | 3 (fixed) | ❌ |
Cluster sizing — min → max scale
| Deployment size | Concurrent agents | Nodes (approx) | Total vCPU | Total RAM | GPU | Reference workload |
|---|---|---|---|---|---|---|
| PoC / Dev | < 10 | 1 (Minikube/kind) | 4 | 8 GB | ❌ | Laptop |
| Small prod | < 100 | 8 mixed | ~24 vCPU | ~128 GB | 1 × A10G | 1× r7i.xl + 1× m7i.xl + 2× c7i.xl + 1× g5.xl + 3× m7a.xl (AWS) |
| Medium prod | ~500 | 20 mixed | ~68 vCPU | ~250 GB | 1 × A10G | Full HPA scale-out |
| Enterprise | > 1000 | 40+ mixed | ~150 vCPU | ~500 GB | 2-4 × A10G/L4 | Multi-AZ + multi-GPU |
| On-prem small | < 100 | 8 bare-metal | ~48 phys cores | ~256 GB | 1 × T4/A10G | 2-socket / node × 24 cores + storage nodes + GPU node |
How to size for your workload:
- Start with Small prod baseline
- Measure p95 CPU + RAM per service under expected load
- Set HPA
maxReplicas= (peak load ÷ per-pod capacity) × 1.5 safety factor - Configure Cluster Autoscaler / Karpenter to add nodes when HPA can't schedule
Node pool separation (recommended for prod)
Prod reference uses 5 taints to isolate workload classes — HPA behaves better when noisy neighbors are excluded:
| Taint | Instance class (AWS example) | Hosts |
|---|---|---|
workload-line=cpu:NoSchedule | c/r/t gen 6+ | Backend, core, fe, opa, keycloak, redis, codec |
workload-line=memory:NoSchedule | m/r/t/x gen 6+ | Temporal server + web + admintools + Elasticsearch |
workload-line=database:NoSchedule | m7a.xlarge | 3× PostgreSQL clusters |
workload-line=llm:NoSchedule | g5.xlarge (1 × A10G GPU) | vllm Qwen3-8B |
workload-line=guardrails:NoSchedule | c7i.xlarge | guardrails-api + 3× model-hosts |
Not required — you can run everything on a single general-purpose node pool. Isolation matters at Medium+ scale.
GPU requirements (only if guardrails-api.llamafirewall.enabled: true)
| GPU | VRAM | Cloud instance | Notes |
|---|---|---|---|
| NVIDIA A10G (default) | 24 GB | AWS g5.xlarge | Reference — Qwen3-8B fits with headroom |
| NVIDIA L4 | 24 GB | GCP g2-standard-8 | Same VRAM, similar throughput |
| NVIDIA T4 | 16 GB | AWS g4dn.xlarge / Azure NCasT4_v3 | Tight — may OOM on long contexts. Reduce max_model_len |
| NVIDIA A100 40/80 GB | 40/80 GB | AWS p4d / Azure ND A100 v4 | Overkill; use for larger custom models |
Requires NVIDIA Device Plugin installed on cluster (kubectl get pods -n kube-system | grep nvidia-device-plugin).
Zero-GPU mode: guardrails-api.llamafirewall.enabled: false — PII/NSFW/toxicity CPU classifiers still work; deep prompt-injection detection unavailable.
Storage
Volume sizing per PVC. All must be ReadWriteOnce.
| PVC | Min | Recommended prod | Max (long-lived) | Backend | Notes |
|---|---|---|---|---|---|
| App Postgres | 20 GB | 100 GB | 500 GB+ | gp3 / equivalent | Enable PITR |
| Identity Postgres | 5 GB | 20 GB | 50 GB | gp3 | Keycloak realms/users |
| Temporal Postgres (self-hosted only) | 10 GB | 100 GB | 500 GB | gp3 | Grows with workflow history |
| Elasticsearch (× 3 pods, self-hosted Temporal only) | 30 GB each | 50 GB each | 100 GB each | gp3 | Configurable retention |
| Redis (openbox-core-redis) | 5 GB | 5 GB | 10 GB | gp3 | Cache — low durability priority |
| OPA policy bundles | < 1 GB | 1 GB | 5 GB | S3 (object) | Not a PVC — S3 bucket |
| Container image cache (per node) | 20 GB | 30 GB | 40 GB | Node root disk | Prune old tags via ImagePolicy |
IOPS: gp3 default (3000 IOPS / 125 MB/s) is fine up to Medium prod. Enterprise → provision gp3 IOPS to 6000+ for Postgres.
Network
| Requirement | Value |
|---|---|
| Ingress | HTTPS 443 (external) |
| Inter-service | gRPC 7233 (Temporal), REST 8xxx, JDBC 5432, Redis 6379 |
| Bandwidth (steady) | ~50-200 Mbps mixed |
| Bandwidth (peak) | ~500 Mbps+ under bursts |
| Latency SLO (internal p99) | < 20 ms service-to-service |
| Egress | Image pulls + KMS API + S3 GET + customer's telemetry |
| Multi-AZ | Recommended for Medium prod+ (spread nodes ≥ 2 AZ) |
4. Database
OpenBox uses PostgreSQL for transactional data + Redis for session cache + (optionally) Elasticsearch for Temporal visibility. Postgres is the critical dependency.
4.1 PostgreSQL
Version: 16.x (chart default) or newer. 15.x is EOL — do not use. 17.x tested and supported.
Three separate DB clusters recommended in prod:
| DB name | Owner | Purpose | Size growth |
|---|---|---|---|
openbox | openbox-backend + openbox-core | App transactional data, agent state, audit logs | Linear with agent activity |
keycloak | identity-service | Realms, users, tokens, sessions | Slow — bounded by user count |
temporal | Temporal server (self-hosted variant only) | Workflow history + task queues | Grows with workflow retention (configurable) |
You can consolidate to 1 Postgres instance with 3 databases for smaller deploys — cheaper, tighter blast radius per shared instance.
Sizing:
| Scale | Instance class (AWS RDS/Aurora) | Storage | IOPS |
|---|---|---|---|
| PoC | db.t4g.micro (in-cluster Bitnami OK) | 20 GB gp3 | Default (3000) |
| Small prod | db.r6i.large (2 vCPU / 16 GB) | 100 GB gp3 | Default (3000) |
| Medium prod | db.r6i.xlarge (4 vCPU / 32 GB) | 250 GB gp3 | 6000 provisioned |
| Enterprise | db.r6i.2xlarge (8 vCPU / 64 GB) + read replica | 500 GB+ | 12000+ provisioned |
Recommended settings:
max_connections = 200 # tune to (pod count × 20 avg connections per pod)
shared_buffers = 25% RAM # standard PG guidance
effective_cache_size = 75% RAM
work_mem = 16 MB # per-query sort/hash
maintenance_work_mem = 512 MB # for VACUUM, CREATE INDEX
Extensions required:
pgcrypto— used byopenbox-backendfor field-level encryptionuuid-ossp— UUID generation
Managed alternatives (recommended over in-cluster Bitnami for prod):
| Cloud | Service | Notes |
|---|---|---|
| AWS | Amazon Aurora PostgreSQL OR RDS PostgreSQL | Aurora Global DB enables T3+ DR tier |
| Azure | Azure Database for PostgreSQL Flexible Server | |
| GCP | Cloud SQL for PostgreSQL | |
| On-prem | CloudNativePG operator | K8s-native Postgres, HA + PITR |
Config lives under openbox-backend.db.*, identity-service.db.*, and (self-hosted Temporal) openbox-core.temporal.server.db.* values.
See Customization → External database endpoint for the full wiring.
Backup / DR:
- Backup retention ≥ 7 days (chart default for the in-cluster Bitnami is 0 — override in prod)
- Enable point-in-time recovery (PITR) — RDS default is 7 days
- Test restore quarterly
4.2 Redis
Version: 7.x (chart default redis:7-alpine). 6.x is legacy; 8.x untested.
Purpose: session cache for openbox-core-server. Data is ephemeral by design — session loss on restart is acceptable.
Sizing:
| Scale | Instance | Storage | Persistence |
|---|---|---|---|
| PoC | 1 pod (in-cluster) | 5 GB gp3 | AOF disabled |
| Small prod | cache.t4g.small (ElastiCache) OR 1 pod | 5 GB | AOF disabled |
| Medium prod | cache.t4g.medium OR ReplicaCount=2 | 10 GB | AOF fsync-per-sec |
| Enterprise | ElastiCache cluster mode + replica | 20 GB+ | AOF + snapshotting |
Managed alternatives:
| Cloud | Service |
|---|---|
| AWS | ElastiCache for Redis (cluster mode enabled for HA) |
| Azure | Azure Cache for Redis |
| GCP | Memorystore for Redis |
| On-prem | Bitnami Redis chart (chart default) |
Config lives under openbox-core.redis.external.host / .port values. See Customization → External database endpoint.
Not required:
- Redis Cluster mode (unless you're at Enterprise scale)
- Redis persistence in most tiers (session data is regenerable from Postgres + Keycloak)
4.3 Elasticsearch (self-hosted Temporal variant only)
If openbox-core.temporal.mode: self-hosted, the Temporal server needs Elasticsearch 7.17.3 for visibility store.
Version: ES 7.17.x (fixed by Temporal upstream — do NOT upgrade to ES 8.x, not yet supported)
Sizing:
- 3 pods (fixed by Bitnami chart, HA quorum)
- 250m CPU / 1 Gi RAM per pod (requests) — bump to 500m / 2 Gi for Medium+
- 30 GB gp3 per pod → 90 GB total baseline; grows with workflow visibility retention
Not required if temporal.mode: cloud — Temporal Cloud handles visibility internally.
Retention tuning: Temporal namespace retention config drives ES growth. Default 30 days = ~30 GB per 1M workflow completions. Tune per compliance needs.
Quick reference by scenario
| Scenario | Cluster | Storage | GPU | Compute (approx) |
|---|---|---|---|---|
| S1 Turnkey | Openbox provisions | 300 GB total | 1 × A10G | Small-Medium prod baseline |
| S2 Fresh AWS | Customer provisions via Terraform/CFN | 250-500 GB | 1 × A10G | Small prod baseline (~24 vCPU) |
| S3 BYOC | Reuse existing K8s | Depends on cluster | Optional | Fits into existing capacity |
| S8 Local PoC | Minikube/kind | 30 GB laptop | ❌ | 4 vCPU / 8 GB laptop |
For per-scenario cost estimates see the brainstorm report §8.
Verification checklist
Before helm install, verify on your cluster:
# K8s version
kubectl version --output=json | jq -r '.serverVersion.gitVersion'
# Expect: v1.27.x or newer
# Nodes ready
kubectl get nodes --no-headers | grep -c ' Ready '
# Expect: ≥ 3 for prod, ≥ 1 for PoC
# metrics-server
kubectl get deployment metrics-server -n kube-system
# Expect: 1/1 Ready
# StorageClass
kubectl get storageclass | grep '(default)'
# Expect: 1 line with (default) annotation
# IngressClass
kubectl get ingressclass
# Expect: 1+ classes
# GPU (if using LlamaFirewall)
kubectl get nodes -o custom-columns=NAME:.metadata.name,GPU:.status.capacity.'nvidia\.com/gpu'
# Expect: at least 1 node with a GPU count > 0
Full checklist in S3 Prerequisites checklist.