Skip to main content
Docker Compose is the quickest way to self-host Plane. This method is ideal for small to medium teams and development environments.

Prerequisites

1

Install Docker

Ensure Docker Engine 20.10+ and Docker Compose v2+ are installed and running.
curl -fsSL https://get.docker.com | sh
Verify installation:
docker --version
docker compose version
2

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
3

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.
1

Create Installation Directory

mkdir plane-selfhost
cd plane-selfhost
2

Download Setup Script

curl -fsSL -o setup.sh https://github.com/makeplane/plane/releases/latest/download/setup.sh
chmod +x setup.sh
3

Run Installation

./setup.sh
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
4

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:
plane.env
# 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.
5

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).
6

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

1

Download Restore Script

curl -fsSL -o restore.sh https://github.com/makeplane/plane/releases/latest/download/restore.sh
chmod +x restore.sh
2

Stop Plane Services

./setup.sh
# Select option 3 (Stop)
3

Run Restore

./restore.sh /path/to/backup/folder/20240722-0914
The script will restore all three data volumes.
4

Start Services

./setup.sh
# Select option 2 (Start)

Upgrading Plane

Always backup your data before upgrading.
1

Create Backup

./setup.sh
# Select option 7 (Backup Data)
2

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
3

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.
4

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:
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

plane.env
REDIS_HOST="your-redis-host"
REDIS_PORT="6379"
REDIS_URL="redis://your-redis-host:6379/"

External S3-Compatible Storage

plane.env
# 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

  1. Check if ports are available:
    sudo lsof -i :80
    sudo lsof -i :443
    
  2. View service logs:
    cd plane-app
    docker compose logs api worker migrator
    
  3. Verify environment variables:
    docker compose config
    

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:
docker-compose.yaml
# 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

Performance Optimization

Increase Worker Replicas

For better background job processing:
plane.env
GUNICORN_WORKERS=4  # Increase API workers

Database Optimization

docker-compose.yaml
plane-db:
  command: postgres -c 'max_connections=1000' -c 'shared_buffers=256MB' -c 'effective_cache_size=1GB'

Enable Redis Persistence

docker-compose.yaml
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

Build docs developers (and LLMs) love