Self-HostingDeploymentKubernetes (Helm)

Kubernetes (Helm)

Deploy Litefuse on Kubernetes with the official Helm chart from litefuse/litefuse-k8s. This is the recommended way to run Litefuse in production when your team operates Kubernetes.

The chart deploys the Litefuse web and worker applications together with all backing stores. Every store ships bundled by default, so a single helm install yields a working stack; each store can be pointed at an external or managed service independently.

ComponentBundled defaultExternal option
Apache Doris (analytics)DorisCluster CR managed by the bundled Doris Operatordoris.deploy=false + doris.host
PostgreSQL (transactional)groundhog2k/postgres sub-chartpostgresql.deploy=false + postgresql.host
Redis (cache / queues)Valkey sub-chartredis.deploy=false + redis.host (standalone / cluster / sentinel)
S3 (blob storage)SeaweedFS all-in-one sub-charts3.deploy=false + s3.endpoint / AWS / Azure / GCS

Prerequisites

  • Kubernetes 1.24+
  • Helm 3.18+
  • A default StorageClass — Doris FE/BE, PostgreSQL, Valkey, and SeaweedFS all request PVCs by default (or set the per-store storageClass fields)
  • Cluster capacity for the default single-replica footprint: roughly 6.5 CPU / 13Gi of requests and ~300Gi of volumes. For a laptop or small dev cluster, start from examples/values-dev.yaml, which roughly halves this.

Quick Start

The published package bundles all sub-chart dependencies — no helm repo add needed:

helm install litefuse oci://ghcr.io/litefuse/litefuse --version 1.0.0 \
  -n litefuse --create-namespace

Discover the configuration without cloning the repository:

helm show values oci://ghcr.io/litefuse/litefuse --version 1.0.0   # all options, annotated
helm show readme oci://ghcr.io/litefuse/litefuse --version 1.0.0   # full reference

Install from source

git clone https://github.com/litefuse/litefuse-k8s.git && cd litefuse-k8s
helm dependency update charts/litefuse
helm install litefuse charts/litefuse -n litefuse --create-namespace

For a development-sized install:

helm install litefuse charts/litefuse -n litefuse --create-namespace \
  -f examples/values-dev.yaml

What to expect on a fresh install

The first install brings in the Doris Operator CRDs, then creates a DorisCluster custom resource. Doris FE/BE take a few minutes to form a cluster, and the web/worker pods restart until the schema migrations succeed — this is expected. Watch progress with:

kubectl get doriscluster -n litefuse
kubectl get pods -n litefuse -w

The install is done when the DorisCluster reports FE/BE available and the web/worker pods are Running and Ready.

Access the UI

Without an ingress:

kubectl port-forward -n litefuse svc/litefuse-web 3000:3000

Open http://localhost:3000 and sign up for the first account. For a real deployment, enable the ingress and set litefuse.nextauth.url to the canonical external URL. After creating your accounts, disable public sign-up with litefuse.features.signUpDisabled=true.

Configuration

All options live in values.yaml with inline documentation; the chart renders them into environment variables on the web/worker pods. Three rules:

  1. Prefer the structured fields (litefuse.*, postgresql.*, redis.*, doris.*, s3.*). They are validated at render time and wired into the right Secrets automatically.
  2. litefuse.additionalEnv is the escape hatch for anything without a structured field. Setting the same variable both ways is rejected at render time.
  3. Litefuse environment variables use the LITEFUSE_ prefix. A stale LANGFUSE_-prefixed variable is silently ignored — mind this when migrating values from langfuse-k8s.

Every sensitive field accepts either an inline value or a reference to an existing Kubernetes Secret:

someSecretField:
  value: ""                # inline (fine for testing)
  secretKeyRef:            # preferred: reference your own Secret
    name: my-secret
    key: my-key

Canonical URL

Required for any real deployment:

litefuse:
  nextauth:
    url: https://litefuse.example.com

Security keys

KeyEnv varFormat
litefuse.saltSALTany string (openssl rand -base64 32)
litefuse.encryptionKeyENCRYPTION_KEY256-bit hex (openssl rand -hex 32)
litefuse.nextauth.secretNEXTAUTH_SECRETany string (openssl rand -base64 32)

Left empty, all three are auto-generated on first install and persisted in the <release>-app Secret, which is kept across uninstalls. Losing SALT or ENCRYPTION_KEY is unrecoverable — API keys and encrypted data become unreadable.

Pin them for production, especially under GitOps where helm template cannot look up the generated Secret:

litefuse:
  salt:
    secretKeyRef: { name: litefuse-app-credentials, key: salt }
  encryptionKey:
    secretKeyRef: { name: litefuse-app-credentials, key: encryption-key }
  nextauth:
    secret:
      secretKeyRef: { name: litefuse-app-credentials, key: nextauth-secret }

Ingress

Only the web Service is exposed; the worker has no HTTP endpoint.

litefuse:
  ingress:
    enabled: true
    className: nginx
    annotations:
      # SDK batch ingestion posts can be large — do not cap at the nginx 1m default
      nginx.ingress.kubernetes.io/proxy-body-size: 100m
    hosts:
      - host: litefuse.example.com
        paths:
          - path: /
            pathType: Prefix
    tls:
      enabled: true
      secretName: litefuse-tls

SSO and SMTP

SSO providers (auth0, cognito, azureAd, github, gitlab, google, keycloak, okta, workos, and more) are configured under litefuse.auth.providers, and transactional email under litefuse.smtp. See the chart reference for details.

