Skip to content

Self-hosting

Deployment overview

Run Golden Reports on your own infrastructure - what to deploy, what to operate, and what to expect.

Golden Reports is a Kubernetes-native application. The official deployment artifact is the golden-reports Helm chart, which renders every workload, its dependencies, and the routing in front of them. This page is the high-level "what you're deploying" view. The chart's reference is on Helm chart reference.


What you'll deploy

A standard deployment consists of:

Application workloads

WorkloadReplicas (default)Purpose
api2Platform API - control plane
query-engine2Query execution service
data-provider2Connector host
manager2Web UI

Each workload runs its own container image; the chart wires them up. Image references resolve through global.imageRegistry so air-gapped deployments can mirror them into a private registry.

Backend components (api, query-engine, data-provider, plus the migrations Job) share a single backendVersion. The manager (the web UI) versions independently as frontendVersion. This separation lets you ship UI updates without redeploying the API and vice versa.

Operational dependencies

DependencyBundled by chart?Notes
PostgreSQLYes (via the CloudNativePG operator)Or point to an external instance with postgresql.enabled: false + externalDatabase.
RedisYesOr use externalRedis.
Object storageNoUsed for assets and exports. S3-compatible (AWS S3, MinIO, GCS via S3 API).
Identity providerExternal, alwaysEmail sign-up and OAuth (Google, Microsoft, etc.). Configured per deployment.

The chart's bundled Postgres mode uses a CloudNativePG cluster - you'll need the CNPG operator pre-installed in the cluster.

Network routing

The chart can render either a classic Ingress or a Gateway API HTTPRoute per service (api and manager). Both gate independently; enabling both is almost certainly wrong because you'd get two parallel routes to the same Service. Pick the one your cluster supports.

Optional cert-manager integration handles TLS certs (Let's Encrypt or your internal CA) - see the certManager block on each ingress or httpRoute.

One-shot Jobs

  • Schema migrations Job runs database migrations before the API starts. The chart wires it as a Helm pre-install/pre-upgrade hook so it always runs before the API rolls.

Prerequisites

Before installing:

  • Kubernetes 1.27+ with a CNI that supports NetworkPolicy if you intend to enable network isolation (Calico, Cilium, Weave).
  • Helm 3.13+.
  • CloudNativePG operator in the cluster (only when bundled Postgres is enabled - the default).
  • An Ingress controller or a Gateway API controller plus CRDs (Istio, Envoy Gateway, etc.).
  • A container registry that can pull the platform's images. Air-gapped environments can mirror them into a private registry and set global.imageRegistry.
  • An identity provider configured for the deployment (email sign-up plus OAuth providers - Google, Microsoft, etc.).
  • A persistent volume class for the Postgres and Redis PVCs (or override global.storageClass).

A first install

The chart's name is golden-reports. Install from a release artifact:

helm upgrade --install golden-reports oci://registry.wolfware.dev/charts/golden-reports \
  --namespace golden-reports --create-namespace \
  --set frontendVersion=<frontend-version> \
  -f values.yaml

frontendVersion is a required override - it has no sensible default because frontend releases are decoupled from the chart version. backendVersion falls back to Chart.AppVersion when blank.

A minimal values.yaml for a development cluster:

backendVersion: ""               # uses chart's appVersion
frontendVersion: "<frontend-version>"

components:
  api:
    ingress:
      enabled: true
      hosts:
        - host: api.golden-reports.local
          paths:
            - path: /
              pathType: Prefix
  manager:
    apiUrl: ""                   # relative routing
    ingress:
      enabled: true
      hosts:
        - host: app.golden-reports.local
          paths:
            - path: /
              pathType: Prefix

postgresql:
  enabled: true
  cnpg:
    instances: 1
    storage:
      size: 20Gi

redis:
  enabled: true

For production you'll want at minimum: TLS via cert-manager, the bundled Postgres scaled to 3 instances, and an explicit existingSecret for Redis auth.


Sizing

A defensible default for a single small-tenant deployment:

ComponentCPU reqMemory reqReplicas
api250m512Mi2
query-engine250m256Mi2
data-provider250m256Mi2
manager50m64Mi2
postgresql (CNPG)500m1Gi1 (dev) / 3 (prod)
redis100m128Mi1

Real load varies wildly by report volume; enable HPAs (autoscaling.enabled: true per component) once you have traffic to measure. The query-engine is the most likely component to bottleneck - large fetches consume CPU during post-processing - so it's the first place to scale.


What you operate

Day-2 responsibilities:

  • Backups. Postgres backups via CNPG (S3 or another supported backend). Asset object storage backups via your bucket's native tools.
  • Upgrades. Backend and frontend version trains move independently. The chart's migrations Job runs on every helm upgrade; failures block the API rollout.
  • Secrets. Database password, Redis password, identity-provider configuration, image pull secrets. The chart accepts each as an existingSecret reference; let your secret manager (SealedSecrets, External Secrets, Vault) own the source of truth.
  • TLS. cert-manager integration is built-in. Without it, supply tls: blocks directly.
  • Observability. All workloads expose Prometheus metrics on the standard port and OpenTelemetry trace context propagates through the request path. See Observability.
  • Plugin management. Connector and block plugins are managed through the in-product Marketplace; ops involvement is limited to making sure outbound network to the Marketplace CDN is allowed.

What you do not operate

A short list to set expectations:

  • Authentication. The identity provider handles users, sessions, and OAuth.
  • CDN for plugin distribution. Marketplace plugins are served from the platform's CDN.
  • Editor bundle hosting. The Manager image already includes the report editor.
  • Per-tenant data isolation. Multi-tenancy is structural - you don't run one cluster per tenant.

Air-gapped and private deployments

A few flags accommodate restricted environments:

  • global.imageRegistry: "registry.example.com" - mirrors all platform images through your registry.
  • global.imagePullSecrets: [{ name: regcred }] - applies to every Pod.
  • externalDatabase.* / externalRedis.* - point to your managed Postgres/Redis instead of the bundled ones.
  • networkPolicy.enabled: true - generate restrictive NetworkPolicies per workload.
  • Side-loaded connectors - mount a directory of .wasm blobs into the data provider Pod via env/envFrom and volumeMounts (extra Pod-level overrides go through component env and external secret refs).

Marketplace access can be turned off entirely for fully air-gapped environments - plugins are then installed by uploading bundles to the workspace's plugin registry directly. Hardening profiles for restricted environments are available on request through your account team.


What's not (yet) supported

For honesty:

  • Cross-region active-active. A single Kubernetes deployment is a single region. Multi-region with shared state isn't supported today; multi-region with per-tenant pinning is achievable by running multiple deployments behind a routing layer.
  • Per-tenant resource isolation. The chart deploys a single set of workloads serving all tenants. Customers needing physical isolation per tenant run separate Helm releases.

Next

Previous
Extensibility model