{"slug": "deploying-an-open-source-ai-agent-platform-to-kubernetes-the-honest-one-command", "title": "Deploying an open-source AI agent platform to Kubernetes: the honest one-command version", "summary": "A developer published an honest, trap-inclusive guide to deploying ApowerB, an open-source AI agent platform, on Kubernetes using its official cosign-signed Helm chart (apowerb-chart, v0.4.23). The writeup details the prerequisites most \"one-command\" tutorials omit — storage classes, ingress controllers, cert-manager and DNS — and warns that omitting the secrets values file on any helm upgrade rotates credentials out from under a running database.", "body_md": "*Every \"deploy X to Kubernetes in one command\" article is technically true and practically a lie. The `helm install` really is one line. What the post skips is the empty cluster with no storage class, no ingress controller, no cert-manager, and no DNS. That 90% is what stands between you and a working URL. So here's the honest version for [ApowerB](https://thaink2.com/opensource), the open-source agent platform: the chart genuinely installs in one command, and here is everything around it, traps included.*\n\nApowerB ships an official Helm chart (`apowerb-chart`, OCI, cosign-signed) that stands up the whole stack, not just the app:\n\nThat's a platform, not a container. Which is exactly why the cluster prerequisites below matter more than for a toy app.\n\nIf you already have a cluster with a working storage class, two commands get you running.\n\n**1. Generate the secrets.** The chart refuses to start without them, on purpose:\n\n```\numask 077\ncat > values-secrets.yaml <<YAML\nbackend:\n  env:\n    encryptKey: \"$(openssl rand -base64 32)\"\nth2etl:\n  apiKey: \"$(openssl rand -hex 32)\"\nth2pulse:\n  ingestToken: \"$(openssl rand -hex 32)\"\n  queryToken: \"$(openssl rand -hex 32)\"\npostgres:\n  password: \"$(openssl rand -hex 16)\"\nYAML\nchmod 600 values-secrets.yaml\n```\n\n**2. Install:**\n\n```\nhelm upgrade --install apowerb \\\n  oci://registry-1.docker.io/apowerb/apowerb-chart --version 0.4.23 \\\n  --namespace apowerb --create-namespace \\\n  --values values-secrets.yaml --timeout 10m\n```\n\nThen port-forward and open the UI:\n\n```\nkubectl -n apowerb port-forward svc/apowerb-frontend 13000:3000 &\n# http://localhost:13000\n```\n\nAdd a model key in the UI and you have a working agent platform on your cluster. That's the \"one command\" part, and it's real.\n\n**The one rule that bites everyone:** pass `--values values-secrets.yaml` on *every* `helm upgrade`. Drop it and you rotate your own credentials out from under a running database. Keep that file safe and version it in your secret store, not in Git.\n\nA real cluster rarely has everything wired. Here's the full walk, which is where most tutorials go quiet.\n\nKubernetes 1.28+. Three nodes at 4 vCPU / 8 GB give comfortable headroom. Check the ground first:\n\n```\nkubectl get nodes          # all Ready\nkubectl get storageclass   # must not be empty\nkubectl get ingressclass   # must exist\n```\n\nLean managed clusters often ship with no default storage class. If `get storageclass` is empty, install one:\n\n```\ncurl -sL -o local-path-storage.yaml \\\n  https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.37/deploy/local-path-storage.yaml\nkubectl apply -f local-path-storage.yaml\nkubectl -n local-path-storage rollout status deploy/local-path-provisioner --timeout=120s\n\nkubectl patch storageclass local-path \\\n  -p '{\"metadata\":{\"annotations\":{\"storageclass.kubernetes.io/is-default-class\":\"true\"}}}'\n```\n\n**Trap:** most storage classes are `WaitForFirstConsumer`, so a lone PVC stays `Pending` and looks broken when it's fine. Test with a PVC *and* a pod together:\n\n```\nkubectl apply -f - <<'YAML'\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata: {name: probe-pvc}\nspec:\n  accessModes: [\"ReadWriteOnce\"]\n  resources: {requests: {storage: 1Gi}}\n---\napiVersion: v1\nkind: Pod\nmetadata: {name: probe-pod}\nspec:\n  restartPolicy: Never\n  containers:\n    - name: writer\n      image: busybox:1.37\n      command: [\"sh\",\"-c\",\"echo ok > /data/marker && cat /data/marker && sleep 20\"]\n      volumeMounts: [{name: data, mountPath: /data}]\n  volumes:\n    - {name: data, persistentVolumeClaim: {claimName: probe-pvc}}\nYAML\nsleep 25 && kubectl get pvc probe-pvc && kubectl logs probe-pod\nkubectl delete pvc probe-pvc pod probe-pod\n```\n\nWant `Bound` and `ok` in the logs. If this fails, stop. Nothing else will work.\n\n```\nkubectl get ingressclass\nkubectl get svc -A | grep LoadBalancer\n```\n\nNote the **class name** (Traefik and ingress-nginx are the usual managed add-ons) and the **EXTERNAL-IP** for DNS.\n\nLet's Encrypt rate-limits at 5 failures/hour, so always start on staging:\n\n```\napiVersion: cert-manager.io/v1\nkind: ClusterIssuer\nmetadata:\n  name: letsencrypt-staging\nspec:\n  acme:\n    server: https://acme-staging-v02.api.letsencrypt.org/directory\n    email: you@example.com\n    privateKeySecretRef:\n      name: letsencrypt-staging-account-key\n    solvers:\n      - http01:\n          ingress:\n            ingressClassName: traefik   # your actual class from Step 2\n```\n\n**Trap that costs an afternoon:** use `ingressClassName`, not the deprecated `class` annotation. Otherwise the ACME challenge Ingress gets no recognised class and the certificate sits at `Ready: False` forever.\n\nSame install command, now with public access turned on:\n\n```\nhelm upgrade --install apowerb \\\n  oci://registry-1.docker.io/apowerb/apowerb-chart --version 0.4.23 \\\n  --namespace apowerb --values values-secrets.yaml \\\n  --set ingress.enabled=true \\\n  --set ingress.className=traefik \\\n  --set ingress.host=apowerb.example.com \\\n  --set ingress.tlsEnabled=true \\\n  --set ingress.annotations.\"cert-manager\\.io/cluster-issuer\"=letsencrypt-staging\n```\n\nCreate the first admin while you're at it:\n\n```\n  --set superadmin.email=admin@example.com \\\n  --set superadmin.password='<a strong one>'\n```\n\nPoint an A record at the `EXTERNAL-IP`, then:\n\n```\nkubectl -n apowerb get certificate\nkubectl -n apowerb describe certificate apowerb-tls\n```\n\nStuck at `Ready: False`? It's almost always one of: DNS not resolving to the load balancer, port 80 closed (HTTP-01 needs it), the `class` vs `ingressClassName` trap, or a staging rate limit. Once it's `True`, swap the issuer to production (` https://acme-v02.api.letsencrypt.org/directory`) and reapply.\n\nThe same `values` mechanism covers the rest:\n\n`defaultLlm.model` and `defaultLlm.apiKey` for agents without their own key (LiteLLM under the hood, so OpenAI / Anthropic / Mistral / Gemini / local all work)`GOOGLE_INTEGRATION_*` (Drive, Gmail, Calendar), `MICROSOFT_INTEGRATION_*` (Outlook, webhooks, mail), `SMTP_*`\n`storage.mode` and `S3_*` to push `bi_store`, `uploads`, `artifacts_store` and `agents_pool` to object storage instead of the PVC\nThe install itself is genuinely one command against an OCI chart, and the chart is honest: it won't boot without real secrets, and it bundles the orchestration, log store and telemetry rather than leaving them as \"exercises for the reader.\" The work that remains isn't ApowerB's, it's the cluster's: storage, ingress, cert-manager, DNS. And that's true of anything serious you deploy.\n\nIf you want to see the easy version first, the Docker Compose stack comes up locally in a few commands. But if you're putting agents in front of real users, the Helm chart is the path, and now you've seen all of it, traps included.\n\n*Deployed it on something interesting? Drop your cluster setup in the comments.*", "url": "https://wpnews.pro/news/deploying-an-open-source-ai-agent-platform-to-kubernetes-the-honest-one-command", "canonical_source": "https://dev.to/anis_meziani_52aab42304a8/deploying-an-open-source-ai-agent-platform-to-kubernetes-the-honest-one-command-version-574", "published_at": "2026-10-05 14:13:00+00:00", "updated_at": "2026-10-05 14:18:26.165177+00:00", "lang": "en", "topics": ["ai-agents", "ai-infrastructure", "mlops", "developer-tools", "ai-tools"], "entities": ["ApowerB", "Kubernetes", "Helm", "Rancher", "Traefik", "ingress-nginx", "Let's Encrypt", "cert-manager"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/deploying-an-open-source-ai-agent-platform-to-kubernetes-the-honest-one-command", "markdown": "https://wpnews.pro/news/deploying-an-open-source-ai-agent-platform-to-kubernetes-the-honest-one-command.md", "text": "https://wpnews.pro/news/deploying-an-open-source-ai-agent-platform-to-kubernetes-the-honest-one-command.txt", "jsonld": "https://wpnews.pro/news/deploying-an-open-source-ai-agent-platform-to-kubernetes-the-honest-one-command.jsonld"}}