Deployment guide

How to Self-Host Metabase on a VPS: Open-Source BI Dashboards

Deploy on a VPS Cloud →

Tutorial

Self-hosting

How to Self-Host Metabase on a VPS: Open-Source BI Dashboards

Metabase (AGPL, ~46k stars) is the easiest way to put self-service dashboards on top of a database you already run — PostgreSQL, MySQL, ClickHouse and dozens more — without a per-seat USD subscription to a foreign BI SaaS. Non-technical users build questions and charts by clicking; analysts drop into raw SQL when they need it. In this guide you deploy Metabase and its companion metadata Postgres as a two-container Docker stack on a VPS, so your entire analytics layer stays on infrastructure you control. The reference version is Metabase 64.1 (LTS, released October 6 2026, supported until December 1 2027) — if you are still on v63, migrate before November 1 2026 when security support ends.

9 min read6 steps
Contents· Why self-host your BI dashboards1/10
  1. 01Why self-host your BI dashboards
  2. 02What Metabase gives you
  3. 03Requirements
  4. 04Deploy Metabase on your VPS
  5. 05Upgrading to Metabase 64 (LTS)
  6. 06Alerts, subscriptions and scheduled reports
  7. 07Supported connectors: well beyond classic SQL
  8. 08Metabase Open Source vs Pro vs Cloud
  9. 09Troubleshooting: common errors
  10. 10Point Metabase at a read replica, not your primary

Why self-host your BI dashboards

Hosted BI tools are convenient until the per-seat bill arrives — and until you realise your product, revenue and customer data are being copied into a third-party SaaS priced in USD. Metabase flips that: it is open source (AGPL), self-hostable, and connects to a database you already own. Run it on a VPS behind your own domain and your analytics layer never leaves your server. You pay a fixed monthly cost for the VPS, not a growing per-user subscription, and your data stays on infrastructure you control — which for a Moroccan team also means data sovereignty, not a datacenter whose location you don't know.

What Metabase gives you

  • A visual query builder so non-technical users create charts and questions by clicking — with a full SQL editor for analysts.
  • Interactive dashboards with filters, drill-through and scheduled refresh.
  • Connectors for 20+ databases: PostgreSQL, MySQL/MariaDB, SQL Server, ClickHouse, BigQuery, Redshift, Snowflake, MongoDB, Athena, Spark, Druid and more.
  • Scheduled subscriptions and threshold alerts delivered to email or Slack.
  • Group- and collection-level permissions plus row/column controls so each team sees only its own data.
  • Embedded analytics to drop signed, filtered dashboards into your own app.
  • AGPL open source — no per-seat fee, its own state stored in a Postgres database you own.

Requirements

A VPS with Ubuntu 22.04 (or Debian 12) and Docker installed. Metabase runs on the JVM, so give it room: 2 GB RAM is the realistic minimum and 4 GB is comfortable for a small team. The JVM defaults to a 1 500 MB heap; on a 2 GB VPS cap it at 1 200 MB with JAVA_OPTS=-Xmx1200m, or raise it to 2 GB on a 4 GB server (-Xmx2g). The deployment is two containers — Metabase itself and a companion postgres:16 that stores Metabase's own metadata (users, dashboards, saved questions). No domain is strictly required — Metabase answers on port 3000 via your server's IP — but you will want a reverse proxy for HTTPS in production.

Deploy Metabase on your VPS

  1. Create a docker-compose stack

    Metabase should store its own state in a real database, not the default embedded H2 file. Create a docker-compose.yml with two services: metabase/metabase:v0.64.1 and a companion postgres:16. Wire Metabase to Postgres with MB_DB_TYPE=postgres, MB_DB_HOST=metabase-db, MB_DB_DBNAME=metabaseappdb, MB_DB_PORT=5432, MB_DB_USER=metabase and a strong MB_DB_PASS. Use the same password for the Postgres container's POSTGRES_PASSWORD, mount a named volume for /var/lib/postgresql/data, and set restart: unless-stopped on both. Also add METABASE_SITE_URL=https://bi.yourdomain.com and MB_ENCRYPTION_SECRET_KEY (a random 32+ character string) to encrypt database credentials at rest — without it passwords are stored in plain text in Postgres.

  2. Tune JVM memory

    Add JAVA_OPTS=-Xmx1500m to the Metabase service environment if you have 2 GB RAM, or -Xmx2g for 4 GB. Without this, the JVM may exceed available memory and trigger an OOM (Out Of Memory) kill that stops the container with no readable error. Check for OOM kills with docker inspect metabase --format '{{.State.OOMKilled}}' (returns true) or dmesg | grep -i oom.

  3. Bring it up and wait for boot

    Run docker compose up -d. On first start Metabase runs its database migrations against Postgres, which takes 60–120 seconds on a small VPS — this is normal. Poll readiness with curl -f http://localhost:3000/api/health; once it returns {"status":"ok"} the app is ready. The compose stack gates Metabase on the Postgres healthcheck so the app never starts before its database is up.

  4. Finish the setup wizard

    Open http://<your-server-ip>:3000. Metabase redirects to the setup wizard: create the admin account, then connect the database you actually want to analyse — typically your application's PostgreSQL or MySQL, ideally a read replica so analytics queries never hit your production primary. Metabase scans the schema and your tables are query-ready in seconds.

  5. Build a dashboard

    Create a couple of questions with the visual query builder (a count over time, a breakdown by category), save them into a collection, and pin them onto a dashboard with a date filter. Switch any question to the native SQL editor when you need full control. Set up an email or Slack subscription to have the dashboard delivered on a schedule.

  6. Add HTTPS and lock it down

    Put Metabase behind a reverse proxy for a real domain and a certificate. With Caddy: apt install caddy, then a /etc/caddy/Caddyfile containing bi.yourdomain.com { reverse_proxy localhost:3000 } and systemctl reload caddy for an automatic Let's Encrypt cert. Point the DNS A record for bi.yourdomain.com at your VPS first, restrict port 3000 with ufw allow from <proxy> to any port 3000, and set a strong admin password — anyone who can log in can query every connected database.