Connecting External Stores

Each bundled store follows the same pattern: <store>.deploy: false plus connection and auth fields. Validation fails at render time if a required endpoint is missing.

External Doris

doris:
  deploy: false
  operator:
    enabled: false
  host: my-doris-fe.example.com   # FE endpoint (MySQL protocol + HTTP)
  httpPort: 8030
  queryPort: 9030
  database: litefuse
  auth:
    username: admin
    existingSecret: my-doris-credentials
    existingSecretKey: password
  replicationNum: 3   # keep 3 with >= 3 BEs

A single-BE external Doris needs replicationNum: 1 — the default of 3 makes every CREATE TABLE fail when fewer backends are alive.

External PostgreSQL

postgresql:
  deploy: false
  host: my-postgres.example.com
  port: 5432
  auth:
    username: litefuse
    database: litefuse
    existingSecret: my-postgres-credentials
    secretKeys:
      userPasswordKey: password

For managed/cloud Postgres, also see postgresql.directUrl (separate connection string for migrations), and postgresql.shadowDatabaseUrl (required when the database user lacks CREATE DATABASE permission).

External Redis

redis:
  deploy: false
  host: my-redis.example.com
  port: 6379
  auth:
    username: "default"
    existingSecret: my-redis-credentials
    existingSecretPasswordKey: password

Redis Cluster (redis.cluster.enabled + nodes) and Sentinel (redis.sentinel.*) are also supported. Configure maxmemory-policy noeviction on any external Redis/Valkey — Litefuse loses job data under eviction.

External S3 / blob storage

s3:
  deploy: false
  bucket: my-litefuse-bucket
  region: eu-west-1
  forcePathStyle: false
  accessKeyId:
    secretKeyRef: { name: my-s3-credentials, key: access-key-id }
  secretAccessKey:
    secretKeyRef: { name: my-s3-credentials, key: secret-access-key }

Leave accessKeyId/secretAccessKey empty to use the pod’s ambient identity (IRSA / instance profile). For MinIO or another S3-compatible gateway, additionally set s3.endpoint and change forcePathStyle to true (the AWS example above uses false). Azure Blob and GCS are supported via s3.storageProvider.

Example Values Files

Ready-to-use values files live under examples/:

FilePurpose
values-dev.yamlLaptop / small dev cluster: single replicas, reduced resources and volumes
values-production.yamlHA Doris (3 FE / 3 BE, replication 3), scaled web+worker, ingress + TLS, pinned secrets
values-external-doris.yamlConnect to a managed / existing Doris cluster
minimal-installation/Full bundled stack with every credential sourced from one pre-created Secret (GitOps-friendly)

Scaling

  • Each web/worker replica is one Node.js process (~1 core at saturation) — scale out, not up:

    litefuse:
      web:
        replicas: 6
      worker:
        replicas: 12
  • HPA, KEDA, and VPA blocks exist for both web and worker (litefuse.web.hpa.*, litefuse.worker.keda.*, …).

  • PodDisruptionBudgets are created by default (maxUnavailable: 1).

  • For production Doris HA, use 3 FE / 3+ BE replicas with doris.replicationNum: 3 — see examples/values-production.yaml.

  • The Doris Operator installs cluster-scoped resources — run only one operator per Kubernetes cluster. For a second Litefuse release, set doris.operator.enabled=false and share the existing operator.

  • Keep the whole stack on UTC (litefuse.timezone, the default) — Doris date partitioning depends on it.

Upgrading

helm upgrade litefuse oci://ghcr.io/litefuse/litefuse --version <ver> -n litefuse
  • The web/worker images default to the chart’s appVersion; pin litefuse.image.tag to control the app version independently. The web pod runs Postgres/Doris migrations on startup.
  • Helm never upgrades CRDs. When a chart upgrade bumps the Doris Operator dependency, apply its updated CRDs manually (kubectl apply -f from the operator release) before upgrading.

Troubleshooting

SymptomCause / fix
web/worker CrashLoopBackOff in the first minutesExpected while Doris FE/BE form a cluster and migrations retry. Watch kubectl get doriscluster; investigate only if it persists after Doris is Ready
helm template fails: Doris Operator CRD not foundRendering offline or against a fresh cluster. Pass --api-versions doris.selectdb.com/v1/DorisCluster or set doris.crdCheck=false
Doris FE pod OOMKilleddoris.cluster.fe.jvmHeapMb too close to the container memory limit — keep ~2Gi+ headroom
CREATE TABLE fails with replication errorsdoris.replicationNum exceeds alive BEs. Single-BE clusters need replicationNum: 1
Worker exits: missing LITEFUSE_S3_EVENT_UPLOAD_BUCKETA stale LANGFUSE_-prefixed env var from a langfuse-k8s migration — Litefuse only reads the LITEFUSE_ prefix
Jobs disappear under memory pressure (external Redis)The external Redis/Valkey must run maxmemory-policy noeviction

See the chart README for the full list.

Uninstalling

helm uninstall litefuse -n litefuse

Kept intentionally after uninstall:

  • PVCs for Doris FE/BE, PostgreSQL, Valkey, and SeaweedFS (the data)
  • The <release>-app Secret (SALT / ENCRYPTION_KEY / NEXTAUTH_SECRET) and generated store-credential Secrets — they unlock those volumes

A reinstall with the same release name picks all of this up and comes back with the data intact. Delete the PVCs and Secrets manually only if you also mean to discard the data.

Was this page helpful?