Analytics & Intelligence

Deploy Metabase on Kubernetes: Helm Chart Guide

J
James Eriksson
··10 min read
Step-by-step guide to deploying Metabase on Kubernetes with Helm. Configure PostgreSQL, manage secrets, set up Ingress, and troubleshoot common issues.
TL;DR
  • There is no official Metabase Helm chart; use community options like pmint93 (118 stars) for production deployments
  • Always configure an external PostgreSQL database instead of the embedded H2 for production reliability and scaling
  • Use Kubernetes Secrets to manage database passwords and encryption keys; never hardcode credentials in values files
  • Set up Ingress with TLS for secure external access and configure RBAC to restrict pod access to sensitive data
  • Self-hosting Metabase on Kubernetes requires cluster expertise, backups, and patch management; managed hosting eliminates operational burden

Deploying Metabase on Kubernetes with Helm gives you version control, repeatability, and secrets management for analytics infrastructure. Helm charts template Kubernetes manifests, letting you deploy Metabase consistently across dev, staging, and production without rewriting YAML by hand. There is no official Metabase Helm chart from the project maintainers--the legacy chart was deprecated--so you will choose from community options like pmint93, TrueCharts, BCGov, or the Metabase Operator.

Why Deploy Metabase on Kubernetes with Helm?

Helm packages Kubernetes applications into reusable templates. Deployment becomes code: you store your values.yaml in Git, review changes before applying them, and roll back broken updates by pointing to a prior release. This approach fits teams running Metabase alongside other microservices. You gain environment parity (same image, same configuration shape, different secrets per environment) and automated secret injection, so you never hardcode credentials into deployment manifests. For organizations already using Kubernetes, adding Metabase via Helm is faster than managing Kubernetes resources by hand or adopting a managed SaaS that costs per user.

Helm also handles upgrades gracefully. When Metabase releases a patch or minor version, you change the chart version in your values file, run helm upgrade, and Helm compares the old and new state--adding new resources, updating existing ones, leaving untouched resources alone. This prevents accidental deletions and makes rollback trivial: helm rollback release-name reverts to the prior release in seconds.

Understanding Helm Charts and Metabase Options

There is no official Helm chart maintained by Metabase. The project deprecated its own chart in 2021 because Kubernetes packaging moved to the community. The most popular community option is pmint93's chart (118 GitHub stars, actively maintained, covers most standard configurations). TrueCharts maintains a modern fork optimized for TrueNAS. BCGov's chart (British Columbia government) targets production deployments with strict RBAC and multi-pod scenarios. Artifact Hub indexes these charts, making them discoverable: search "metabase" on artifacthub.io and you will see options ranked by activity and recency.

The Metabase Operator (unagex/metabase-operator, 19 stars) takes a different approach: instead of templating YAML, it watches a Kubernetes CRD (Custom Resource Definition) and reconciles Metabase deployments like a service operator would. This suits teams building internal developer platforms but adds complexity. For most users, a standard Helm chart is simpler and more portable than an operator.

Choosing a chart: check the last commit date (active maintenance), test it against your Metabase version, and review the values.yaml defaults. pmint93 is the safe default. All community charts use the official Metabase Docker image (50.2K stars on GitHub, well-maintained) and differ mainly in how they expose the database, secrets, and ingress configuration.

Prerequisites and Setup

You need a running Kubernetes cluster (EKS, GKE, AKS, or self-hosted). Install kubectl (the CLI) and helm (version 3.x or later). Both are standard tooling; most cloud providers include them in quickstart guides.

If you plan to expose Metabase outside the cluster, you also need an Ingress controller. Most managed Kubernetes services (AWS EKS, Google GKE, Azure AKS) include one by default. If you are running a self-hosted cluster, install nginx-ingress or another ingress provider before deploying Metabase.

Optionally, configure your local kubeconfig to point to your cluster: kubectl config use-context <your-cluster> and test connectivity with kubectl get nodes. A simple sanity check confirms your cluster is reachable before you begin the Helm workflow.

Step-by-Step: Install Metabase via Helm

Start by adding the Helm repository. Using pmint93 as the example:

helm repo add pmint93 https://pmint93.github.io/helm-charts && helm repo update

Verify the repo is searchable:

helm search repo metabase

Create a dedicated namespace to isolate Metabase from other applications:

kubectl create namespace metabase

Install Metabase with a basic values file. Create a file called values.yaml:

