Skip to content

Apache Superset

Deploy Apache Superset on Kubernetes — a modern business intelligence platform with 60+ database connectors, interactive dashboards, SQL editor, and chart builder. The chart deploys three independent components: a Gunicorn web server, Celery workers for async queries, and a Celery Beat scheduler for cache warming and alerts.

secretKey protects all sessions — losing it logs out every user simultaneously

superset.secretKey is the Flask SECRET_KEY used to sign sessions and encrypt sensitive metadata. The chart preserves an auto-generated key across upgrades, but uninstalling and reinstalling without an operator-owned Secret loses it. Use superset.existingSecret in production and include the key in the PostgreSQL recovery plan.

PostgreSQL and Redis are enabled by default — both subcharts are bundled

Unlike most charts, Superset ships with postgresql.enabled: true and redis.enabled: true. No manual activation is needed for a quick start. Set both to false and configure database.mode: external and redisConfig.mode: external to use external services.

Key Features

  • Three-component architecture — web (Gunicorn), worker (Celery), beat (Celery Beat)
  • Init Job — runs superset db upgrade and admin creation on every install/upgrade
  • Bundled PostgreSQL and Redis — both enabled by default
  • superset_config.py override — arbitrary Python config via superset.extraConfig
  • Additional Python packages — optional database drivers shared by web, worker, beat, and init
  • Configurable listener — web.containerPort changes the real Gunicorn bind port
  • Secure defaults — non-root, read-only containers with seccomp and dropped capabilities
  • NetworkPolicy — web-listener ingress isolation with configurable peers and egress
  • pg_dump backup — scheduled PostgreSQL S3 backup CronJob

Installation

HTTPS repository:

helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install superset helmforge/superset -f values.yaml

OCI registry:

helm install superset oci://ghcr.io/helmforgedev/helm/superset -f values.yaml

Upgrading from Superset 4

This release crosses the Superset 5 and 6 major versions

Back up the metadata database and plan for migration downtime. The init Job runs superset db upgrade and superset init before the application workloads become ready. Superset 6 removes AUTH_OID; migrate those installations to OAuth, LDAP, or database authentication before upgrading. Custom frontend extensions may also need changes for the React upgrade introduced in Superset 5.

Review the upstream Superset 5 update notes and Superset 6 update notes before upgrading production.

Additional Database Drivers

Use superset.extraPythonPackages for development and simpler deployments that need optional Python database drivers. Entries accept package names with optional version constraints and are installed consistently in the web, worker, beat, and init processes. Pin a version that you have tested:

superset:
  extraPythonPackages:
    - clickhouse-connect==0.13.0

For Superset 6.1.0, clickhouse-connect>=0.13.0 is the recommended ClickHouse driver. Configure the database with a clickhousedb://user:password@host:port/database SQLAlchemy URI.

Runtime package installation depends on the package index

Packages configured through extraPythonPackages are downloaded whenever a Superset container starts. For production, build an immutable image with the tested drivers preinstalled, publish it under an immutable tag, and configure that tag through image.repository and image.tag. Set superset.installPythonPackages: false so startup does not access the package index.

FROM apache/superset:6.1.0

USER root

RUN . /app/.venv/bin/activate && \
    uv pip install psycopg2-binary redis "clickhouse-connect==0.13.0"

USER superset

After publishing the image under an immutable tag, disable runtime package installation:

image:
  repository: registry.example.com/superset
  tag: 6.1.0-clickhouse-0.13.0

superset:
  installPythonPackages: false

The custom image must contain psycopg2-binary, redis, and every configured extra package.

Deployment Examples

# values.yaml — Superset with bundled PostgreSQL + Redis (with persistence overrides)
superset:
  adminUsername: admin
  adminEmail: [email protected]
  existingSecret: superset-secrets
  existingSecretPasswordKey: admin-password
  existingSecretSecretKeyKey: secret-key # Flask SECRET_KEY

postgresql:
  enabled: true
  auth:
    database: superset
    username: superset
    password: 'strong-db-password'
  standalone:
    persistence:
      storageClass: fast-storage
      size: 20Gi

redis:
  enabled: true
  auth:
    password: 'strong-redis-password'
  standalone:
    persistence:
      storageClass: fast-storage
      size: 8Gi

ingress:
  enabled: true
  ingressClassName: traefik
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: superset.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: superset-tls
      hosts:
        - superset.example.com
