Prerequisites & VPS Selection
What You'll Need
- Ubuntu 22.04/24.04 or Debian 11/12
- Root or sudo access
- Domain name (for SSL)
- A database to analyze (PostgreSQL, MySQL, etc.)
Initial Server Setup
Update your system and configure the firewall:
sudo apt update && sudo apt upgrade -ysudo apt install -y ufw
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status⚠️ Warning: Ensure SSH (port 22) is allowed before enabling UFW!
Install Docker
Install Docker for running Metabase:
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-pluginsudo usermod -aG docker $USER
newgrp docker
docker --versionSetup PostgreSQL for Metabase
Metabase needs a database to store its application data. We'll use PostgreSQL:
mkdir -p ~/metabase
cd ~/metabaseversion: '3.8'
services:
metabase-db:
image: postgres:15-alpine
container_name: metabase-db
restart: always
environment:
POSTGRES_USER: metabase
POSTGRES_PASSWORD: your_secure_password_here
POSTGRES_DB: metabase
volumes:
- metabase-db-data:/var/lib/postgresql/data
networks:
- metabase-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U metabase"]
interval: 10s
timeout: 5s
retries: 5
metabase:
image: metabase/metabase:latest
container_name: metabase
restart: always
depends_on:
metabase-db:
condition: service_healthy
environment:
MB_DB_TYPE: postgres
MB_DB_DBNAME: metabase
MB_DB_PORT: 5432
MB_DB_USER: metabase
MB_DB_PASS: your_secure_password_here
MB_DB_HOST: metabase-db
JAVA_TIMEZONE: UTC
ports:
- "127.0.0.1:3000:3000"
networks:
- metabase-network
volumes:
metabase-db-data:
networks:
metabase-network:
driver: bridge⚠️ Important: Replace your_secure_password_here with a strong password!
docker compose up -d
docker compose logs -f metabase💡 Note: First startup may take 2-3 minutes as Metabase initializes. Watch the logs until you see "Metabase Initialization COMPLETE".
Configure Nginx Reverse Proxy
Set up Nginx to proxy requests to Metabase:
sudo apt install -y nginx certbot python3-certbot-nginxserver {
listen 80;
server_name analytics.yourdomain.com;
client_max_body_size 50M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 90s;
proxy_connect_timeout 90s;
proxy_send_timeout 90s;
}
}⚠️ Important: Replace analytics.yourdomain.com with your actual domain!
sudo ln -s /etc/nginx/sites-available/metabase /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginxSSL Certificate
Secure your Metabase installation with SSL:
sudo certbot --nginx -d analytics.yourdomain.com✅ Certbot will automatically configure Nginx for HTTPS and set up auto-renewal.
Initial Setup
Complete the Metabase setup wizard:
- 1Access Metabase: Navigate to
https://analytics.yourdomain.com - 2Language: Select your preferred language
- 3Admin Account: Create your admin user with a strong password
- 4Add Database: Connect your first data source (can skip and add later)
- 5Usage Data: Choose whether to share anonymous usage statistics
Connect Data Sources
Connect Metabase to your databases for analysis:
Supported Databases
- • PostgreSQL
- • MySQL / MariaDB
- • MongoDB
- • SQLite
- • SQL Server
- • Google BigQuery
- • Snowflake
- • And many more...
Adding a Database
- Go to Admin → Databases
- Click "Add database"
- Select database type
- Enter connection details
- Test and save connection
Host: your-database-host.com
Port: 5432
Database name: your_database
Username: your_user
Password: your_password
# For local databases on the same VPS:
Host: host.docker.internal # or use the host IP💡 Tip: Create a read-only database user for Metabase to prevent accidental data modifications.
Security Hardening
Secure your Metabase installation:
Environment Variables for Security
environment:
# ... existing variables ...
MB_PASSWORD_COMPLEXITY: strong
MB_PASSWORD_LENGTH: 12
MB_SESSION_COOKIES: true
MB_EMBEDDING_SECRET_KEY: your_32_char_secret_key_here
MB_ENCRYPTION_SECRET_KEY: your_32_char_encryption_keyAdmin Settings
- • Admin → Settings → Authentication: Enable Google/LDAP SSO if needed
- • Admin → People: Manage users and groups
- • Admin → Permissions: Set database and collection permissions
- • Admin → Settings → Public Sharing: Disable if not needed
Restrict Signup
Disable public signups if you want to control user access:
MB_ENABLE_PASSWORD_LOGIN: trueThen go to Admin → Settings → Authentication and disable "Enable Password Login" for new users (admin creates accounts).
Backup Strategy
Backup your Metabase configuration and data:
#!/bin/bash
# /opt/metabase/backup.sh
BACKUP_DIR="/backups/metabase"
DATE=$(date +%Y%m%d_%H%M%S)
COMPOSE_DIR="/root/metabase"
mkdir -p $BACKUP_DIR
# Backup PostgreSQL database
docker exec metabase-db pg_dump -U metabase metabase > $BACKUP_DIR/metabase_db_$DATE.sql
# Compress backup
gzip $BACKUP_DIR/metabase_db_$DATE.sql
# Keep only last 14 days of backups
find $BACKUP_DIR -name "*.sql.gz" -mtime +14 -delete
echo "Backup completed: metabase_db_$DATE.sql.gz"chmod +x /opt/metabase/backup.sh
mkdir -p /backups/metabase
# Add to crontab (daily at 3 AM)
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/metabase/backup.sh") | crontab -# Stop Metabase
cd ~/metabase && docker compose stop metabase
# Restore database
gunzip -c /backups/metabase/metabase_db_20241217.sql.gz | \
docker exec -i metabase-db psql -U metabase metabase
# Start Metabase
docker compose start metabaseUpdates & Maintenance
Keep Metabase updated:
cd ~/metabase
# Backup first!
/opt/metabase/backup.sh
# Pull latest image
docker compose pull
# Recreate container with new image
docker compose up -d
# Check logs for any migration issues
docker compose logs -f metabase⚠️ Important: Always backup before updating! Check release notes for breaking changes.
# View running containers
docker compose ps
# Check resource usage
docker stats metabase metabase-db
# View logs
docker compose logs --tail=100 metabaseTroubleshooting
Metabase Won't Start
docker compose logs metabase
docker compose logs metabase-db
# Check if database is healthy
docker compose exec metabase-db pg_isready -U metabaseOut of Memory
# Add to metabase service in docker-compose.yml:
environment:
JAVA_OPTS: "-Xmx2g" # Adjust based on available RAMSlow Queries
- • Check database indexes on frequently queried columns
- • Use Metabase's query caching (Admin → Settings → Caching)
- • Create database views for complex queries
- • Optimize your database server resources
502 Bad Gateway
# Check if Metabase is running
docker compose ps
# Check if port is listening
curl -I http://127.0.0.1:3000
# Restart services
docker compose restart
sudo systemctl reload nginxReset Admin Password
# Connect to database
docker compose exec metabase-db psql -U metabase metabase
# Reset password (user will need to set new password on login)
UPDATE core_user SET password = NULL WHERE email = 'admin@example.com';
\q
# Restart Metabase
docker compose restart metabaseMetabase Deployed Successfully!
Your self-hosted business intelligence platform is ready. Start creating beautiful dashboards and exploring your data!
