Deploy with Docker Compose
Deploy OpenPanel using Docker Compose on your own server
This guide will help you deploy OpenPanel using Docker Compose. This method gives you full control over your deployment and is perfect for self-hosting on a VPS or dedicated server.
Prerequisites
- A VPS or server. Docker is checked for automatically, and on Linux the CLI offers to install it.
- At least 4GB RAM (6GB+ recommended) โ the stack includes Redpanda alongside Postgres, Redis and ClickHouse
- Domain name pointing to your server (optional but recommended)
- Basic knowledge of command line
๐โโ๏ธ This works on any Linux server (x64 or arm64) that can run Docker. You don't need Node, npm or git.
Quick Start
Install the CLI
curl -fsSL https://raw.githubusercontent.com/Openpanel-dev/openpanel/main/self-hosting/install.sh | shThis downloads a single openpanel binary, verifies its checksum and puts it on your PATH. Builds for Linux (x64 and arm64) are also on the releases page.
Run the setup
openpanel initIt checks your host (Docker, Docker Compose, memory), then asks about:
- Your domain name
- Whether to run Postgres, ClickHouse and Redis for you, or connect your own
- Whether to use the bundled Caddy (automatic HTTPS) or your own reverse proxy
- Email (optional)
Secrets, the worker count and the queue-dashboard password are generated. It writes docker-compose.yml, .env and the supporting config files to ~/openpanel (use --dir <path> to change that) and prints the queue-dashboard password once.
For unattended setups every answer is a flag, e.g. openpanel init --yes --domain https://analytics.example.com. Run openpanel --help to see them.
Start the Services
openpanel upThis will start all required services:
- op-db: PostgreSQL database
- op-kv: Redis cache
- op-ch: ClickHouse analytics database
- op-rp: Redpanda (Kafka-compatible event broker, see Event Streaming)
- op-api: OpenPanel API server
- op-dashboard: OpenPanel dashboard (frontend)
- op-worker: Background worker for processing events
- op-proxy: Caddy reverse proxy, unless you chose your own
Verify Installation
openpanel statusAll services should show as "healthy" or "running". To watch the logs:
openpanel logsOnce all services are healthy, you can access OpenPanel at your configured domain.
Configuration
Environment Variables
openpanel init configures most environment variables for you. You can edit the .env file in your install directory if needed.
For a complete reference of all available environment variables, see the Environment Variables documentation.
Changed the .env file? run openpanel reload. It checks the file for mistakes first, then recreates only the services whose settings changed; your databases keep running. A plain docker compose restart is not enough: it restarts containers with their old environment.
The generated .env also contains commented-out blocks for optional features. Uncomment and fill them in to enable social login with Google or GitHub and the Google Search Console integration.
Docker Image Versions
Each CLI release is built for one OpenPanel image tag, and openpanel upgrade moves the lindesvard/openpanel-* images in your docker-compose.yml to it, including a version you pinned yourself. The compose changes an upgrade makes only work with the images they were released for. To stay on a version, don't run upgrade. Images from other registries are left alone.
Scaling Workers
The worker count is set in docker-compose.yml as ${OP_WORKER_REPLICAS:-N}, where N is what init chose. Override it by adding a line to .env, then apply it:
OP_WORKER_REPLICAS=3openpanel upManaging Your Deployment
Run these anywhere: the CLI finds your install (the current directory, ./self-hosting in an old git clone, the last install it used, or a running OpenPanel stack) and prints which one it picked. Pass --dir <path> to choose explicitly.
Basic Operations
openpanel up # Start all OpenPanel services
openpanel down # Stop all OpenPanel services (data is kept)
openpanel reload # Apply changes to .env or docker-compose.yml
openpanel restart # Recreate every container (a full restart)
openpanel logs # Follow logs from all services
openpanel status # Show running servicesView Logs
openpanel logs # all services
openpanel logs op-api # one serviceCheck Your Setup
openpanel doctorChecks that Docker is running and has enough memory, and that your docker-compose.yml and .env match what this version expects. openpanel doctor --fix repairs what it can and keeps the originals as <file>.bak.
Update OpenPanel
openpanel upgradeThis will:
- Update the CLI itself, after verifying its checksum
- Run the
doctorchecks and offer to fix yourdocker-compose.ymland.envfor the new version - Pull the latest Docker images
- Restart the services
Always backup your data before updating. The database migrations will run automatically when the API container starts. Also read any changes in the changelog.
Start Over
openpanel resetDeletes this install's data volumes after you type the directory name to confirm. docker-compose.yml, .env and Caddy's HTTPS certificates are kept, so a fresh start does not re-request certificates.
Backup and Restore
Backup
Backup your PostgreSQL database:
docker compose exec op-db pg_dump -U postgres postgres > backup.sqlBackup volumes:
docker run --rm -v openpanel_op-db-data:/data -v $(pwd):/backup alpine tar czf /backup/db-backup.tar.gz /dataRestore
Restore PostgreSQL database:
docker compose exec -T op-db psql -U postgres postgres < backup.sqlTroubleshooting
Services Won't Start
-
Check Docker and Docker Compose versions:
docker --version docker compose version -
Check available disk space:
df -h -
Check logs for errors:
docker compose logs
Database Connection Issues
If services can't connect to the database:
-
Verify the database is healthy:
docker compose ps op-db -
Check database logs:
docker compose logs op-db -
Verify
DATABASE_URLin your.envfile matches the service nameop-db
Port Conflicts
If ports 80 or 443 are already in use, you can:
-
Change the ports in
docker-compose.yml:ports: - "8080:80" - "8443:443" -
Or stop the conflicting service
Health Check Failures
If health checks are failing:
-
Check if services are actually running:
docker compose ps -
Increase health check timeout in
docker-compose.yml:healthcheck: interval: 30s timeout: 10s retries: 10
Using Your Own Reverse Proxy
If you want to use NGINX, Traefik, or another reverse proxy instead of the bundled Caddy โ or put a TLS terminator upstream of Caddy โ see the dedicated Reverse proxy setup guide. It covers the working NGINX config, the Connection: upgrade SSR-break gotcha, and the WebSocket upgrade headers required for the Realtime view.
Next Steps
- Configure email settings for password resets and invitations
- Set up AI integration for the analytics assistant
- Configure SDK to track events from your applications
- Enable social login with Google or GitHub
- Connect Google Search Console for SEO data