Skip to main content
This guide installs the complete Bud-Stack platform — the application plus its in-cluster dependencies (PostgreSQL, ClickHouse, Kafka, MongoDB, Valkey, SeaweedFS, observability) — into an existing Kubernetes cluster using ArgoCD. ArgoCD pulls every chart from the OCI registry, so you do not need access to the source repository.
Already run managed databases (Azure Database for PostgreSQL, Cosmos DB, external Kafka/ClickHouse, etc.) and want a single Helm install instead of in-cluster dependencies? Follow the Deployment Guide — it installs only the bud chart pointed at your external services.

How it works

You apply two ArgoCD ApplicationSets, both sourcing charts from oci://registry.bud.studio/charts:
ApplicationSetDeploysNamespace(s)
cluster-addonsdapr, cert-manager, cert-manager-issuer, postgres, clickhouse, kafka, mongodb, valkey, seaweedfsone per addon
prod-appskeycloak, bud (the platform)keycloak, bud
The chart comes from the registry; your configuration (values.yaml + secrets) comes from a source you control — a small config repo (recommended), inline values, or the CLI (Step 3). Nothing proprietary lives in your config, and you never need credentials to bud-runtime.
Ordering. The addon charts install operators (CloudNativePG, Strimzi, Altinity, Percona, …) whose CRDs must exist before the database custom-resources can apply. The charts do not use ArgoCD sync-waves; instead ArgoCD’s automated + selfHeal sync policy retries failed syncs until each operator establishes its CRDs and the dependent resources converge. Expect a few Applications to show Degraded/Progressing on the first pass and self-heal within a few minutes — this is normal.

Prerequisites

RequirementNotes
Kubernetes 1.25+With a default StorageClass for PVCs
kubectl, helm 3.8+Helm must support OCI registries
ArgoCD installedYou bootstrap it yourself (Step 2). Bud does not manage your ArgoCD.
Ingress controllerChart Ingresses default to ingressClassName: traefik
Registry credentialsRobot account for registry.bud.studio
A config sourceA git repo you own (recommended) or inline values — see Step 3

Step 1 — Get registry credentials

You need a read-only robot account for registry.bud.studio to let both ArgoCD (chart pulls) and your cluster (image pulls) authenticate.
helm registry login registry.bud.studio -u 'robot$yourname'
# password prompt — quote the username so the shell does not expand the $

Step 2 — Install ArgoCD

If you don’t already run ArgoCD, install it (any supported method works):
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Then register the OCI registry as a Helm repository credential so ArgoCD can pull the charts:
kubectl apply -n argocd -f - <<'EOF'
apiVersion: v1
kind: Secret
metadata:
  name: bud-charts-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: helm
  url: registry.bud.studio/charts
  enableOCI: "true"
  username: robot$yourname
  password: <token>
EOF

Step 3 — Choose how to supply configuration

ArgoCD needs your values.yaml (Step 4) and secrets.yaml (Step 5). There are three ways to provide them; pick based on where your secrets end up.
OptionHowSecrets land in…Use for
Config git repo (recommended)A repo you own, joined to the chart with $valuesA repo (encryptable with SOPS)Real installs
Inline valuesObjectValues written directly in the Application manifestThe manifest & etcd, in plaintextQuick / demo, non-secret values only
CLI --valuesargocd app set <app> --values … from your machineArgoCD’s DB only (not git)Imperative single-Application flow, not the ApplicationSet flow below
Why the repo is recommended. The bud chart renders its own Kubernetes Secrets from the values you pass in, so DB passwords, the RSA private key, the registry token and OIDC secrets travel in the values stream. With inline valuesObject those secrets sit in plaintext inside the Application manifest and in etcd — and inline valuesObject also has known bugs when used inside a templated ApplicationSet. Keep secrets in a private repo (optionally SOPS-encrypted). Inline is fine for the non-secret values.yaml if you prefer not to run a repo — see the note at the end of Step 6.
The fastest start is to fork the example repo, BudEcosystem/example-bud-foundry-config — it already contains the two ApplicationSets and the config layout this guide uses:
example-bud-foundry-config/
└── argocd/
    ├── cluster-addons.yaml      # ApplicationSet (Step 6)
    ├── prod-apps.yaml           # ApplicationSet (Step 6)
    ├── bud/
    │   ├── values.yaml          # cluster config: ingress host, storage class
    │   └── secrets.example.yaml # copy to secrets.yaml, then fill in (Step 5)
    └── keycloak/
        └── values.yaml
