Metabase Business Intelligence Installation
Metabase is an open-source business intelligence platform that lets you connect to databases and build dashboards without writing SQL. This guide covers self-hosting Metabase on Linux using Docker, including database connections, the question builder, custom dashboards, user permissions, and performance tuning.
Prerequisites
- Ubuntu 20.04+ / Debian 11+ or CentOS 8+ / Rocky Linux 8+
- Docker and Docker Compose (recommended), or Java 11+
- At least 2 GB RAM (4 GB recommended for production)
- A database to analyze (PostgreSQL, MySQL, SQLite, etc.)
- A dedicated PostgreSQL database for Metabase's own metadata (recommended for production)
Installing Metabase with Docker
Docker is the simplest way to run Metabase. Create a Docker Compose file for a production-ready setup:
# Create a directory for Metabase
mkdir -p /opt/metabase && cd /opt/metabase
# Create docker-compose.yml
cat > docker-compose.yml << 'EOF'
version: "3.9"
services:
metabase-db:
image: postgres:15-alpine
container_name: metabase-db
restart: unless-stopped
environment:
POSTGRES_DB: metabase
POSTGRES_USER: metabase
POSTGRES_PASSWORD: strongpassword
volumes:
- metabase-db-data:/var/lib/postgresql/data
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: strongpassword
MB_DB_HOST: metabase-db
MB_SITE_URL: http://your-domain.com:3000
JAVA_TIMEZONE: UTC
depends_on:
- metabase-db
volumes:
- metabase-data:/metabase-data
volumes:
metabase-db-data:
metabase-data:
EOF
# Start Metabase
docker compose up -d
# Check logs during startup (first start takes 1-2 minutes)
docker compose logs -f metabase
Installing Metabase without Docker
For a bare-metal installation using Java:
# Install Java 11
# Ubuntu/Debian:
sudo apt-get update && sudo apt-get install -y openjdk-11-jre-headless
# CentOS/Rocky:
sudo dnf install -y java-11-openjdk-headless
# Create Metabase user and directory
sudo useradd -r -m -d /opt/metabase metabase
sudo mkdir -p /opt/metabase
cd /opt/metabase
# Download Metabase JAR
sudo curl -o metabase.jar https://downloads.metabase.com/latest/metabase.jar
sudo chown metabase:metabase metabase.jar
# Create environment file
sudo cat > /opt/metabase/metabase.env << 'EOF'
MB_DB_TYPE=postgres
MB_DB_DBNAME=metabase
MB_DB_PORT=5432
MB_DB_USER=metabase
MB_DB_PASS=strongpassword
MB_DB_HOST=localhost
MB_SITE_URL=http://your-domain.com:3000
JAVA_TIMEZONE=UTC
EOF
# Create systemd service
sudo cat > /etc/systemd/system/metabase.service << 'EOF'
[Unit]
Description=Metabase BI Server
After=network.target postgresql.service
[Service]
User=metabase
WorkingDirectory=/opt/metabase
EnvironmentFile=/opt/metabase/metabase.env
ExecStart=/usr/bin/java -jar /opt/metabase/metabase.jar
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now metabase
sudo systemctl status metabase
Initial Setup and Database Connection
After starting, access Metabase at http://your-server:3000. The setup wizard walks you through:
- Create your admin account (name, email, password)
- Tell Metabase about your organization
- Connect your first database
To add a database connection later via the Admin Panel:
- Go to Settings (gear icon) → Admin → Databases
- Click Add database
- Select your database type and fill in connection details
- Click Save
For PostgreSQL, the connection test verifies credentials and network access. If you're connecting to a database on the host machine from Docker, use the host IP or host.docker.internal.
# Allow Metabase container to reach host PostgreSQL
# On host, edit pg_hba.conf to allow the Docker subnet
sudo nano /etc/postgresql/15/main/pg_hba.conf
# Add: host mydb myuser 172.17.0.0/16 md5
# Reload PostgreSQL
sudo systemctl reload postgresql
Building Questions and Visualizations
Metabase's Question Builder lets non-technical users query data without SQL:
- Click New → Question
- Choose your data source (table or model)
- Add Filters (e.g., date range, category)
- Add Summaries (e.g., count by category, sum by month)
- Select a visualization type (bar chart, line, map, etc.)
- Click Save and name your question
For SQL power users, use the Native Query Editor:
- Click New → SQL query
- Select your database
- Write your SQL with optional template variables:
-- Template variable for date filtering
SELECT
date_trunc('month', created_at) AS month,
count(*) AS new_users
FROM users
WHERE created_at >= {{start_date}}
AND created_at < {{end_date}}
GROUP BY 1
ORDER BY 1;
Variables like {{start_date}} become filter widgets on the dashboard.
Creating Dashboards
Dashboards combine multiple questions into a single view:
- Click New → Dashboard
- Name your dashboard
- Click Add a question and search for saved questions
- Drag and resize cards to arrange the layout
- Click Add a filter to link a dashboard filter to multiple questions
- Click Save
To set auto-refresh for live dashboards:
- Click the clock icon in the top-right
- Select refresh interval (1 min, 5 min, etc.)
User Permissions and Groups
Metabase uses groups to control data access:
Admin Panel → People → Groups
Default groups:
- Administrators - full access
- All Users - baseline permissions (restrict this group)
Create a custom group:
- Go to Admin → People → Groups → Create a group
- Name the group (e.g., "Finance Team")
- Add users to the group
- Go to Admin → Permissions → Data
- Set database/schema/table access per group:
- Unrestricted - can query any table
- Granular - choose table-by-table
- No self-service - can only see saved questions
For collection permissions (who sees which dashboards):
- Admin → Permissions → Collections
Embedding and Sharing
Public links - anyone with the link can view (no login required):
- Open a question or dashboard → click Share → enable public link
Signed embedding (embed in your app with JWT):
# Generate a signing key
openssl rand -hex 32
Set this key in Admin → Embedding → Embedding secret key.
In your application, generate a signed token:
import jwt, time
METABASE_SITE_URL = "http://your-domain.com:3000"
METABASE_SECRET_KEY = "your-signing-key"
payload = {
"resource": {"dashboard": 1}, # dashboard ID
"params": {},
"exp": round(time.time()) + (60 * 10) # 10 min expiry
}
token = jwt.encode(payload, METABASE_SECRET_KEY, algorithm="HS256")
iframe_url = f"{METABASE_SITE_URL}/embed/dashboard/{token}#bordered=true&titled=true"
Performance Tuning
# Increase JVM heap for Metabase (Docker)
# Edit docker-compose.yml environment section:
environment:
JAVA_OPTS: "-Xmx2g -Xms512m"
# Enable question caching in Admin → Caching
# Set minimum query time to cache (e.g., 60 seconds)
# Cached results are stored for a configurable TTL
# For large datasets, create database indexes on commonly filtered columns
# Example for PostgreSQL:
psql -U myuser -d mydb << 'SQL'
CREATE INDEX CONCURRENTLY idx_orders_created_at ON orders(created_at);
CREATE INDEX CONCURRENTLY idx_orders_status ON orders(status);
SQL
# Monitor Metabase logs for slow queries
docker compose logs metabase | grep -i "slow\|timeout"
Enable query caching in Admin → Performance → Caching to avoid re-running expensive queries on every dashboard load.
Troubleshooting
Metabase won't start:
docker compose logs metabase | tail -50
# Look for database connection errors or Java heap errors
"Can't connect to database" error:
# Test connectivity from Metabase container
docker exec -it metabase bash
# Then test with nc or curl
nc -zv your-db-host 5432
Slow dashboard loading:
- Enable caching for slow questions
- Add database indexes on filter columns
- Check if the application database (Metabase's own DB) is on slow storage
Out of memory errors:
# Increase heap size
JAVA_OPTS="-Xmx4g" docker compose up -d metabase
SMTP/email not working:
- Go to Admin → Email and test the SMTP connection
- Ensure port 587 or 465 is not blocked by firewall
Reset admin password:
docker exec -it metabase java -jar /app/metabase.jar reset-password [email protected]
Conclusion
Metabase provides a powerful self-hosted BI platform that makes data exploration accessible to technical and non-technical users alike. With Docker deployment, PostgreSQL as the application database, and careful permission setup, you can have a production-ready analytics platform running on your VPS. Enable query caching and add appropriate database indexes to keep dashboards fast as your data grows.


