-
Notifications
You must be signed in to change notification settings - Fork 3.5k
docs: Add comprehensive Dokploy deployment guide for Plane #8605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: preview
Are you sure you want to change the base?
docs: Add comprehensive Dokploy deployment guide for Plane #8605
Conversation
Add comprehensive guide for deploying Plane on Dokploy with 3 approaches: - Docker Compose from Git repo (recommended) - AIO (All-In-One) pre-built image - Compose with pre-built images (no build required) https://claude.ai/code/session_01CTtRjowgPvFWBCESwRbHRx
|
|
📝 WalkthroughWalkthroughA new comprehensive deployment guide for Plane on Dokploy is introduced, documenting system architecture, three deployment options (Docker Compose via Dokploy, AIO image, and pre-built images), environment configuration, domain setup with Traefik, troubleshooting procedures, and version update workflows. Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@deployments/dokploy/DEPLOY.md`:
- Around line 132-133: Add a short guidance block under the SECRET_KEY and
LIVE_SERVER_SECRET_KEY entries explaining how to generate cryptographically
secure keys; mention using Django's get_random_secret_key (via a small python
one-liner) and an alternative using openssl rand -base64 50, and note that keys
should be at least 50 random characters and kept secret—update the DEPLOY.md
text around the SECRET_KEY and LIVE_SERVER_SECRET_KEY references to include this
guidance.
- Around line 493-494: Add explicit guidance beside the SECRET_KEY and
LIVE_SERVER_SECRET_KEY examples: explain they must be cryptographically secure
random strings (suggest length e.g., 50+ chars), show secure generation commands
(for example use openssl rand -base64 50 or Python: python -c "import secrets;
print(secrets.token_urlsafe(50))"), instruct readers to store them in
environment variables or a .env file and never commit them to source control,
and note that LIVE_SERVER_SECRET_KEY should be different from SECRET_KEY and
kept secret for production use; update the text around the SECRET_KEY and
LIVE_SERVER_SECRET_KEY examples accordingly.
- Line 211: Replace the floating tag `:latest` on the Plane image reference
`artifacts.plane.so/makeplane/plane-aio-community:latest` with a pinned tag
(e.g., `:stable` or a specific semver like `:v1.2.0`) and do the same for all
other image references in the pre-built compose section (the referenced
pre-built compose image list) so every container image uses a fixed version;
update deployment docs/examples to show the pinned tag and mention how to
choose/update the pinned version.
🧹 Nitpick comments (2)
deployments/dokploy/DEPLOY.md (2)
10-10: Optional: Fix table formatting for consistency.The table has spacing inconsistencies around the pipe separators. Consider adjusting for better formatting compliance.
✨ Proposed formatting fix
-|---------|--------|-------------| +| ------- | ------ | ----------- |Apply similar spacing to line 527 as well.
189-193: Add language identifier to code block.For better syntax highlighting and clarity, specify
bashas the language identifier.✨ Proposed fix
- ``` + ```bash RABBITMQ_DEFAULT_USER=planeApply similarly to code blocks at lines 200 and 514.
| - SECRET_KEY=<django-secret-key-ngẫu-nhiên-50-ký-tự> | ||
| - LIVE_SERVER_SECRET_KEY=<random-key> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add guidance for generating SECRET_KEY.
The documentation references SECRET_KEY and LIVE_SERVER_SECRET_KEY but doesn't provide instructions for generating cryptographically secure values. Django's SECRET_KEY should be a random string of at least 50 characters.
📝 Suggested addition
Consider adding a note like:
> **Tạo SECRET_KEY an toàn:**
> ```bash
> python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
> ```
> hoặc dùng: `openssl rand -base64 50`🤖 Prompt for AI Agents
In `@deployments/dokploy/DEPLOY.md` around lines 132 - 133, Add a short guidance
block under the SECRET_KEY and LIVE_SERVER_SECRET_KEY entries explaining how to
generate cryptographically secure keys; mention using Django's
get_random_secret_key (via a small python one-liner) and an alternative using
openssl rand -base64 50, and note that keys should be at least 50 random
characters and kept secret—update the DEPLOY.md text around the SECRET_KEY and
LIVE_SERVER_SECRET_KEY references to include this guidance.
|
|
||
| 1. Trong project, nhấn **+ Add Service** → **Docker** | ||
| 2. Chọn source: **Docker Image** | ||
| 3. Image: `artifacts.plane.so/makeplane/plane-aio-community:latest` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recommend version pinning instead of :latest tag.
Using :latest tag for production deployments can lead to unpredictable behavior, breaking changes, and difficult rollbacks. Consider specifying a stable version tag.
Example:
image: artifacts.plane.so/makeplane/plane-aio-community:stable
# or a specific version like:
image: artifacts.plane.so/makeplane/plane-aio-community:v1.2.0This same concern applies to all image references in the pre-built compose approach (lines 253-458).
🤖 Prompt for AI Agents
In `@deployments/dokploy/DEPLOY.md` at line 211, Replace the floating tag
`:latest` on the Plane image reference
`artifacts.plane.so/makeplane/plane-aio-community:latest` with a pinned tag
(e.g., `:stable` or a specific semver like `:v1.2.0`) and do the same for all
other image references in the pre-built compose section (the referenced
pre-built compose image list) so every container image uses a fixed version;
update deployment docs/examples to show the pinned tag and mention how to
choose/update the pinned version.
| image: artifacts.plane.so/makeplane/plane-frontend:latest | ||
| restart: always | ||
| depends_on: | ||
| - api | ||
|
|
||
| admin: | ||
| image: artifacts.plane.so/makeplane/plane-admin:latest | ||
| restart: always | ||
| depends_on: | ||
| - api | ||
|
|
||
| space: | ||
| image: artifacts.plane.so/makeplane/plane-space:latest | ||
| restart: always | ||
| depends_on: | ||
| - api | ||
|
|
||
| api: | ||
| image: artifacts.plane.so/makeplane/plane-backend:latest | ||
| restart: always | ||
| command: ./bin/docker-entrypoint-api.sh | ||
| environment: | ||
| - DEBUG=0 | ||
| - POSTGRES_USER=${POSTGRES_USER} | ||
| - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} | ||
| - POSTGRES_HOST=plane-db | ||
| - POSTGRES_DB=${POSTGRES_DB} | ||
| - POSTGRES_PORT=5432 | ||
| - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@plane-db:5432/${POSTGRES_DB} | ||
| - REDIS_HOST=plane-redis | ||
| - REDIS_PORT=6379 | ||
| - REDIS_URL=redis://plane-redis:6379/ | ||
| - RABBITMQ_HOST=plane-mq | ||
| - RABBITMQ_PORT=5672 | ||
| - RABBITMQ_USER=${RABBITMQ_USER} | ||
| - RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD} | ||
| - RABBITMQ_VHOST=${RABBITMQ_VHOST} | ||
| - SECRET_KEY=${SECRET_KEY} | ||
| - LIVE_SERVER_SECRET_KEY=${LIVE_SERVER_SECRET_KEY} | ||
| - AWS_REGION=${AWS_REGION} | ||
| - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} | ||
| - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} | ||
| - AWS_S3_ENDPOINT_URL=http://plane-minio:9000 | ||
| - AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME} | ||
| - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT} | ||
| - USE_MINIO=1 | ||
| - MINIO_ENDPOINT_SSL=0 | ||
| - WEB_URL=${WEB_URL} | ||
| - CORS_ALLOWED_ORIGINS=${WEB_URL} | ||
| - GUNICORN_WORKERS=2 | ||
| - API_KEY_RATE_LIMIT=${API_KEY_RATE_LIMIT} | ||
| depends_on: | ||
| - plane-db | ||
| - plane-redis | ||
|
|
||
| worker: | ||
| image: artifacts.plane.so/makeplane/plane-backend:latest | ||
| restart: always | ||
| command: ./bin/docker-entrypoint-worker.sh | ||
| environment: | ||
| - DEBUG=0 | ||
| - POSTGRES_USER=${POSTGRES_USER} | ||
| - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} | ||
| - POSTGRES_HOST=plane-db | ||
| - POSTGRES_DB=${POSTGRES_DB} | ||
| - POSTGRES_PORT=5432 | ||
| - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@plane-db:5432/${POSTGRES_DB} | ||
| - REDIS_HOST=plane-redis | ||
| - REDIS_PORT=6379 | ||
| - REDIS_URL=redis://plane-redis:6379/ | ||
| - RABBITMQ_HOST=plane-mq | ||
| - RABBITMQ_PORT=5672 | ||
| - RABBITMQ_USER=${RABBITMQ_USER} | ||
| - RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD} | ||
| - RABBITMQ_VHOST=${RABBITMQ_VHOST} | ||
| - SECRET_KEY=${SECRET_KEY} | ||
| - LIVE_SERVER_SECRET_KEY=${LIVE_SERVER_SECRET_KEY} | ||
| - AWS_REGION=${AWS_REGION} | ||
| - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} | ||
| - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} | ||
| - AWS_S3_ENDPOINT_URL=http://plane-minio:9000 | ||
| - AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME} | ||
| - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT} | ||
| - USE_MINIO=1 | ||
| - MINIO_ENDPOINT_SSL=0 | ||
| - WEB_URL=${WEB_URL} | ||
| - GUNICORN_WORKERS=2 | ||
| - API_KEY_RATE_LIMIT=${API_KEY_RATE_LIMIT} | ||
| depends_on: | ||
| - api | ||
| - plane-db | ||
| - plane-redis | ||
|
|
||
| beat-worker: | ||
| image: artifacts.plane.so/makeplane/plane-backend:latest | ||
| restart: always | ||
| command: ./bin/docker-entrypoint-beat.sh | ||
| environment: | ||
| - DEBUG=0 | ||
| - POSTGRES_USER=${POSTGRES_USER} | ||
| - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} | ||
| - POSTGRES_HOST=plane-db | ||
| - POSTGRES_DB=${POSTGRES_DB} | ||
| - POSTGRES_PORT=5432 | ||
| - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@plane-db:5432/${POSTGRES_DB} | ||
| - REDIS_HOST=plane-redis | ||
| - REDIS_PORT=6379 | ||
| - REDIS_URL=redis://plane-redis:6379/ | ||
| - RABBITMQ_HOST=plane-mq | ||
| - RABBITMQ_PORT=5672 | ||
| - RABBITMQ_USER=${RABBITMQ_USER} | ||
| - RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD} | ||
| - RABBITMQ_VHOST=${RABBITMQ_VHOST} | ||
| - SECRET_KEY=${SECRET_KEY} | ||
| - LIVE_SERVER_SECRET_KEY=${LIVE_SERVER_SECRET_KEY} | ||
| - AWS_REGION=${AWS_REGION} | ||
| - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} | ||
| - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} | ||
| - AWS_S3_ENDPOINT_URL=http://plane-minio:9000 | ||
| - AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME} | ||
| - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT} | ||
| - USE_MINIO=1 | ||
| - MINIO_ENDPOINT_SSL=0 | ||
| - WEB_URL=${WEB_URL} | ||
| - GUNICORN_WORKERS=2 | ||
| - API_KEY_RATE_LIMIT=${API_KEY_RATE_LIMIT} | ||
| depends_on: | ||
| - api | ||
| - plane-db | ||
| - plane-redis | ||
|
|
||
| migrator: | ||
| image: artifacts.plane.so/makeplane/plane-backend:latest | ||
| restart: "no" | ||
| command: ./bin/docker-entrypoint-migrator.sh | ||
| environment: | ||
| - DEBUG=0 | ||
| - POSTGRES_USER=${POSTGRES_USER} | ||
| - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} | ||
| - POSTGRES_HOST=plane-db | ||
| - POSTGRES_DB=${POSTGRES_DB} | ||
| - POSTGRES_PORT=5432 | ||
| - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@plane-db:5432/${POSTGRES_DB} | ||
| - REDIS_HOST=plane-redis | ||
| - REDIS_PORT=6379 | ||
| - REDIS_URL=redis://plane-redis:6379/ | ||
| - RABBITMQ_HOST=plane-mq | ||
| - RABBITMQ_PORT=5672 | ||
| - RABBITMQ_USER=${RABBITMQ_USER} | ||
| - RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD} | ||
| - RABBITMQ_VHOST=${RABBITMQ_VHOST} | ||
| - SECRET_KEY=${SECRET_KEY} | ||
| - AWS_REGION=${AWS_REGION} | ||
| - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} | ||
| - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} | ||
| - AWS_S3_ENDPOINT_URL=http://plane-minio:9000 | ||
| - AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME} | ||
| - USE_MINIO=1 | ||
| depends_on: | ||
| - plane-db | ||
| - plane-redis | ||
|
|
||
| live: | ||
| image: artifacts.plane.so/makeplane/plane-live:latest | ||
| restart: always | ||
|
|
||
| plane-db: | ||
| image: postgres:15.7-alpine | ||
| restart: always | ||
| command: postgres -c 'max_connections=1000' | ||
| volumes: | ||
| - pgdata:/var/lib/postgresql/data | ||
| environment: | ||
| POSTGRES_USER: ${POSTGRES_USER} | ||
| POSTGRES_DB: ${POSTGRES_DB} | ||
| POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} | ||
| PGDATA: /var/lib/postgresql/data | ||
|
|
||
| plane-redis: | ||
| image: valkey/valkey:7.2.11-alpine | ||
| restart: always | ||
| volumes: | ||
| - redisdata:/data | ||
|
|
||
| plane-mq: | ||
| image: rabbitmq:3.13.6-management-alpine | ||
| restart: always | ||
| environment: | ||
| RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER} | ||
| RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD} | ||
| RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST} | ||
| volumes: | ||
| - rabbitmq_data:/var/lib/rabbitmq | ||
|
|
||
| plane-minio: | ||
| image: minio/minio | ||
| restart: always | ||
| command: server /export --console-address ":9090" | ||
| volumes: | ||
| - uploads:/export | ||
| environment: | ||
| MINIO_ROOT_USER: ${AWS_ACCESS_KEY_ID} | ||
| MINIO_ROOT_PASSWORD: ${AWS_SECRET_ACCESS_KEY} | ||
|
|
||
| proxy: | ||
| image: artifacts.plane.so/makeplane/plane-proxy:latest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Version pinning recommended for all Docker images.
All services in this compose file use :latest tags, which is not recommended for production deployments. This creates several risks:
- Reproducibility: Deployments at different times may pull different versions
- Stability: Automatic updates may introduce breaking changes
- Rollback difficulty: Hard to revert to a known-good state
Consider adding a note recommending users replace :latest with specific version tags (e.g., v1.2.0 or stable) for all images:
plane-frontend:latestplane-admin:latestplane-space:latestplane-backend:latestplane-live:latestplane-proxy:latest
Infrastructure images (postgres, valkey, rabbitmq, minio) are already pinned, which is good practice.
| SECRET_KEY=<random-50-char-string> | ||
| LIVE_SERVER_SECRET_KEY=<random-string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SECRET_KEY generation guidance needed here too.
Same as the earlier comment on lines 132-133: provide users with instructions for generating cryptographically secure SECRET_KEY values. This is especially important since this section may be read independently of the Docker Compose approach.
🤖 Prompt for AI Agents
In `@deployments/dokploy/DEPLOY.md` around lines 493 - 494, Add explicit guidance
beside the SECRET_KEY and LIVE_SERVER_SECRET_KEY examples: explain they must be
cryptographically secure random strings (suggest length e.g., 50+ chars), show
secure generation commands (for example use openssl rand -base64 50 or Python:
python -c "import secrets; print(secrets.token_urlsafe(50))"), instruct readers
to store them in environment variables or a .env file and never commit them to
source control, and note that LIVE_SERVER_SECRET_KEY should be different from
SECRET_KEY and kept secret for production use; update the text around the
SECRET_KEY and LIVE_SERVER_SECRET_KEY examples accordingly.
Description
This PR adds a comprehensive Vietnamese deployment guide for deploying Plane on Dokploy. The guide covers three different deployment approaches with detailed step-by-step instructions, environment configuration, troubleshooting, and best practices.
The document (
deployments/dokploy/DEPLOY.md) includes:Architecture Overview - Complete service breakdown with ports and descriptions
Three Deployment Methods:
Detailed Configuration:
Operational Guidance:
Type of Change
Key Features
Test Scenarios
This is a documentation-only change. The guide has been structured to be:
References
https://claude.ai/code/session_01CTtRjowgPvFWBCESwRbHRx
Summary by CodeRabbit