After forking, set the ref: values source’s repoURL in both ApplicationSets to your fork, then edit the files under argocd/. The ApplicationSets reference these via $values, which resolves to the repo root — hence the paths are $values/argocd/<app>/values.yaml. Keep your fork private if it will hold a real secrets.yaml.
You only edit a handful of values. The bud chart’s defaults already point the application at the in-cluster databases this guide deploys (pooler-rw.postgres, clickhouse-clickhouse.clickhouse, mongodb-rs0.mongodb, valkey-master.valkey). Leave the externalServices.*.host keys at their defaults — those are only changed for the managed-database path in the Deployment Guide.

Step 4 — Cluster configuration (argocd/bud/values.yaml)

The mandatory non-secret values. Everything else falls back to chart defaults.
global:
  ingress:
    hosts:
      # Set ONLY this — all service sub-hosts derive from it.
      root: "bud.yourdomain.com"

ingress:
  enabled: true
  # internal = cert-manager issues + Traefik terminates TLS in-cluster (most setups).
  # external = an upstream LB/WAF terminates TLS; NO certs are issued in-cluster.
  # disabled = plain HTTP.
  https: internal          # external | internal | disabled

storage:
  budmodelRegistry:
    className: "fast-ssd"   # a StorageClass in your cluster — no safe default
    size: 300Gi            # size for the models you plan to host
See the Deployment Guide → Cluster-level config for the full list of ingress/storage options.
TLS with https: internal. The chart annotates its Ingresses with kubernetes.io/tls-acme: "true", which cert-manager’s ingress-shim resolves to its default ClusterIssuer letsencrypt-http01 — created by the cert-manager-issuer addon (in cluster-addons, so make sure it’s enabled). That issuer uses the HTTP-01 challenge, so every ingress host (admin.<root>, app.<root>, gateway.<root>, …) must be publicly resolvable and reachable on port 80 for certificates to issue. If certs stay Ready=False, check kubectl -n bud describe certificate <name> and kubectl -n bud get challenge.

Step 5 — Application secrets (argocd/bud/secrets.yaml)

These are required for a new install and are not wired to external hosts. The per-key reference — what each secret is for and how to generate it — lives in the deployment guide; this is the same set regardless of install method:
Database password consistency. Because the databases run in-cluster, the password you set for, say, Postgres in argocd/bud/secrets.yaml must match the password the postgres addon provisions the user with. Set each database password once and reference the same value in both the addon’s config and argocd/bud/secrets.yaml. A mismatch shows up as backend pods failing to connect after they start.
Storing secrets. The simplest path is a secrets.yaml in a private config repo. To avoid plaintext secrets in git, encrypt the file with SOPS and enable the helm-secrets plugin in your ArgoCD — this is optional hardening, not required to get a working install.

Step 6 — Apply the ApplicationSets

The two ApplicationSets ship in your fork at argocd/cluster-addons.yaml and argocd/prod-apps.yaml. cluster-addons deploys the required in-cluster dependencies (dapr, cert-manager, cert-manager-issuer, postgres, clickhouse, kafka, mongodb, valkey, seaweedfs); prod-apps deploys keycloak and the bud platform in a later sync-wave. Each joins its OCI chart to your config via $values. (Storage and observability add-ons are optional — see Optional add-ons.)
# excerpt from argocd/prod-apps.yaml
      sources:
        - repoURL: registry.bud.studio/charts        # the chart (OCI)
          chart: "{{.name}}"
          targetRevision: "{{.version}}"             # bud 0.14.2, deps 0.1.0
          helm:
            valueFiles:
              - "$values/argocd/{{.name}}/values.yaml"
              - "$values/argocd/{{.name}}/secrets.yaml"
            ignoreMissingValueFiles: true
        - repoURL: https://github.com/YOUR_ORG/example-bud-foundry-config  # ← your fork
          targetRevision: main
          ref: values
