Plane Project Management
Open source project tracking tool like Jira/Linear.
Overview
Plane is a modern, open-source project management platform that serves as a powerful alternative to Jira and Linear. Born from the need for developer-friendly issue tracking without vendor lock-in, Plane provides agile project management with cycles, modules, views, and real-time collaboration features. The platform emphasizes speed and user experience while maintaining the depth required for complex project workflows.
This stack combines Plane's three-tier architecture with robust data infrastructure. The plane-web frontend delivers a responsive React-based interface, while plane-api handles business logic and REST endpoints. The plane-worker processes background tasks through Celery queues. PostgreSQL stores structured project data with full ACID compliance for data integrity, Redis provides sub-millisecond caching and task queue management, and MinIO offers S3-compatible object storage for file attachments and assets.
Development teams, startups, and organizations seeking project management control without SaaS limitations will find this configuration valuable. Unlike hosted solutions, this self-hosted approach eliminates per-user costs, provides complete data ownership, and allows custom integrations. The combination is particularly suited for teams already comfortable with containerized infrastructure who need enterprise-grade project tracking with the flexibility of open-source tooling.
Key Features
- Agile project management with sprints (cycles), feature groupings (modules), and custom issue views
- Real-time collaborative editing and commenting powered by Redis pub/sub messaging
- Advanced PostgreSQL-backed analytics with custom fields, filters, and project insights
- S3-compatible file attachment system using MinIO for images, documents, and project assets
- Celery-based background processing for notifications, imports, and scheduled tasks
- Multi-workspace support with team permissions and project-level access controls
- API-first architecture enabling custom integrations and automation workflows
- GitHub, GitLab, and other VCS integrations for linking commits to issues
Common Use Cases
- 1Software development teams transitioning from Jira to avoid licensing costs and vendor lock-in
- 2Startups requiring enterprise project management features without per-seat pricing constraints
- 3Organizations with data sovereignty requirements needing on-premises issue tracking
- 4Development agencies managing multiple client projects with workspace isolation
- 5Open source projects needing professional project management tools with community hosting
- 6Companies requiring custom project workflows and integrations not available in SaaS solutions
- 7Teams in regulated industries needing complete audit trails and data control for compliance
Prerequisites
- Docker Engine 20.10+ and Docker Compose V2 for container orchestration support
- Minimum 4GB RAM (2GB for PostgreSQL/MinIO, 1GB for Plane services, 512MB for Redis)
- Available ports 3000 (web interface), 8000 (API), and 9001 (MinIO console)
- Basic understanding of environment variable configuration for secrets management
- Familiarity with PostgreSQL concepts for database maintenance and backups
- Knowledge of object storage concepts for file upload and MinIO bucket management
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 plane-web: 3 image: makeplane/plane-frontend:latest4 ports: 5 - "3000:3000"6 environment: 7 NEXT_PUBLIC_API_BASE_URL: http://localhost:80008 depends_on: 9 - plane-api10 networks: 11 - plane-net12 restart: unless-stopped1314 plane-api: 15 image: makeplane/plane-backend:latest16 ports: 17 - "8000:8000"18 environment: 19 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}20 REDIS_URL: redis://redis:637921 SECRET_KEY: ${SECRET_KEY}22 AWS_ACCESS_KEY_ID: ${MINIO_ACCESS_KEY}23 AWS_SECRET_ACCESS_KEY: ${MINIO_SECRET_KEY}24 AWS_S3_BUCKET_NAME: uploads25 AWS_S3_ENDPOINT_URL: http://minio:900026 depends_on: 27 postgres: 28 condition: service_healthy29 redis: 30 condition: service_started31 networks: 32 - plane-net33 restart: unless-stopped3435 plane-worker: 36 image: makeplane/plane-backend:latest37 command: celery -A plane worker -l info38 environment: 39 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}40 REDIS_URL: redis://redis:637941 SECRET_KEY: ${SECRET_KEY}42 depends_on: 43 - plane-api44 networks: 45 - plane-net46 restart: unless-stopped4748 postgres: 49 image: postgres:16-alpine50 environment: 51 POSTGRES_USER: ${POSTGRES_USER}52 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}53 POSTGRES_DB: ${POSTGRES_DB}54 volumes: 55 - postgres_data:/var/lib/postgresql/data56 healthcheck: 57 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]58 interval: 10s59 timeout: 5s60 retries: 561 networks: 62 - plane-net63 restart: unless-stopped6465 redis: 66 image: redis:7-alpine67 volumes: 68 - redis_data:/data69 networks: 70 - plane-net71 restart: unless-stopped7273 minio: 74 image: minio/minio:latest75 ports: 76 - "9001:9001"77 environment: 78 MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}79 MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}80 volumes: 81 - minio_data:/data82 command: server /data --console-address ":9001"83 networks: 84 - plane-net85 restart: unless-stopped8687volumes: 88 postgres_data: 89 redis_data: 90 minio_data: 9192networks: 93 plane-net: 94 driver: bridge.env Template
.env
1# PostgreSQL2POSTGRES_USER=plane3POSTGRES_PASSWORD=secure_postgres_password4POSTGRES_DB=plane56# Plane7SECRET_KEY=$(openssl rand -hex 32)89# MinIO10MINIO_ACCESS_KEY=plane11MINIO_SECRET_KEY=secure_minio_passwordUsage Notes
- 1Plane at http://localhost:3000
- 2API at http://localhost:8000
- 3Modern issue tracking UI
- 4Cycles, modules, and views
Individual Services(6 services)
Copy individual services to mix and match with your existing compose files.
plane-web
plane-web:
image: makeplane/plane-frontend:latest
ports:
- "3000:3000"
environment:
NEXT_PUBLIC_API_BASE_URL: http://localhost:8000
depends_on:
- plane-api
networks:
- plane-net
restart: unless-stopped
plane-api
plane-api:
image: makeplane/plane-backend:latest
ports:
- "8000:8000"
environment:
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
REDIS_URL: redis://redis:6379
SECRET_KEY: ${SECRET_KEY}
AWS_ACCESS_KEY_ID: ${MINIO_ACCESS_KEY}
AWS_SECRET_ACCESS_KEY: ${MINIO_SECRET_KEY}
AWS_S3_BUCKET_NAME: uploads
AWS_S3_ENDPOINT_URL: http://minio:9000
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
networks:
- plane-net
restart: unless-stopped
plane-worker
plane-worker:
image: makeplane/plane-backend:latest
command: celery -A plane worker -l info
environment:
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
REDIS_URL: redis://redis:6379
SECRET_KEY: ${SECRET_KEY}
depends_on:
- plane-api
networks:
- plane-net
restart: unless-stopped
postgres
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test:
- CMD-SHELL
- pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
interval: 10s
timeout: 5s
retries: 5
networks:
- plane-net
restart: unless-stopped
redis
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
networks:
- plane-net
restart: unless-stopped
minio
minio:
image: minio/minio:latest
ports:
- "9001:9001"
environment:
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
volumes:
- minio_data:/data
command: server /data --console-address ":9001"
networks:
- plane-net
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 plane-web:5 image: makeplane/plane-frontend:latest6 ports:7 - "3000:3000"8 environment:9 NEXT_PUBLIC_API_BASE_URL: http://localhost:800010 depends_on:11 - plane-api12 networks:13 - plane-net14 restart: unless-stopped1516 plane-api:17 image: makeplane/plane-backend:latest18 ports:19 - "8000:8000"20 environment:21 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}22 REDIS_URL: redis://redis:637923 SECRET_KEY: ${SECRET_KEY}24 AWS_ACCESS_KEY_ID: ${MINIO_ACCESS_KEY}25 AWS_SECRET_ACCESS_KEY: ${MINIO_SECRET_KEY}26 AWS_S3_BUCKET_NAME: uploads27 AWS_S3_ENDPOINT_URL: http://minio:900028 depends_on:29 postgres:30 condition: service_healthy31 redis:32 condition: service_started33 networks:34 - plane-net35 restart: unless-stopped3637 plane-worker:38 image: makeplane/plane-backend:latest39 command: celery -A plane worker -l info40 environment:41 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}42 REDIS_URL: redis://redis:637943 SECRET_KEY: ${SECRET_KEY}44 depends_on:45 - plane-api46 networks:47 - plane-net48 restart: unless-stopped4950 postgres:51 image: postgres:16-alpine52 environment:53 POSTGRES_USER: ${POSTGRES_USER}54 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}55 POSTGRES_DB: ${POSTGRES_DB}56 volumes:57 - postgres_data:/var/lib/postgresql/data58 healthcheck:59 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]60 interval: 10s61 timeout: 5s62 retries: 563 networks:64 - plane-net65 restart: unless-stopped6667 redis:68 image: redis:7-alpine69 volumes:70 - redis_data:/data71 networks:72 - plane-net73 restart: unless-stopped7475 minio:76 image: minio/minio:latest77 ports:78 - "9001:9001"79 environment:80 MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}81 MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}82 volumes:83 - minio_data:/data84 command: server /data --console-address ":9001"85 networks:86 - plane-net87 restart: unless-stopped8889volumes:90 postgres_data:91 redis_data:92 minio_data:9394networks:95 plane-net:96 driver: bridge97EOF9899# 2. Create the .env file100cat > .env << 'EOF'101# PostgreSQL102POSTGRES_USER=plane103POSTGRES_PASSWORD=secure_postgres_password104POSTGRES_DB=plane105106# Plane107SECRET_KEY=$(openssl rand -hex 32)108109# MinIO110MINIO_ACCESS_KEY=plane111MINIO_SECRET_KEY=secure_minio_password112EOF113114# 3. Start the services115docker compose up -d116117# 4. View logs118docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/plane-project/run | bashTroubleshooting
- plane-api fails to connect to PostgreSQL: Ensure PostgreSQL health check passes before API startup and verify DATABASE_URL environment variable format
- File uploads return 403 errors: Check MinIO bucket creation and verify AWS_S3_BUCKET_NAME exists with proper access policies configured
- Background tasks not processing: Verify plane-worker container is running and Redis connection is established for Celery task queue
- Frontend shows API connection errors: Confirm NEXT_PUBLIC_API_BASE_URL matches your domain and plane-api is accessible on port 8000
- PostgreSQL connection pool exhausted: Increase max_connections in PostgreSQL config or implement connection pooling like PgBouncer for high-traffic instances
- MinIO console inaccessible: Verify MINIO_ROOT_USER and MINIO_ROOT_PASSWORD are set correctly and console is bound to port 9001
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
plane-webplane-apiplane-workerpostgresqlredisminio
Tags
#plane#project-management#jira-alternative#linear#issues
Category
Productivity & CollaborationAd Space
Shortcuts: C CopyF FavoriteD Download