Octov0.4.2
Deployment

Helm Chart

Install and configure the Octo Helm chart.

The octo Helm chart in the repo's helm/ directory deploys the full platform — Postgres, NATS, the orchestrator, the log aggregator, and the editor UI — onto any Kubernetes cluster. The chart version is tracked in helm/Chart.yaml and kept in step with repo releases by release-please.

What the chart deploys

ComponentWorkloadPortNotes
Platform (editor UI)Deployment3000Exposed by the Traefik Ingress at ingress.host; proxies the orchestrator and logs APIs through its BFF
OrchestratorDeployment + RBAC8090ClusterIP only; deploys integrations through the Kubernetes API
Log aggregatorDeployment8091Consumes NATS internal.logs into Postgres; serves the logs query API
PostgresStatefulSet + PVC5432Headless ClusterIP; credentials in a generated Secret
NATSStatefulSet (no volume)4222 / 8222Core NATS pub-sub; disable with nats.enabled=false
Schema applierJob (Helm hook)Runs psql -f schema.sql on every install and upgrade
Runtime RBACServiceAccount + RoleLease permissions for integration pods (leader election)

The octo-runtime image is not a chart workload: the chart passes it to the orchestrator as RUNTIME_IMAGE, and the orchestrator deploys one pod set per integration from it at runtime. The schema Job is annotated helm.sh/hook: post-install,post-upgrade with the before-hook-creation delete policy, so it re-runs (idempotently) on every upgrade.

Key values

Defaults live in helm/values.yaml; every knob is documented there. The most important ones:

Images

KeyDefaultPurpose
image.registry""Registry base the per-component repositories are appended to (e.g. us-west1-docker.pkg.dev/PROJECT/octo). Empty uses bare local image names.
image.tagdevTag shared by all five Octo images. Bump it to roll an upgrade.
image.pullPolicyIfNotPresentApplied to all Octo images.
platform.repositoryocto-platformEditor UI image name.
orchestrator.repositoryocto-orchestratorOrchestrator image name.
logs.repositoryocto-logsLog-aggregator image name.
schema.repositoryocto-schemaSchema-applier image name.
runtime.repositoryocto-runtimePer-integration runtime image, passed to the orchestrator as RUNTIME_IMAGE.

Domain, ingress, and TLS

KeyDefaultPurpose
ingress.enabledtrueCreate the editor Ingress. Disabled, reach the editor by port-forwarding the platform Service.
ingress.classNametraefikIngress class.
ingress.hostocto.juancavallotti.comHostname the editor is served at.
ingress.tls.enabledtrueRequest a cert for the editor host.
ingress.tls.secretNameocto-tlsSecret the cert is stored in.
ingress.tls.clusterIssuerletsencrypt-prodcert-manager ClusterIssuer for the editor cert.
orchestrator.baseDomain""Parent domain for per-integration external endpoints ({subdomain}.{baseDomain}). Empty disables external exposure.
orchestrator.clusterIssuer""ClusterIssuer for per-integration TLS certs (HTTP-01, one per host).
wildcardTLS.enabledfalseIssue one wildcard cert for the apex and *.{ingress.host} via DNS-01 and share it across the editor and every integration Ingress. Requires a DNS-01 ClusterIssuer.
wildcardTLS.secretNameocto-wildcard-tlsSecret holding the shared wildcard cert.
wildcardTLS.clusterIssuerletsencrypt-dnsDNS-01 ClusterIssuer for the wildcard cert.

Secrets and auth

KeyDefaultPurpose
postgres.auth.username / .password / .databaseocto / octo / octoDatabase credentials, stored in a chart-managed Secret. Always override the password.
kv.encryptionKey""Base64-encoded 32-byte AES-256 key encrypting KV secret namespaces at rest. Empty rejects secret-namespace writes; plain KV still works. See KV and storage.
auth.oidc.enabledfalseGate the editor behind OIDC SSO (Auth.js). Disabled, the editor is open.
auth.oidc.issuerhttps://auth.eetr.appOIDC issuer URL.
auth.oidc.clientId / .clientSecret""IdP client credentials; the secret lands in the chart's auth Secret.
auth.secret""Auth.js session secret (AUTH_SECRET).
auth.writeRoles""Comma-separated roles allowed to mutate; empty allows any signed-in user.
auth.rolesClaim""ID-token claim carrying roles (Auth.js default roles).

Persistence and scaling

KeyDefaultPurpose
postgres.storage.size5GiPostgres PVC size.
postgres.storage.storageClassName""Empty uses the cluster default StorageClass (local-path on k3s).
platform.replicas / orchestrator.replicas / logs.replicas1Replica counts. The log aggregator scales safely (NATS queue group).
nats.enabledtrueDeploy the NATS broker; when off, live event streams fall back to polling. See Event bus.
runtime.servicesModulek8sRuntime-services backend injected into integration pods: k8s (Lease leader election + orchestrator KV) or standalone (in-process noop). Cluster deploys want k8s.

Install

The chart is published as an OCI artifact. In the reference GCP deployment, Cloud Build pushes it to your Artifact Registry on every version tag (see Releases and upgrades); you can also publish it yourself from a checkout:

# Lint and package into dist/octo-<version>.tgz
task helm:package

# Push to an OCI registry (Artifact Registry shown)
helm registry login us-west1-docker.pkg.dev -u oauth2accesstoken -p "$(gcloud auth print-access-token)"
task helm:push IMAGE_BASE=us-west1-docker.pkg.dev/PROJECT/octo

Then install from the registry, pointing the image values at where you pushed the images (task images:push IMAGE_BASE=… TAG=…):

helm install octo oci://us-west1-docker.pkg.dev/PROJECT/octo/octo \
  --version <chart-version> \
  --namespace octo-dev --create-namespace \
  --set image.registry=us-west1-docker.pkg.dev/PROJECT/octo \
  --set image.tag=v0.2.0 \
  --set ingress.host=octo.example.com \
  --set postgres.auth.password=<strong-password>

The chart version comes from helm/Chart.yaml — list available versions with helm show chart oci://…/octo. You can also install straight from a checkout with helm install octo ./helm -f my-values.yaml.

The chart assumes Traefik as the ingress class and cert-manager with a ClusterIssuer for TLS — both ship with the k3s bootstrap in the GCP reference deployment. On other clusters, install cert-manager and adjust ingress.className, or disable TLS.

In the GCP reference deployment, Terraform owns the Helm release — do not run helm upgrade against it by hand. Apply the release root (or task deploy TAG=…) instead.

Upgrade

Upgrades are a normal helm upgrade with a new chart version and image tag:

helm upgrade octo oci://us-west1-docker.pkg.dev/PROJECT/octo/octo \
  --version <new-chart-version> \
  --namespace octo-dev \
  --reuse-values \
  --set image.tag=v0.3.0

What happens on an upgrade:

  • A changed image.tag rewrites the pod templates, so the platform, orchestrator, and logs Deployments roll automatically.
  • The schema hook Job re-runs and applies sql/schema.sql; the schema is idempotent (IF NOT EXISTS / ON CONFLICT), so this is safe on every upgrade.
  • Postgres and its PVC are untouched when only the tag moves — your data survives the upgrade.
  • Integrations already deployed keep running on the runtime image they were deployed with; redeploy them from the editor to pick up a new octo-runtime.

On this page