Skip to main content
Conduit ships a Helm chart that covers both deployment tiers — embedded (a single replica owning a persistent volume) and active-active PostgreSQL — from one set of values. This page covers the chart first, then complete raw manifests for clusters that don’t use Helm. If you haven’t picked a tier, start with Deployment Tiers.

Before you start

  • Helm 3.8+ (OCI registry support) — or skip to the raw manifests.
  • A ReadWriteOnce block-storage StorageClass (EBS, GCE PD, Azure Disk, Ceph RBD, local-path). Never network filesystems (NFS, EFS, Azure Files) — Conduit’s embedded database is not safe on them.
  • An Ingress controller or LoadBalancer terminating TLS. AI clients require HTTPS for OAuth.

Secrets first

Conduit encrypts stored secrets with a key you provide. Create it as a Kubernetes Secret before installing, and keep a copy somewhere safe (a password manager or secret manager) — stored secrets are unrecoverable without it:
The chart requires this Secret (existingSecret.name) and never generates one itself: a template-generated key would silently regenerate under GitOps tooling that renders without cluster access, losing every stored secret. A Secret also keeps the key out of data-volume snapshots, so a leaked backup alone can’t decrypt anything.

Install with Helm

A minimal values.yaml for the embedded tier:
That renders the same shape as the raw manifests below: a PVC, a single-replica Deployment with the Recreate strategy (the data volume is ReadWriteOnce, so the old pod must release it before the new one starts), a Service, and the Ingress. CONDUIT_BASE_URL defaults to https://<ingress.host>; set baseURL if you terminate TLS somewhere the chart can’t see. Each chart release pins its matching vX.Y.Z image, so --version is also how you choose the Conduit version.

Active-active on PostgreSQL

With an operator-supplied PostgreSQL 14+ (see Deployment Tiers), add the connection URL to your Secret and point the chart at its key:
Configuring the database is the tier switch — the chart derives the rest: The chart’s Service and Ingress carry no sticky-session settings, and none are needed: any replica serves any request. On a fresh PostgreSQL database Conduit refuses to start without a bootstrap password, so set existingSecret.adminPasswordKey on first install and remove it (with a helm upgrade) once setup completes. Concurrent boots are safe: migrations and startup sweeps coordinate through database locks. If your database URL lives in a Secret managed elsewhere (e.g. written by a PostgreSQL operator), set database.secretName too — it defaults to existingSecret.name.

IAM authentication to RDS

On EKS with RDS or Aurora, CONDUIT_DATABASE_AUTH=rds-iam replaces the password in the database URL with per-connection IAM tokens. The AWS side — enabling IAM auth, the rds_iam grant, the connect policy — is on Deployment Tiers; the chart wires the Kubernetes half. Mount the RDS CA bundle so verify-full can validate the server certificate:
with the database URL in the Secret carrying no password and naming the mounted bundle:

Values reference

The chart deliberately models only what these manifests need. Every other CONDUIT_* variable in the configuration reference goes through extraEnv / extraEnvFrom, which also fit External Secrets or Vault workflows:
Run helm show values oci://ghcr.io/pipedreamhq/charts/conduit for the full annotated list (pod placement, security contexts, service account, PDB). Uninstalling the release keeps the data PVC (helm.sh/resource-policy: keep) — the volume is the database, so deleting it is a deliberate kubectl action, never a side effect of helm uninstall.

Private registries and air-gapped installs

A release is exactly two artifacts — the image and the chart, with no sidecars, init containers, or subcharts pulling images of their own — so copying both into your registry is a complete mirror:
Keep the image tag unchanged: a released chart defaults to the vX.Y.Z image tag matching its own version, so a mirror that preserves tags needs no image.tag override. If your registry re-tags, set image.tag. Then install from your registry. image.repository carries the registry host, so pointing at the mirrored image is the only values change — plus pull credentials if your registry requires them:
  • A registry that proxies ghcr.io as a pull-through cache works the same way with no copy step — set image.repository to the proxied path.
  • If your network can’t reach ghcr.io at all, build the image from source and push it to your registry; everything else here applies unchanged.
  • With the raw manifests there is no chart to mirror: copy the image and edit the pinned image: line to match.
Once running, Conduit makes outbound requests only for the features you configure — there is no phone-home, license check, or update poll — so a fully air-gapped instance works as long as its connectors and identity providers point at hosts it can reach. Network Access lists every host and when it is contacted.

Raw manifests (without Helm)

