Skip to main content

Self-Hosting Guide: Deploy Metabase for Business Intelligence

·OSSAlt Team
metabasebusiness-intelligenceself-hostingdockerguide

Self-Hosting Guide: Deploy Metabase for Business Intelligence

Metabase is the most popular open source BI tool — it lets non-technical users explore data, build dashboards, and share insights without writing SQL. Self-hosting gives you unlimited users and dashboards for free.

Requirements

  • VPS with 2 GB RAM minimum (4 GB recommended)
  • Docker and Docker Compose
  • Domain name (e.g., bi.yourdomain.com)
  • 10+ GB disk
  • A database to analyze (PostgreSQL, MySQL, etc.)

Step 1: Create Docker Compose

# docker-compose.yml
services:
  metabase:
    image: metabase/metabase:latest
    container_name: metabase
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - MB_DB_TYPE=postgres
      - MB_DB_DBNAME=metabase
      - MB_DB_PORT=5432
      - MB_DB_USER=metabase
      - MB_DB_PASS=your-strong-password
      - MB_DB_HOST=db
      - MB_SITE_URL=https://bi.yourdomain.com
      - MB_ENCRYPTION_SECRET_KEY=your-random-32-char-key
    depends_on:
      - db

  db:
    image: postgres:16-alpine
    container_name: metabase-db
    restart: unless-stopped
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=metabase
      - POSTGRES_USER=metabase
      - POSTGRES_PASSWORD=your-strong-password

volumes:
  postgres_data:

Note: This PostgreSQL is for Metabase's own data (dashboards, users, settings). Your business data lives in separate databases that you'll connect in Step 6.

Step 2: Generate Encryption Key

openssl rand -hex 16

This encrypts database credentials stored in Metabase.

Step 3: Start Metabase

docker compose up -d

First boot takes 1-2 minutes to initialize.

Step 4: Reverse Proxy (Caddy)

# /etc/caddy/Caddyfile
bi.yourdomain.com {
    reverse_proxy localhost:3000
}
sudo systemctl restart caddy

Step 5: Initial Setup Wizard

  1. Open https://bi.yourdomain.com
  2. Select your language
  3. Create admin account
  4. Connect your first database (can skip and add later)
  5. Choose usage tracking preference

Step 6: Connect Your Data Sources

Go to AdminDatabasesAdd database:

DatabaseConnection String
PostgreSQLhost:5432/dbname
MySQLhost:3306/dbname
MongoDBmongodb://host:27017/dbname
SQLite/path/to/database.db
BigQueryService account JSON
SnowflakeAccount + credentials
Redshifthost:5439/dbname

Tip: Create a read-only database user for Metabase:

CREATE USER metabase_reader WITH PASSWORD 'read-only-password';
GRANT CONNECT ON DATABASE myapp TO metabase_reader;
GRANT USAGE ON SCHEMA public TO metabase_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO metabase_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO metabase_reader;

Step 7: Build Your First Dashboard

Create a question (query):

  1. Click NewQuestion
  2. Pick your database and table
  3. Use the visual query builder or write SQL
  4. Save the question

Build a dashboard:

  1. Click NewDashboard
  2. Add saved questions as cards
  3. Add filters (date range, category, etc.)
  4. Arrange and resize cards
  5. Save and share

Common dashboard patterns:

DashboardMetrics
RevenueMRR, churn rate, LTV, new subscriptions
ProductDAU/MAU, feature usage, retention cohorts
SupportTicket volume, response time, CSAT scores
MarketingTraffic, conversion rate, CAC, channel performance

Step 8: Configure SMTP for Alerts

AdminSettingsEmail:

SettingValue
SMTP Hostsmtp.resend.com
SMTP Port587
SMTP SecurityTLS
SMTP Usernameresend
SMTP Passwordre_your_api_key
From Addressbi@yourdomain.com

Enables:

  • Scheduled dashboard emails (daily/weekly reports)
  • Alert notifications (when metrics cross thresholds)
  • User invitation emails

Step 9: Set Up Alerts

  1. Open a question/chart
  2. Click the bell icon → Create alert
  3. Choose condition: "When results go above/below X"
  4. Set recipients and frequency
  5. Alerts fire automatically when conditions are met

Step 10: Embedding (Optional)

Embed Metabase dashboards in your app:

// Generate signed embed URL (server-side)
const jwt = require('jsonwebtoken');

const METABASE_SITE_URL = 'https://bi.yourdomain.com';
const METABASE_SECRET_KEY = 'your-embedding-secret-key';

const payload = {
  resource: { dashboard: 1 },
  params: {},
  exp: Math.round(Date.now() / 1000) + (10 * 60), // 10 min expiration
};

const token = jwt.sign(payload, METABASE_SECRET_KEY);
const embedUrl = `${METABASE_SITE_URL}/embed/dashboard/${token}`;
<iframe
  src="https://bi.yourdomain.com/embed/dashboard/TOKEN"
  width="100%"
  height="600"
  frameborder="0"
></iframe>

Enable embedding in AdminSettingsEmbedding.

Production Hardening

Environment tuning:

environment:
  - JAVA_OPTS=-Xmx2g  # Increase for large datasets
  - MB_JETTY_MAXTHREADS=100
  - MB_ASYNC_QUERY_THREAD_POOL_SIZE=10

Backups:

# Database backup (daily cron)
docker exec metabase-db pg_dump -U metabase metabase > /backups/metabase-$(date +%Y%m%d).sql

Updates:

docker compose pull
docker compose up -d

Security:

  • Use read-only database users
  • Enable SSL for all database connections
  • Restrict Admin access to specific users
  • Set session timeout in Admin settings

Resource Usage

UsersRAMCPUDisk
1-102 GB2 cores10 GB
10-504 GB4 cores15 GB
50-2008 GB8 cores30 GB

VPS Recommendations

ProviderSpec (20 users)Price
Hetzner4 vCPU, 8 GB RAM€8/month
DigitalOcean2 vCPU, 4 GB RAM$24/month
Linode2 vCPU, 4 GB RAM$24/month

Compare BI tools on OSSAlt — features, data sources, and self-hosting options side by side.