Skip to main content
This page is intended for integrators who install Popsink in their own Kubernetes cluster. The chart deploys a self-hosted Popsink data plane — the runtime that moves data from your sources to your targets. It connects to a control plane (managed by Popsink at control-plane.popsink.com, or your own) which orchestrates and monitors the deployment.

Architecture overview

The chart deploys the following components: Connector workers are not part of the chart: the data-plane creates them as pods in its own namespace at runtime. You can disable any sub-component and bring your own:
  • External Kafkakodansu.enabled=false, configure defaultKafka.*
  • External Schema Registrykora.enabled=false, configure schemaRegistry.*
  • External PostgreSQLpostgresql.enabled=false, configure externalDatabase.*
kodansu was previously called tansu, and the chart still reads a tansu: block for backwards compatibility (anything under kodansu: wins). New values files should use kodansu:.Two components that appeared in earlier versions of this page — karapace and kafka-ui — no longer exist in the chart. They were replaced by kora and kotatsu respectively. A values.yaml that still sets karapace.* or kafkaUi.* is silently ignored.
The chart can render an Ingress (ingress.enabled, off by default), but it never installs an ingress controller: you still need your own (Traefik, NGINX, Istio…) and a DNS record pointing at it. Both options — chart-rendered or bring-your-own — are covered under Ingress below.

Prerequisites

Cluster

Access to Popsink images

All images are published to a private GAR registry:
Popsink will provide you with a service-account JSON token to pull these images.
Let the chart create the imagePullSecret for you:

Onboarding flow (control plane)

Before installing the chart, you need a deployment ID and a deployment JWT token issued by the control plane.
1

Open the control plane

Log into https://control-plane.popsink.com (or your own control plane).
2

Create a self-hosted deployment

Open Deployments → New deployment and pick Self-hosted.
3

