Self-Hosting¶
Run Meridian on your own infrastructure. Choose the path that matches how much control you want versus how much setup you are willing to do.
Choose a setup path¶
The fastest path for local or small-team usage. No Python required.
Windows
- Download
meridian.exe - Double-click to run
- Meridian opens your browser at
http://localhost:7878
macOS (Apple Silicon)
curl -Lo meridian https://github.com/meridianmcp/Meridian/releases/latest/download/meridian-mac-arm64
chmod +x meridian
xattr -d com.apple.quarantine meridian 2>/dev/null || true
./meridian
Linux
Use the published Docker Hub image when you want a clean containerized setup.
docker pull meridianmcp/meridian:latest
docker run --rm -p 7878:7878 --env-file .env \
-v "$(pwd)/data:/app/data" \
meridianmcp/meridian:latest
If you prefer source-based Compose:
By default, SQLite data is persisted in ./data/meridian.db.
Best for contributors and active development.
For hot reload:
Confirm the server is healthy:
The dashboard is at http://localhost:7878.
Postgres setup with Neon¶
Neon is a good default when you want a hosted Postgres backend for a self-hosted Meridian server.
- Create a project at neon.tech
- Copy the Postgres connection string
- Set
MERIDIAN_DB_URL - Start Meridian normally
export MERIDIAN_DB_URL="postgresql://neondb_owner:...@ep-xxx.us-east-2.aws.neon.tech/neondb?sslmode=require"
pixi run start
Meridian auto-detects Postgres from the URL prefix and switches to psycopg3
(the connection pool, autocommit, and adapter translation live in
meridian/pg_adapter.py; SQLite remains the default for local installs).
Environment variables¶
See the full Configuration Reference.
Key variables for self-hosting:
| Variable | What to set |
|---|---|
SESSION_SECRET |
Long random string used to sign session cookies |
APP_URL |
Public base URL such as https://meridian.yourdomain.com |
MERIDIAN_DB_URL |
Optional Postgres URL; SQLite is fine for smaller installs |
SITE_PASSWORD |
Optional password gate for preview deployments |
Example .env:
SESSION_SECRET=replace-me
# APP_URL=https://meridian.example.com
# MERIDIAN_DB_URL=postgresql://user:pass@host/dbname
# SITE_PASSWORD=preview-password
Expose localhost for browser clients¶
Claude remote connectors and ChatGPT custom apps need a public HTTPS MCP
endpoint. If you are running Meridian on localhost, a quick test path is a
Cloudflare Tunnel:
Cloudflare prints a temporary public URL such as https://random-name.trycloudflare.com.
Use that host plus /mcp in Claude or ChatGPT:
Note
This is great for demos and short-lived testing. For a stable setup, put
Meridian behind your own domain and reverse proxy, then set APP_URL
accordingly.
Reverse proxy setup¶
nginx¶
server {
listen 80;
server_name meridian.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name meridian.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/meridian.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/meridian.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:7878;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_read_timeout 3600s;
}
}
WebSocket support
Meridian uses WebSockets for the live dashboard. Keep the Upgrade and
Connection headers in place.
Caddy¶
meridian.yourdomain.com {
reverse_proxy localhost:7878 {
header_up Host {host}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto {scheme}
}
}
Caddy handles TLS automatically.
Upgrading¶
cd Meridian
git pull origin main
pixi install # or: docker pull meridianmcp/meridian:latest
pixi run start # or: docker compose up -d
Meridian runs database migrations automatically on startup.
Backup and restore¶
SQLite¶
# Backup
cp data/meridian.db "data/meridian-$(date +%Y%m%d).db"
# Restore
cp data/meridian-20260101.db data/meridian.db
Automated daily backup example:
0 2 * * * cp /path/to/Meridian/data/meridian.db \
/backups/meridian-$(date +%Y%m%d).db && \
find /backups -name "meridian-*.db" -mtime +7 -delete
Postgres¶
pg_dump "$MERIDIAN_DB_URL" -Fc -f meridian-backup-$(date +%Y%m%d).dump
pg_restore -d "$MERIDIAN_DB_URL" meridian-backup-20260101.dump
Running multiple instances¶
SQLite does not support multiple writers
If you need multiple Meridian instances for HA or load balancing, move to Postgres first.
services:
meridian-1:
image: meridianmcp/meridian:latest
ports: ["7878:7878"]
environment:
- MERIDIAN_DB_URL=postgresql://...
meridian-2:
image: meridianmcp/meridian:latest
ports: ["7879:7878"]
environment:
- MERIDIAN_DB_URL=postgresql://...
Put nginx or Caddy in front once you scale past a single instance.