Make sure the ref: values repoURL in both files points at your fork (see Step 3), then apply:
kubectl apply -f argocd/cluster-addons.yaml
kubectl apply -f argocd/prod-apps.yaml
ArgoCD now reconciles everything. The addons converge first; the operators may cause a few transient Degraded states that self-heal (see How it works). prod-apps is annotated to apply after the addons.
No config repo? Inline the non-secret values. If you’d rather not fork a config repo, drop the second (ref: values) source and the $values/... valueFiles, and inline the non-secret values.yaml with valuesObject instead:
      sources:
        - repoURL: registry.bud.studio/charts
          chart: bud
          targetRevision: "0.14.2"
          helm:
            releaseName: bud
            valuesObject:
              global:
                ingress:
                  hosts:
                    root: "bud.yourdomain.com"
              storage:
                budmodelRegistry:
                  className: "fast-ssd"
Keep secrets out of the manifest — pre-create them as Kubernetes Secrets the chart consumes, or use the repo path for secrets.yaml. Inline valuesObject is best used in a single Application (not a templated ApplicationSet) to avoid the templating caveats noted in Step 3.

Step 7 — Verify

# Watch ArgoCD reconcile every Application to Synced / Healthy
kubectl get applications -n argocd

# Once healthy, check the platform pods
kubectl -n bud get pods
kubectl -n bud get ingress
All pods should reach Running within ~5–10 minutes of the Applications going Healthy. Backend pods run a Dapr sidecar, so expect 2/2 READY for most of them.

Optional add-ons

These charts are published alongside the required ones but are not part of the base install — whether you need them depends on your cluster and your operational preferences. To enable one, add it to cluster-addons.yaml (an element { name: <addon>, namespace: <addon> }) just like a required addon.
Add-onWhat it providesWhen you need it
openebsA storage provisioner / StorageClass (Mayastor, LVM, ZFS, hostpath)Only if your cluster has no StorageClass — e.g. bare metal with raw disks. Managed clusters (EKS/AKS/GKE) already provide one; skip it.
otelOpenTelemetry operator + a node-level collector for cluster/infra metricsInfra-level observability only. The platform ships its own app-telemetry collector (traces/metrics → ClickHouse), so the application works without this.
signozObservability dashboards UI (traces, logs, metrics)A console for viewing telemetry. Nothing in the platform depends on it.
Storage is still required — just not from openebs. The databases need a working StorageClass either way. openebs is one way to provide it; a cloud CSI driver is another. Set storage.*.className (Step 4) to whichever your cluster offers.

Post-installation

Navigate to your configured domain (e.g. https://admin.bud.yourdomain.com) and log in with the SUPER_USER_EMAIL / SUPER_USER_PASSWORD you set in argocd/bud/secrets.yaml.

Upgrading

Bump targetRevision in the ApplicationSet (e.g. the bud element to a new chart version) and commit. ArgoCD rolls out the change on its next sync.

Uninstalling

kubectl delete -f argocd/prod-apps.yaml
kubectl delete -f argocd/cluster-addons.yaml
# Optionally remove namespaces and PVCs
kubectl delete namespace bud keycloak postgres clickhouse kafka mongodb valkey seaweedfs dapr-system cert-manager
# plus any optional add-on namespaces you enabled: openebs otel signoz

Common pitfalls

  • kubectl apply of an ApplicationSet fails with no matches for kind "ApplicationSet" — your ArgoCD install registered the Application CRD but not the ApplicationSet one (some install variants split them). Install the CRD for your ArgoCD version, and use --server-side — the CRD’s schema exceeds the 256 KB last-applied-configuration annotation limit, so a plain kubectl apply errors with metadata.annotations: Too long:
    kubectl apply --server-side -f \
      https://raw.githubusercontent.com/argoproj/argo-cd/<version>/manifests/crds/applicationset-crd.yaml
    
  • Addon Applications stuck Degraded on first sync — usually the operator CRDs not yet established. ArgoCD selfHeal retries; give it a few minutes. If it persists, sync the operator’s Application manually first.
  • Backend pods crash-loop on DB connection — almost always a database password mismatch between the addon and argocd/bud/secrets.yaml (see the Step 5 warning).
  • registries.registry.bud.studio credentials are required even on clusters that mirror images locally — the chart still creates the imagePullSecret referenced by every Deployment.
  • budmetrics ClickHouse database name must be metrics — it is hardcoded. See the Deployment Guide.

Next steps

Deployment Guide

Per-service secret & config reference; managed-database install path.

Helm Configuration

Full list of chart values and overrides.