Upgrading to Metabase 64 (LTS)

If you are on v63 or earlier, migrate before November 1 2026 — that is when v63 security support ends. Metabase 64.1 is the recommended LTS branch, supported until December 1 2027. Upgrading with Docker is straightforward: stop the stack (docker compose down), replace the image tag with v0.64.1 in your docker-compose.yml, then bring it back up (docker compose up -d). Metabase automatically applies schema migrations on startup. Back up your Postgres volume (docker exec metabase-db pg_dump -U metabase metabaseappdb > backup-before-v64.sql) before upgrading, and verify the container starts cleanly with curl -f http://localhost:3000/api/health before discarding the backup.

Alerts, subscriptions and scheduled reports

Metabase can send dashboards by email or Slack on a schedule. For email, configure an SMTP server in Administration → Email settings: set METABASE_SMTP_HOST, METABASE_SMTP_PORT, METABASE_SMTP_USER and METABASE_SMTP_PASSWORD as environment variables, or fill in the form directly. Once SMTP is active, every dashboard offers a Subscribe button: choose recipients, frequency (daily, weekly) and format (PNG image or attachment). Threshold alerts work on any numeric question: Metabase evaluates the query on a schedule and sends a notification when the value crosses a threshold — ideal for monitoring KPIs like daily revenue, error rates or conversion rates without opening the dashboard.

Supported connectors: well beyond classic SQL

Metabase Open Source connects natively to PostgreSQL, MySQL/MariaDB, SQL Server, SQLite, H2, Redshift, BigQuery, Snowflake, Athena, Druid, ClickHouse, MongoDB (read-only via the official driver), Presto/Trino and SparkSQL. The Pro/Enterprise edition adds certified drivers and official support. For unlisted databases, community JSON drivers are available: drop them in the /plugins directory of the container (mount a volume) and Metabase detects them on startup. The ClickHouse connector is worth highlighting: ClickHouse is increasingly used for high-volume real-time analytics, and Metabase connects to it natively since v44 — a powerful combination for near-real-time dashboards without a dedicated data warehouse.

Metabase Open Source vs Pro vs Cloud

The Open Source edition (AGPL) covers all common analytics use cases: dashboards, alerts, subscriptions, basic embedded analytics, group-level access control. The Pro edition (commercial license) adds sub-organization management (multi-tenant), interactive dashboards with session variables for advanced embedded analytics, access audit logs and SAML SSO. The Cloud edition (managed SaaS by Metabase Inc.) removes maintenance overhead but moves your data to third-party servers — which for sensitive data or compliance requirements is reason enough to self-host. On a €8/month VPS, the Open Source edition covers almost all SMB needs with no user limits.

Troubleshooting: common errors

Container restarting in a loop / OOM. Check docker inspect metabase --format '{{.State.OOMKilled}}' — if true, increase VPS memory or reduce the heap with JAVA_OPTS=-Xmx1200m. A 1 GB RAM VPS is too tight; 2 GB is the minimum. JDBC connection refused at startup. Metabase tries to reach Postgres before it is ready. Ensure a healthcheck is defined on the Postgres service and that Metabase depends on it (depends_on: metabase-db: condition: service_healthy). Very long startup time (> 5 min). On a low-CPU VPS, initial migrations can take up to 5 minutes. This is normal on first launch; subsequent starts are fast (15–30 seconds). Slow dashboards or timeouts. Connect Metabase to a read replica rather than the primary. If that is not possible, enable query caching with MB_QUERY_CACHING_TTL_RATIO=10. Emails not received. Check SMTP logs in Administration → Audit logs. Test the connection with Administration → Email settings → Send test email.

Point Metabase at a read replica, not your primary

Analytics queries can be heavy. Connect Metabase to a read replica or a dedicated reporting database rather than your production primary, so a slow dashboard query never slows down your live application. On a single VPS you can run a lightweight replica in its own container on the same private Docker network — Metabase reaches it by service name and your primary stays untouched.

Deploy Metabase on your VPS in one click

Stop paying per seat in USD for hosted BI. ServOrbit provisions a ready-to-use Metabase instance — companion Postgres pre-wired, health-checked, and reachable from your browser in minutes — on infrastructure you control.