Docker Compose is the quickest way to self-host Plane. This method is ideal for small to medium teams and development environments.
Prerequisites
Install Docker
Ensure Docker Engine 20.10+ and Docker Compose v2+ are installed and running. Linux (Ubuntu/Debian)
macOS
Windows
curl -fsSL https://get.docker.com | sh
Verify installation: docker --version
docker compose version
System Requirements
CPU : 2 vCPU minimum (4 vCPU recommended)
RAM : 4GB minimum (8GB recommended)
Storage : 20GB minimum
OS : Ubuntu 20.04+, Amazon Linux 2, macOS, or Windows with WSL2
User Permissions
Ensure your user has Docker permissions. On Linux, you may need: sudo usermod -aG docker $USER
newgrp docker
Quick Start Installation
Plane provides an interactive setup script that handles the entire installation process.
Create Installation Directory
mkdir plane-selfhost
cd plane-selfhost
Download Setup Script
curl -fsSL -o setup.sh https://github.com/makeplane/plane/releases/latest/download/setup.sh
chmod +x setup.sh
Run Installation
You’ll see a menu like this: Select an Action you want to perform:
1) Install (x86_64)
2) Start
3) Stop
4) Restart
5) Upgrade
6) View Logs
7) Backup Data
8) Exit
Action [2]: 1
Select 1 to install. This creates a plane-app directory with:
docker-compose.yaml - Service definitions
plane.env - Environment configuration
Configure Environment
Edit the plane-app/plane.env file before starting services: cd plane-app
nano plane.env # or use your preferred editor
Critical settings to configure :# Web URL - Change to your domain or IP
WEB_URL = "http://localhost"
# Port configuration
LISTEN_HTTP_PORT = 80
LISTEN_HTTPS_PORT = 443
# CORS configuration - Must match WEB_URL
CORS_ALLOWED_ORIGINS = "http://localhost"
# Database credentials (change in production)
POSTGRES_PASSWORD = "plane"
# Object storage credentials (change in production)
AWS_ACCESS_KEY_ID = "access-key"
AWS_SECRET_ACCESS_KEY = "secret-key"
See the configuration guide for all available options.
Start Services
Run the setup script again and select 2 : cd ..
./setup.sh
# Select option 2 (Start)
The script will:
Pull Docker images for all services
Create Docker volumes for data persistence
Start all containers
Run database migrations
Wait for all services to start (2-5 minutes depending on your connection).
Access Plane
Open your browser and navigate to the URL you configured:
Local: http://localhost
Custom port: http://localhost:8080 (if you set LISTEN_HTTP_PORT=8080)
Domain: https://plane.example.com
You’ll be prompted to create the first instance admin account.
Docker Compose Configuration
The docker-compose.yaml file defines all services. Here’s an overview of the architecture:
docker-compose.yaml (simplified)
services :
# Frontend applications
web :
image : makeplane/plane-frontend:latest
depends_on : [ api ]
space :
image : makeplane/plane-space:latest
depends_on : [ api , web ]
admin :
image : makeplane/plane-admin:latest
depends_on : [ api , web ]
# Backend services
api :
image : makeplane/plane-backend:latest
command : ./bin/docker-entrypoint-api.sh
env_file : [ .env ]
depends_on : [ plane-db , plane-redis , plane-mq ]
worker :
image : makeplane/plane-backend:latest
command : ./bin/docker-entrypoint-worker.sh
depends_on : [ api , plane-db , plane-redis ]
beat-worker :
image : makeplane/plane-backend:latest
command : ./bin/docker-entrypoint-beat.sh
depends_on : [ api , plane-db , plane-redis ]
live :
image : makeplane/plane-live:latest
# Infrastructure
plane-db :
image : postgres:15.7-alpine
command : postgres -c 'max_connections=1000'
volumes : [ pgdata:/var/lib/postgresql/data ]
plane-redis :
image : valkey/valkey:7.2.11-alpine
volumes : [ redisdata:/data ]
plane-mq :
image : rabbitmq:3.13.6-management-alpine
volumes : [ rabbitmq_data:/var/lib/rabbitmq ]
plane-minio :
image : minio/minio:latest
command : server /export --console-address ":9090"
volumes : [ uploads:/export ]
proxy :
image : makeplane/plane-proxy:latest
ports :
- "${LISTEN_HTTP_PORT}:80"
- "${LISTEN_HTTPS_PORT}:443"
depends_on : [ web , api , space , admin , live ]
volumes :
pgdata :
redisdata :
uploads :
rabbitmq_data :
Do not modify the docker-compose.yaml file directly. The setup script may overwrite it during upgrades. Use environment variables in plane.env instead.
Management Operations
Starting Services
./setup.sh
# Select option 2 (Start)
Alternatively, use Docker Compose directly:
cd plane-app
docker compose up -d
Stopping Services
./setup.sh
# Select option 3 (Stop)
Or with Docker Compose:
cd plane-app
docker compose down
Restarting Services
Useful after configuration changes:
./setup.sh
# Select option 4 (Restart)
Or restart specific services:
cd plane-app
docker compose restart api worker
Viewing Logs
Interactive log viewer:
./setup.sh
# Select option 6 (View Logs)
# Then select the service (API, Worker, etc.)
Direct log access:
cd plane-app
# All services
docker compose logs -f
# Specific service
docker compose logs -f api
# Last 100 lines
docker compose logs --tail=100 api
Checking Service Status
cd plane-app
docker compose ps
Backup and Restore
Creating Backups
The setup script includes a backup utility:
./setup.sh
# Select option 7 (Backup Data)
This creates a timestamped backup in plane-app/backup/YYYYMMDD-HHMM/ containing:
pgdata.tar.gz - PostgreSQL database
redisdata.tar.gz - Redis data
uploads.tar.gz - User uploads and files
Schedule regular backups using cron: # Edit crontab
crontab -e
# Add daily backup at 2 AM
0 2 * * * cd /path/to/plane-selfhost && ./setup.sh backup
Restoring from Backup
Download Restore Script
curl -fsSL -o restore.sh https://github.com/makeplane/plane/releases/latest/download/restore.sh
chmod +x restore.sh
Stop Plane Services
./setup.sh
# Select option 3 (Stop)
Run Restore
./restore.sh /path/to/backup/folder/20240722-0914
The script will restore all three data volumes.
Start Services
./setup.sh
# Select option 2 (Start)
Upgrading Plane
Always backup your data before upgrading.
Create Backup
./setup.sh
# Select option 7 (Backup Data)
Run Upgrade
./setup.sh
# Select option 5 (Upgrade)
This will:
Stop running services
Download the latest docker-compose.yaml
Download the latest plane.env template
Pull new Docker images
Review Configuration
Important : Review the new plane.env file for new settings:cd plane-app
diff plane.env plane.env.backup # If you have a backup
Merge your custom configuration with new defaults.
Start Updated Instance
./setup.sh
# Select option 2 (Start)
The migrator service will automatically run database migrations.
SSL/HTTPS Configuration
Plane’s proxy service supports automatic SSL certificate generation using Let’s Encrypt.
Using Let’s Encrypt
Edit plane.env:
# Your domain name
WEB_URL = "https://plane.example.com"
CORS_ALLOWED_ORIGINS = "https://plane.example.com"
# Let's Encrypt configuration
CERT_EMAIL = "[email protected] "
CERT_ACME_CA = "https://acme-v02.api.letsencrypt.org/directory"
# Port configuration (use standard ports)
LISTEN_HTTP_PORT = 80
LISTEN_HTTPS_PORT = 443
# Trust all proxies (adjust for your setup)
TRUSTED_PROXIES = "0.0.0.0/0"
SITE_ADDRESS = ":80"
Ensure your domain points to your server’s IP and ports 80/443 are accessible from the internet.
Using Custom Certificates
If you have your own SSL certificates, you can mount them into the proxy container. Modify the docker-compose.yaml proxy service:
proxy :
volumes :
- /path/to/your/cert.pem:/etc/ssl/certs/plane.crt:ro
- /path/to/your/key.pem:/etc/ssl/private/plane.key:ro
External Services
You can use external managed services instead of the bundled containers.
External PostgreSQL
Edit plane.env:
# Database configuration
DATABASE_URL = "postgresql://username:password@your-db-host:5432/plane"
POSTGRES_USER = "username"
POSTGRES_PASSWORD = "password"
POSTGRES_DB = "plane"
POSTGRES_HOST = "your-db-host"
POSTGRES_PORT = "5432"
Comment out the plane-db service in docker-compose.yaml or use a custom compose file.
External Redis
REDIS_HOST = "your-redis-host"
REDIS_PORT = "6379"
REDIS_URL = "redis://your-redis-host:6379/"
External S3-Compatible Storage
# Disable MinIO
USE_MINIO = 0
# AWS S3 or compatible service
AWS_REGION = "us-east-1"
AWS_ACCESS_KEY_ID = "your-access-key"
AWS_SECRET_ACCESS_KEY = "your-secret-key"
AWS_S3_ENDPOINT_URL = "https://s3.amazonaws.com" # Or your S3 endpoint
AWS_S3_BUCKET_NAME = "plane-uploads"
Troubleshooting
Services Won’t Start
Check if ports are available:
sudo lsof -i :80
sudo lsof -i :443
View service logs:
cd plane-app
docker compose logs api worker migrator
Verify environment variables:
Database Connection Errors
# Check if PostgreSQL is running
docker compose ps plane-db
# View PostgreSQL logs
docker compose logs plane-db
# Check database connectivity from API
docker compose exec api python manage.py check --database default
Migration Failures
# View migrator logs
docker compose logs migrator
# Manually run migrations
docker compose run --rm migrator python manage.py migrate
Out of Memory
If services are crashing due to memory issues:
# Add memory limits to services
api :
deploy :
resources :
limits :
memory : 2G
reservations :
memory : 1G
Permission Errors
# Fix volume permissions
sudo chown -R $( id -u ) : $( id -g ) plane-app/
# Or run with sudo
sudo ./setup.sh
Increase Worker Replicas
For better background job processing:
GUNICORN_WORKERS = 4 # Increase API workers
Database Optimization
plane-db :
command : postgres -c 'max_connections=1000' -c 'shared_buffers=256MB' -c 'effective_cache_size=1GB'
Enable Redis Persistence
plane-redis :
command : valkey-server --save 60 1 --loglevel warning
Next Steps
Configuration Configure environment variables, email, OAuth, and more
Instance Admin Set up instance administration and manage settings