# values.yaml — Superset with scaled web, workers, and beat scheduler
superset:
  existingSecret: superset-secrets

web:
  replicaCount: 2 # web server pods
  workers: 4 # Gunicorn worker processes per web pod (NOT Celery workers)
  timeout: 120

worker:
  enabled: true
  replicaCount: 3 # Celery worker pods
  concurrency: 4 # simultaneous Celery tasks per worker pod

beat:
  enabled: true # Celery Beat: cache warming, alerts, reports

postgresql:
  enabled: true
  auth:
    password: 'strong-db-password'

redis:
  enabled: true
  auth:
    password: 'strong-redis-password'

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: superset.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Superset with external PostgreSQL and Redis
superset:
  existingSecret: superset-secrets

postgresql:
  enabled: false

redis:
  enabled: false

database:
  mode: external
  external:
    host: postgres.database.svc.cluster.local
    port: 5432
    name: superset
    username: superset
    existingSecret: superset-db-credentials
    existingSecretPasswordKey: password
    sslMode: verify-full

redisConfig:
  mode: external
  external:
    host: redis.cache.svc.cluster.local
    port: 6379
    db: 0
    tls: true
    existingSecret: superset-redis-credentials
    existingSecretPasswordKey: password

backup:
  enabled: true
  schedule: '0 3 * * *'
  s3:
    endpoint: https://s3.amazonaws.com
    bucket: superset-backups
    existingSecret: superset-s3-credentials

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: superset.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Superset with OIDC/OAuth2 via superset.extraConfig
superset:
  existingSecret: superset-secrets
  extraConfig: |
    from flask_appbuilder.security.manager import AUTH_OAUTH
    AUTH_TYPE = AUTH_OAUTH
    OAUTH_PROVIDERS = [
      {
        "name": "keycloak",
        "token_key": "access_token",
        "icon": "fa-key",
        "remote_app": {
          "client_id": "superset",
          "client_secret": "my-client-secret",
          "server_metadata_url": "https://auth.example.com/realms/myrealm/.well-known/openid-configuration",
          "client_kwargs": {"scope": "openid email profile"},
          "redirect_uri": "https://superset.example.com/oauth-authorized/keycloak",
        },
      }
    ]
    AUTH_USER_REGISTRATION = True
    AUTH_USER_REGISTRATION_ROLE = "Gamma"

postgresql:
  enabled: true
  auth:
    password: 'strong-db-password'

redis:
  enabled: true
  auth:
    password: 'strong-redis-password'

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: superset.example.com
      paths:
        - path: /
          pathType: Prefix

Runtime Security

Superset containers run as UID/GID 1000 with a read-only root filesystem, RuntimeDefault seccomp, no privilege escalation, and all Linux capabilities dropped. EmptyDir volumes provide the required writable home and /tmp paths. The initialization and backup Jobs do not receive Kubernetes API tokens. Application pods receive a namespaced token only while init.enabled is true, because their wait container reads the revisioned initialization Job.

NetworkPolicy is enabled by default. It permits ingress only on web.containerPort and allows egress. Restrict networkPolicy.ingressFrom to the ingress-controller namespace and replace the egress rules only after including DNS, PostgreSQL, Redis, package-index access when runtime installs are enabled, and every data source queried by Superset.

Connection URLs are built inside superset_config.py with URL-encoded Secret values. Passwords are never stored in the ConfigMap. Treat superset.extraConfig as trusted Python code.

Configuration Reference

Image

Parameter Type Default Description
image.repository string docker.io/apache/superset Superset image.
image.tag string "6.1.0" Image tag.

Superset Application

Parameter Type Default Description
superset.adminUsername string admin Admin username created by the init Job.
superset.adminPassword string "" Admin password. Auto-generated if empty. Use existingSecret.
superset.secretKey string "" Flask SECRET_KEY. Auto-generated if empty. Use existingSecret.
superset.existingSecret string "" Existing secret with admin password and SECRET_KEY.
superset.existingSecretPasswordKey string admin-password Key for the admin password in the existing secret.
superset.existingSecretSecretKeyKey string secret-key Key for the Flask SECRET_KEY in the existing secret.
superset.loadExamples boolean false Load example dashboards during init (use for demos only).
superset.extraConfig string "" Extra Python appended to superset_config.py (OAuth, cache, features).
superset.extraEnv array [] Extra environment variables for all Superset containers.
superset.installPythonPackages boolean true Install Python dependencies when each Superset process starts.
superset.extraPythonPackages array [] Additional Python packages installed in every Superset process.

