How to Self-Host Plane on a VPS: Open-Source Project Management for Engineering Teams

How to Self-Host Plane on a VPS: Open-Source Project Management for Engineering Teams

Plane is an open-source project management tool built for engineering teams — it provides issue tracking, sprints (Cycles), epics (Modules), roadmaps, pages (wiki), analytics, and GitHub integration. Plane targets the same market as Linear ($8/user/month) and Jira ($8.15/user/month). Self-hosting Plane on a VPS eliminates per-seat licensing for teams of any size.

What Plane Provides

  • Issues: Create, assign, prioritize, and track work items with custom states, labels, and priorities
  • Cycles: Time-boxed sprints with burndown charts and velocity tracking
  • Modules: Group issues into epics or feature areas with progress tracking
  • Views: Board (Kanban), List, Spreadsheet, Gantt, and Calendar views
  • Pages: Collaborative document editor for specifications, meeting notes, and wikis
  • Analytics: Issue distribution by state, assignee, priority, and custom filters
  • GitHub integration: Link commits and pull requests to issues

Server Requirements

  • Minimum 4 GB RAM (Plane runs ~8 Docker services)
  • Docker and Docker Compose
  • 20+ GB NVMe storage

Step 1: Clone Plane

<code">mkdir -p /opt/plane && cd /opt/plane
git clone https://github.com/makeplane/plane.git .

# Copy environment template
cp .env.example .env
nano .env
<code"># Required changes:
SECRET_KEY=your_50_char_random_key   # python3 -c "import secrets; print(secrets.token_hex(25))"

# Database
POSTGRES_USER=plane
POSTGRES_PASSWORD=StrongPlaneDbPassword!
POSTGRES_DB=plane

# Redis
REDIS_URL=redis://plane-redis:6379/

# Application
WEB_URL=https://plane.yourdomain.com
CORS_ALLOWED_ORIGINS=https://plane.yourdomain.com

# Email (required for invites)
EMAIL_HOST=smtp.mailgun.org
EMAIL_PORT=587
EMAIL_HOST_USER=postmaster@mg.yourdomain.com
EMAIL_HOST_PASSWORD=your_smtp_password
EMAIL_USE_TLS=1
DEFAULT_FROM_EMAIL=plane@yourdomain.com

# File storage — local or S3
USE_MINIO=1   # Use built-in MinIO for S3-compatible storage
MINIO_ROOT_USER=plane_minio_user
MINIO_ROOT_PASSWORD=StrongMinioPassword!

Step 2: Start Plane

<code"># Plane uses its own setup script
chmod +x setup.sh
sudo ./setup.sh start

# Or use Docker Compose directly:
docker compose -f docker-compose.yml up -d

# Check all services are running
docker compose ps

# Plane services: web, api, worker, beat (scheduler), postgres, redis, minio

Step 3: Nginx Reverse Proxy

<code">sudo nano /etc/nginx/sites-available/plane
<code">server {
    listen 80;
    server_name plane.yourdomain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name plane.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/plane.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/plane.yourdomain.com/privkey.pem;

    client_max_body_size 50M;

    # Next.js frontend
    location / {
        proxy_pass http://127.0.0.1:3000;
        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-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
    }

    # Django API
    location /api/ {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # File storage (MinIO)
    location /uploads/ {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header Host $host;
    }
}
<code">sudo ln -s /etc/nginx/sites-available/plane /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d plane.yourdomain.com

Step 4: Initial Setup

  1. Visit https://plane.yourdomain.com
  2. Create your admin account (first user)
  3. Create a Workspace (e.g., “Acme Engineering”)
  4. Create a Project → add members
  5. Configure states, labels, and priority levels per project

Step 5: Configure GitHub Integration

  1. Go to github.com/settings/apps → New GitHub App
  2. Homepage URL: https://plane.yourdomain.com
  3. Callback URL: https://plane.yourdomain.com/auth/github/callback/
  4. Webhook URL: https://plane.yourdomain.com/api/v1/integrations/github/webhook/
  5. Permissions: Issues (read/write), Pull requests (read/write), Metadata (read)
  6. Add the GitHub App ID and private key to Plane’s Settings → Integrations

Key Plane Workflows

<code"># Creating issues via API
curl -X POST https://plane.yourdomain.com/api/v1/workspaces/{slug}/projects/{id}/issues/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Implement user authentication",
    "state": "backlog_state_id",
    "priority": "high",
    "assignees": ["user_id"]
  }'

# Export issues to CSV
curl https://plane.yourdomain.com/api/v1/workspaces/{slug}/exports/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"provider": "csv", "project": ["project_id"]}'

Updating Plane

<code">cd /opt/plane
git pull
sudo ./setup.sh update

Getting Started

Plane needs 4 GB RAM for its eight Docker services (API, worker, scheduler, Next.js frontend, PostgreSQL, Redis, MinIO). KVM VPS plans at VPS.DO with 4 GB RAM run Plane comfortably for teams up to 50 people. For larger teams or higher issue volumes, 8 GB RAM provides comfortable headroom for the PostgreSQL query load.

Conclusion

Self-hosted Plane provides a modern, linear-style project management experience — Kanban boards, sprints, epics, roadmaps, and GitHub integration — without $8/user/month Linear fees or $8.15/user/month Jira fees. For a 15-person engineering team, that’s $1,440/year saved against Linear. The Docker Compose deployment is maintained by the Plane team with a dedicated setup script for easy installation and updates.

Fast • Reliable • Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!