Fill the wizard

  • Optional pre-fill of PostgreSQL credentials (not stored).
  • Retention strategy — pick S3-compatible storage (recommended) or PostgreSQL.
  • FQDN — the public URL where the data plane will be reachable (e.g. https://popsink.your-company.com).
4

Copy the values snippet

The wizard outputs a values-control-plane.yaml snippet containing controlPlaneUrl, deploymentId and deploymentJwtToken. Use these values verbatim — they identify and authenticate your data plane against the control plane.
5

Wait for connection

Keep the wizard open. After helm install, the control plane will switch from Awaiting connection… to Connected once the data plane registers.

Required secrets to generate yourself

Beyond the values handed by the control plane, you must generate four secrets locally:
These four secrets encrypt connector credentials, sign user sessions and protect the admin login. Lose them and you lose access to your stored connector configs. Back them up in your secret manager.connectorConfigEncryptionKey.key must never be rotated: every stored connector configuration is encrypted with it and becomes unreadable if it changes. Each deployment gets its own — never share one across deployments.
If you prefer to manage secrets out of band (Vault, Sealed Secrets, External Secrets Operator…), set the corresponding existingSecret field instead.

Schema registry database (Kora)

Kora is Popsink’s schema registry: every connector registers the structure of what it reads there, and every target resolves schemas from it. It is enabled by default and it requires its own PostgreSQL role and database, which the chart does not create for you.
This is the step most first installs miss. The bundled PostgreSQL provisions the data-plane’s own role and database (postgresql.auth.*) and nothing else, so leaving kora.database unset points Kora at a role that exists nowhere. From chart 0.1.0-alpha.162 the install aborts with the instructions below; on earlier charts it installs a pod that crash-loops on:
Credentials can also come from a secret rather than a literal — use kora.database.existingSecret with secretKeys.password, or secretKeys.url for a full connection URL. The three sources are mutually exclusive: an existingSecret combined with a literal password or url is rejected at render time. Kora also supports an Oracle backend: kora.database.backend: oracle, port 1521, and database set to the service name (e.g. FREEPDB1). The chart selects the matching image automatically.

Stream browser (Kotatsu)

Kotatsu is optional and disabled by default. It is a read-only browser over the objects the broker wrote to S3, and it backs two things in the UI:
  • search, pagination and the timestamp column on the datamodel Stream tab;
  • the per-subscription target lag rows on the pipeline latency view.
Without it, the Stream tab falls back to a live Kafka read (no search, no pagination) and the target-lag rows are simply absent. Pipelines, connectors, subscriptions and delivery are unaffected — it is safe to leave disabled in production. Because it reads the bucket the broker writes, it only means anything with S3 retention. To enable it:
That is the entire configuration. Bucket, cluster id, region, endpoint and credentials all default to the broker’s own (kodansu.storage.*, kodansu.clusterId) — the only combination that can work, since the two read and write the same objects. Set kotatsu.s3.* only to point Kotatsu at a replica of the bucket or at a separate read-only credential. On EKS with IRSA, leave the keys empty and annotate kotatsu.serviceAccount.annotations with the role ARN.
On charts before 0.1.0-alpha.162 Kotatsu defaulted to enabled, so an install that had not opted into S3 aborted with kotatsu.s3.bucket must be provided when kotatsu is enabled. Setting kotatsu.enabled: false is the correct workaround on those versions.

Broker storage (S3)

Kodansu is a stateless Kafka broker that stores log segments in an object store. kodansu.storage.engine decides where records live, and both it and kodansu.storage.aws.region are required by the chart.
The bucket must exist, be writable by the configured identity, and ideally have object versioning enabled.
Before bumping the broker image on an existing bucket, read the upgrade notes on tansu.image.tag in the chart’s values.yaml. Two of the tags cross an object-layout boundary and need a quiesce-and-flip rather than a rolling upgrade.
PostgreSQL retention is simpler to operate but does not scale the same way, and rules out Kotatsu (there is no bucket to browse).
If you don’t want the in-cluster broker, set kodansu.enabled=false and kora.enabled=false, then point the data plane at your existing Kafka:

Ingress

The chart’s built-in ingress.enabled flag is off by default and we recommend leaving it that way: ingress in production usually needs company-specific annotations (cert-manager, WAF, allow-lists). Provide your own Ingress resource that exposes:
  • the data-plane HTTP service (<release>-data-plane, port 80),
  • on the FQDN you declared in the control plane (ingressUrl).
Example with NGINX + cert-manager:
If you want the chart to render an Ingress for you, set ingress.enabled=true and configure ingress.hostname, ingress.ingressClassName, ingress.tls.
The value of ingressUrl in the chart must match the public URL the control plane redirects users to (it is also used for OAuth-style callbacks):

Putting it together — minimal values.yaml

values.yaml
For production, swap the in-cluster Postgres for a managed one:
externalDatabase.user and externalDatabase.database are not guarded by the chart: left empty they render, install, and the data plane then crash-loops on an empty DB_USER. The database must exist before the install — the data plane runs its own migrations on startup.

Install

Use helm search repo or check the chart’s Chart.yaml (version:) to pin the chart version. Pinning avoids surprise upgrades.
Watch the rollout:
When all pods are Ready, head back to the control-plane deployment page — the status should flip from Awaiting connection… to Connected within a minute. Open ingressUrl and log in with the adminCredentials you set.

Production checklist

  • Pin the chart version (--version) and the application image (image.tag) — never deploy latest.
  • Use external PostgreSQL (postgresql.enabled=false, externalDatabase.*) backed by managed snapshots, not the in-cluster Bitnami chart.
  • Use external S3 with versioning + lifecycle policy for the broker.
  • Set explicit resources.requests/limits on every component (defaults target small-medium clusters; tune for your workload).
  • Configure replicaCount ≥ 2 on data-plane (default), keep tansu.replicaCount=3 (default).
  • Enable pdb.create: true (default) — at least 1 pod stays during node drains.
  • Provide imagePullSecrets via a sealed secret / external secrets controller, not plain values.
  • Back up the four secrets (admin credentials, JWT secret, Fernet key, DB password) in your secret manager.
  • Keep allowDesignLogin: false (default) and pipelineMode: false unless explicitly told otherwise — these are dev-only switches.
  • Ingress: TLS-only, cert-manager (or equivalent), restrict source ranges if your data plane is internet-exposed only for known IPs.

Upgrade

The data plane runs DB migrations on startup. Watch a pod’s logs:

Uninstall

By default the PostgreSQL PVC and the broker’s S3 data are kept (postgresql.primary.persistentVolumeClaimRetentionPolicy.whenDeleted=Retain, S3 buckets are external). Delete them manually if you want a clean slate:

Troubleshooting

For deeper logs:

Reference — most useful values

A full list lives in values.yaml (annotated with @param blocks). The most common knobs are:

Further reading

Installation prerequisites

Hardware, ingress and storage requirements for a Popsink-ready cluster.

Self-hosted onboarding

The control-plane wizard that issues your deploymentId and JWT token.

Deployments and environments

How to map deployments onto your regions, networks and staging tiers.