Web Server

Parameter Type Default Description
web.replicaCount integer 1 Number of web server pods.
web.containerPort integer 8088 Actual Gunicorn listener port.
web.workers integer 2 Gunicorn worker processes per pod (not Celery workers).
web.timeout integer 120 Gunicorn worker timeout in seconds.
web.resources object {} CPU and memory requests/limits for web pods.

Celery Worker

Parameter Type Default Description
worker.enabled boolean true Enable Celery worker Deployment.
worker.replicaCount integer 1 Number of Celery worker pods.
worker.concurrency integer 2 Simultaneous Celery tasks per worker pod.
worker.resources object {} CPU and memory requests/limits for worker pods.

Celery Beat

Parameter Type Default Description
beat.enabled boolean true Enable Celery Beat scheduler (cache warming, alerts, reports).
beat.resources object {} CPU and memory requests/limits for the beat pod.

Init Job

Parameter Type Default Description
init.enabled boolean true Enable the init Job. Runs superset db upgrade + admin creation on every install/upgrade.
init.resources object {} CPU and memory requests/limits for the init container.

Database

The bundled PostgreSQL runs in standalone mode. Its PVC is configured under postgresql.standalone.persistence; leave storageClass empty to use the cluster’s default StorageClass.

Parameter Type Default Description
database.mode string subchart Mode: subchart or external.
database.external.host string "" External database hostname.
database.external.existingSecret string "" Existing secret with database password.
database.external.existingSecretPasswordKey string password Key for the password in the existing secret.
database.external.sslMode string require PostgreSQL client SSL mode.
postgresql.enabled boolean true Deploy the bundled PostgreSQL subchart.
postgresql.auth.password string "" Password. Auto-generated if empty.
postgresql.standalone.persistence.enabled boolean true Enable the bundled PostgreSQL PVC.
postgresql.standalone.persistence.storageClass string "" StorageClass name. Empty uses the cluster default.
postgresql.standalone.persistence.accessModes array [ReadWriteOnce] Access modes for the bundled PostgreSQL PVC.
postgresql.standalone.persistence.size string 8Gi Size of the bundled PostgreSQL PVC.

Redis

The bundled Redis also runs in standalone mode. Its PVC is configured under redis.standalone.persistence; leave storageClass empty to use the cluster’s default StorageClass.

Parameter Type Default Description
redisConfig.mode string subchart Mode: subchart or external.
redisConfig.external.host string "" External Redis hostname.
redisConfig.external.existingSecret string "" Existing secret with Redis password.
redisConfig.external.tls boolean false Use a TLS-protected external Redis connection.
redis.enabled boolean true Deploy the bundled Redis subchart.
redis.auth.password string "" Password. Auto-generated if empty.
redis.standalone.persistence.enabled boolean true Enable the bundled Redis PVC.
redis.standalone.persistence.storageClass string "" StorageClass name. Empty uses the cluster default.
redis.standalone.persistence.accessModes array [ReadWriteOnce] Access modes for the bundled Redis PVC.
redis.standalone.persistence.size string 8Gi Size of the bundled Redis PVC.

Service and Ingress

Parameter Type Default Description
service.type string ClusterIP Service type.
service.port integer 80 Service port.
ingress.enabled boolean false Enable an Ingress resource.
ingress.ingressClassName string traefik Ingress class name.
networkPolicy.enabled boolean true Create a NetworkPolicy.

Security Context and ServiceAccount

Parameter Type Default Description
serviceAccount.create boolean true Create a dedicated ServiceAccount.
serviceAccount.automountServiceAccountToken boolean true Allow the init waiter to read the namespaced Job.
podSecurityContext.seccompProfile.type string RuntimeDefault Pod seccomp profile.
securityContext.readOnlyRootFilesystem boolean true Protect the container root filesystem.
securityContext.allowPrivilegeEscalation boolean false Block privilege escalation.

Backup

Backup runs pg_dump on PostgreSQL. No backup for Redis data.

Parameter Type Default Description
backup.enabled boolean false Enable scheduled pg_dump S3 backup.
backup.schedule string "0 3 * * *" Cron schedule.
backup.s3.endpoint string "" S3-compatible endpoint URL.
backup.s3.bucket string "" Target bucket name.
backup.s3.existingSecret string "" Existing secret with S3 credentials.
extraManifests array [] Extra Kubernetes manifests.

More Information