Complete, working manifest sets for both tiers — the same shapes the chart renders.

Embedded tier

Active-active on PostgreSQL

Relative to the manifests above, the Deployment becomes stateless and scales horizontally:
What changed and why:
  • No PVC, no volume mount, RollingUpdate — all state lives in PostgreSQL, so updates are zero-downtime.
  • CONDUIT_DATABASE_URL, CONDUIT_ENCRYPTION_KEY, and (pre-setup) CONDUIT_ADMIN_PASSWORD come from Secrets. Conduit refuses to start without the key, and without the password on a fresh database — the failure messages say why.
  • Readiness (/healthz/ready) verifies database connectivity, so the Service ejects an instance that lost PostgreSQL; liveness stays process-local. Concurrent boots are safe — migrations and startup sweeps coordinate through database locks.
  • No session affinity. Any replica serves any request — including the answer to an in-band MCP prompt or a request cancellation, which Conduit hands to the replica holding the call — so the Service and Ingress need no sticky-session settings.

Notes (both paths)

  • CONDUIT_BASE_URL must match the Ingress host — it’s what OAuth callbacks and MCP discovery hand to clients.
  • Set CONDUIT_TRUSTED_PROXIES to your pod CIDR (kubectl cluster-info dump | grep -m1 cluster-cidr). Conduit only honors X-Forwarded-For from proxies you declare, and an in-cluster ingress controller is not trusted by default; without it, audit entries and per-IP rate limits collapse onto the ingress address. With the chart, set it via extraEnv (the example above). See client IP attribution.
  • MCP clients hold long-lived SSE connections. If your ingress enforces a short proxy read timeout, raise it for this host — e.g. ingress-nginx: nginx.ingress.kubernetes.io/proxy-read-timeout: "3600".
  • Any L7 load balancer works with its defaults. Replicas need no session affinity (see Deployment Tiers). An AWS ALB can stay on round-robin with stickiness off; Conduit writes a keep-alive frame on every idle MCP stream at least every 30 seconds, inside the ALB’s default 60-second idle timeout.
  • On AZ-bound storage (EBS and friends), use a StorageClass with volumeBindingMode: WaitForFirstConsumer so the volume is created in the AZ the pod actually schedules to.
  • Prometheus metrics are opt-in: metrics.enabled: true with the chart, or (raw manifests) CONDUIT_METRICS_ADDR=0.0.0.0:9464 plus a matching metrics container port. Scrape at the pod IP; keep the port out of the Service and Ingress. See Monitoring.
  • A load balancer with its own target health checks (an AWS ALB, a cloud LB) is usually the slowest link in an embedded-tier upgrade: point its check at /healthz/ready, tighten the interval, and shorten any deregistration/draining delay — the old target is already dead when it deregisters, so draining buys nothing.

Validate the deployment

A green readiness probe means the pod serves traffic and can reach its database. To confirm the deployment end to end, walk the same path a user will — each step exercises a different piece of configuration:
  1. Probes — /healthz (process) and /healthz/ready (database connectivity) return 200 through your Service.
  2. Sign in — open https://<your-host> in a browser and complete first-run setup (or sign in). This proves TLS, the Ingress, and session cookies.
  3. Connect an AI client — add https://<your-host>/mcp to any MCP client and complete the sign-in it opens. This is the sharpest test of CONDUIT_BASE_URL: the OAuth flow round-trips through the externally reachable address, so a mismatch fails here and nowhere earlier. The client should list Conduit’s built-in tools.
  4. Call a tool — any built-in tool (ask the client “what session am I using?”), then confirm the call appears in the audit log and usage dashboard. That proves the whole loop: authorization, execution, recording.
  5. Check IP attribution — if the audit entries show your ingress or load-balancer address as the client IP, set CONDUIT_TRUSTED_PROXIES (see Notes).
Adding an identity provider and a first connector after that follows Single Sign-On and Connectors.

Upgrades

Read the release’s Upgrade notes in the changelog first, then upgrade deliberately: helm upgrade --version X.Y.Z with the chart (which moves the image in lockstep), or bump the pinned image tag with raw manifests. On the embedded tier the Recreate strategy means an upgrade takes the seconds between pod stop and ready — sessions and tokens live in the database, so nobody is signed out and MCP clients reconnect on their own. To track releases automatically, run your rollout from CI: watch the :stable tag (or GitHub releases) and apply the new pinned version when one appears, recording it in your deploy annotations so rollout history maps to releases.