image:
  repository: metabase/metabase
  tag: v0.50.0

replicas: 1

persistence:
  enabled: true
  size: 10Gi

service:
  type: ClusterIP
  port: 3000

Then run:

helm install metabase pmint93/metabase --namespace metabase --values values.yaml

Helm creates all Kubernetes resources--Deployment, Service, StatefulSet, and PersistentVolumeClaim. Verify the installation:

kubectl get pods --namespace metabase

Wait for the pod to reach Running status. This may take 1-2 minutes as Kubernetes pulls the image and starts the container. Check logs if the pod stalls:

kubectl logs -n metabase deployment/metabase

Configuring an External PostgreSQL Database

Metabase ships with an embedded H2 database for data storage (not the application database, just Metabase's own settings, saved questions, and dashboards). H2 is file-based, loses data if the pod restarts without a persistent volume, and does not scale. For production, always use an external PostgreSQL or MySQL database.

Create a PostgreSQL instance. Most cloud providers offer managed PostgreSQL: AWS RDS, Google Cloud SQL, Azure Database for PostgreSQL. For self-hosted Kubernetes, deploy PostgreSQL as a Helm chart or use an operator like CloudNativePG.

In your values.yaml, specify the external database:

database:
  type: postgres
  host: my-postgres.example.com
  port: 5432
  name: metabase
  username: metabase_user
  password: "my-secure-password"

Do not commit passwords to Git. Use Kubernetes Secrets instead (covered next section). But for now, this illustrates the structure. Helm interpolates these values into the Metabase Deployment as environment variables:

MB_DB_TYPE=postgres
MB_DB_HOST=my-postgres.example.com
MB_DB_PORT=5432
MB_DB_NAME=metabase
MB_DB_USER=metabase_user
MB_DB_PASS=my-secure-password

Upgrade the deployment:

helm upgrade metabase pmint93/metabase --namespace metabase --values values.yaml

Metabase will initialize the database schema on first connection. Watch the logs: if connection fails, you will see a stack trace revealing DNS, authentication, or network issues. Verify the database credentials and network access (security groups, firewall rules) before troubleshooting further.

Managing Secrets and Security

Kubernetes Secrets store sensitive data like database passwords and encryption keys. Create a Secret manually and reference it in your values:

kubectl create secret generic metabase-secrets \
  --from-literal=db-password=my-secure-password \
  --from-literal=encryption-key=my-32-character-hex-key \
  --namespace metabase

Then update values.yaml to reference the Secret:

database:
  type: postgres
  host: my-postgres.example.com
  port: 5432
  name: metabase
  username: metabase_user
  existingSecret: metabase-secrets
  existingSecretPasswordKey: db-password

encryption:
  existingSecret: metabase-secrets
  existingSecretKey: encryption-key

Metabase uses MB_ENCRYPTION_SECRET_KEY to encrypt sensitive fields (saved passwords for data source connections). If you lose this key, those encrypted credentials become unrecoverable. Store the key in a secure vault (HashiCorp Vault, AWS Secrets Manager) and rotate it periodically.

For the Metabase admin account, set the initial password via the MB_ADMIN_DATABASE_FILE_UPLOAD_DIRECTORY or initialization variables, then change it through the web interface after first login. Never hardcode the admin password in values or Secrets; Kubernetes RBAC should restrict access to Secret objects by role.

Configure RBAC to limit who can view Secrets and Deployments:

kubectl create role metabase-admin --verb=get,list --resource=secrets --namespace metabase
kubectl create rolebinding metabase-admin-binding --role=metabase-admin --user=devops-team --namespace metabase

Setting Up Ingress for External Access

By default, Metabase is accessible only inside the cluster via the Kubernetes Service (ClusterIP). To expose it to the internet, create an Ingress resource:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: metabase-ingress
  namespace: metabase
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - analytics.example.local
    secretName: metabase-tls
  rules:
  - host: analytics.example.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: metabase
            port:
              number: 3000

This routes traffic from your ingress host to the Metabase Service. The cert-manager.io/cluster-issuer annotation tells cert-manager to issue a Let's Encrypt certificate. Install cert-manager by adding its Helm repository and deploying:

helm repo add jetstack https://charts.jetstack.io && helm repo update

Then install cert-manager:

helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace

Apply the Ingress:

kubectl apply -f ingress.yaml --namespace metabase

Within minutes, cert-manager provisions a TLS certificate, and Metabase is accessible at your configured host. Avoid exposing Metabase on HTTP; always use TLS.

Upgrading and Troubleshooting

When Metabase releases a new version, update the chart in values.yaml and run upgrade:

helm upgrade metabase pmint93/metabase --namespace metabase --values values.yaml

Helm compares old and new state and rolls out changes. Metabase itself handles database migrations on startup. If an upgrade fails, roll back instantly:

helm rollback metabase --namespace metabase

Common failures:

CrashLoopBackOff: The pod restarts repeatedly. Check logs: kubectl logs -n metabase deployment/metabase. Usually caused by database connectivity (wrong password, host unreachable) or missing persistent volume (if using H2). Verify the database is reachable and credentials are correct.

ImagePullBackOff: Kubernetes cannot pull the Docker image. Confirm the image tag (e.g., v0.50.0) exists. If using a private registry, create an imagePullSecret.

Persistence issues: If Metabase loses data after pod restart, the persistent volume is not configured. Ensure persistence.enabled: true and persistence.size is adequate. Check PersistentVolumeClaim status: kubectl get pvc --namespace metabase.

RBAC permission errors: Pods cannot access ConfigMaps or Secrets. Verify the ServiceAccount has appropriate role bindings: kubectl get rolebindings --namespace metabase.

Always inspect pod events for clues:

kubectl describe pod <pod-name> --namespace metabase

When Managed Hosting Makes Sense

Self-hosting Metabase on Kubernetes requires cluster management, database backups, security patches, and incident response. If your team lacks Kubernetes expertise, the operational burden outweighs the cost savings. Managed Metabase hosting removes database and infrastructure concerns, letting you focus on data analysis instead of ops.

Opsily offers managed Metabase on Kubernetes, handling database, backup, updates, and monitoring. See how our platform compares on the Metabase hosting page for pricing and feature parity with DIY deployments.

Frequently Asked Questions

What deployment options exist for Metabase on Kubernetes?

Helm charts (pmint93, TrueCharts, BCGov) are the most common. The Metabase Operator (unagex) watches Kubernetes CRDs and is useful for GitOps workflows. All use the official Metabase Docker image and differ in defaults and integrations.

Is there an official Metabase Helm chart?

No. Metabase deprecated its official chart in 2021. The community maintains several alternatives. pmint93's chart (118 GitHub stars) is the most popular and actively maintained.

What are the key configuration steps?

Create a namespace, configure persistent storage, set up an external PostgreSQL database, manage secrets for credentials and encryption keys, and expose Metabase via Ingress with TLS.

How do you manage database credentials and secrets?

Use Kubernetes Secret objects to store passwords and encryption keys. Reference them in your Helm values using existingSecret fields. Never hardcode secrets into YAML files or Git repositories.

What causes CrashLoopBackOff errors?

Missing or misconfigured persistent volume, database connectivity failures (wrong password, host unreachable), or RBAC permission issues (pods cannot access Secrets). Inspect pod logs with kubectl logs to identify the root cause.

How do you upgrade Metabase safely?

Run helm upgrade to apply new chart versions. Helm compares old and new state and rolls out changes gracefully. If an upgrade fails, helm rollback reverts to the prior release instantly. Always test upgrades in staging first.

Can you use the embedded H2 database in production?

No. H2 is file-based and loses data if the pod restarts without persistence. For production, always use external PostgreSQL or MySQL. H2 is suitable only for evaluation or development.

Why would I choose managed hosting over Helm?

Managed hosting eliminates operational complexity: no cluster provisioning, no secret rotation, no backup management, no security patches. If your team lacks Kubernetes expertise, managed hosting reduces costs and risk.

The Bottom Line

Helm charts simplify Metabase deployment on Kubernetes by templating manifests, managing secrets, and enabling repeatable infrastructure-as-code. There is no official chart, but pmint93's community chart is battle-tested and actively maintained. The operational burden includes database management, secret rotation, backup strategy, and security patches. For teams already running Kubernetes, Helm is the right tool. For organizations without Kubernetes expertise, managed Metabase hosting trades upfront complexity for long-term operational simplicity. Compare both approaches on the Metabase hosting page to determine which fits your team's capabilities and constraints.

Skip the infrastructure work
Opsily manages Metabase on Kubernetes so you focus on dashboards and analytics.
Get Started Free

Ready to self-host your own apps?

One server. Multiple apps. No per-app fees.

Get started →