Install Plane on Coolify
This guide adds Plane as a workload on top of a VPS already bootstrapped with this repository.
Expected order before using this page:
- Bootstrap server baseline
- Complete Coolify onboarding
- Create internal service layer (
infra) - Install Plane
Scope:
- this repository bootstraps server baseline + Coolify
- this guide covers Plane deployment inside Coolify
- this guide uses a Community-only baseline (
v1.2.3 full-with-proxy)
Version baseline used here:
- Plane Community v1.2.3 (repository baseline)
- verify upstream before changing versions:
Important:
- this repository intentionally keeps a Community-only external-infra compose baseline
- the provided compose profile is adapted from official Plane
v1.2.3and intentionally disables bundled stateful services (plane-db,plane-redis,plane-mq, built-inplane-minio) to use shared infra services instead - official Plane
setup.shinstaller currently usesartifacts.plane.so/makeplane/*image references - this repository intentionally defaults to Docker Hub (
makeplane/*) for better cross-environment pull reliability and simpler fallback behavior - if your environment requires another registry mirror, set explicit
PLANE_*_IMAGEoverrides in Plane env values
Files provided in this repository
- Compose template:
templates/plane-coolify-compose.community.v1.2.3.full-with-proxy.yml
- Env template:
env/plane-coolify.env.example
- Env secret generator scripts:
scripts/generate-plane-secrets.shscripts/generate-plane-secrets.ps1
- Compose renderer script:
scripts/prepare-plane-compose.shscripts/prepare-plane-compose.ps1
- Incident-prevention notes:
Prerequisites
- Coolify onboarding is complete and the dashboard is reachable on final HTTPS domain:
- expected end-state:
https://<coolify-domain> http://<server-ip>:8000is only the temporary onboarding entrypoint
- expected end-state:
- local server validation passes in Coolify:
- in
Servers -> localhost,Validate Server/Check Connectionreturns success - this specifically means Coolify can SSH from container context to the host with the configured localhost server settings (
host,port,user, private key) - no SSH/sudo errors (
Server is not reachable,Connection refused,sudo password is required)
- in
- shared services required by this Plane profile are running and reachable from the same Docker network:
postgres-appsvalkey-appsrabbitmq-planeseaweedfs-plane- if you changed infra container-name overrides, use your custom names instead
- ensure infra setup was executed from this repo scripts so SeaweedFS S3 bucket (
PLANE_S3_BUCKET, defaultplane-uploads) is created before Plane deploy - external Docker network
infraexists, and shared services are attached to it (Plane services are attached during Step 5)
Before proceeding, if infra is missing, create it using:
- Create Infra Network
- recommended path: generate infra env locally, copy it to VPS, then run server-side
setup-infra.sh --env-file ...
Local ownership: infra secrets vs Plane secrets
Recommended source of truth:
- infra secrets are generated locally in
bootstrap-artifacts/production-infra.env - Plane env is generated locally in
bootstrap-artifacts/plane.env - Plane env imports infra-dependent values from local infra env during generation
Infra -> Plane synced keys (automatic in generate-plane-secrets.*):
POSTGRES_APPS_USER->POSTGRES_USERPOSTGRES_APPS_PASSWORD->POSTGRES_PASSWORDPOSTGRES_PLANE_DB->POSTGRES_DBPOSTGRES_APPS_CONTAINER_NAME->POSTGRES_HOSTAPPS_VALKEY_PASSWORD->REDIS_PASSWORDVALKEY_APPS_CONTAINER_NAME->REDIS_HOSTPLANE_RABBITMQ_USER->RABBITMQ_DEFAULT_USERPLANE_RABBITMQ_PASSWORD->RABBITMQ_DEFAULT_PASSPLANE_RABBITMQ_VHOST->RABBITMQ_VHOSTandRABBITMQ_DEFAULT_VHOSTRABBITMQ_PLANE_CONTAINER_NAME->RABBITMQ_HOSTPLANE_S3_ACCESS_KEY->AWS_ACCESS_KEY_IDPLANE_S3_SECRET_KEY->AWS_SECRET_ACCESS_KEYPLANE_S3_BUCKET->AWS_S3_BUCKET_NAMEandBUCKET_NAMESEAWEEDFS_PLANE_CONTAINER_NAME->AWS_S3_ENDPOINT_URL(http://<container>:8333)
Dependent URLs are regenerated when needed:
DATABASE_URLREDIS_URLAMQP_URL
1) Generate Plane env secrets and passwords locally
Bash:
bash scripts/generate-plane-secrets.sh
PowerShell:
pwsh -File scripts/generate-plane-secrets.ps1
Default output:
bootstrap-artifacts/plane.env
Default infra source:
bootstrap-artifacts/production-infra.env
If infra env does not exist yet:
generate-plane-secrets.*still succeeds and creates/updatesbootstrap-artifacts/plane.env- script warns that infra sync is skipped (missing infra env file)
- local Plane secrets/passwords are generated, and dependent URLs are built from current Plane values
- after infra env is created, rerun
generate-plane-secrets.*so infra-derived values are synchronized
Rerun commands after infra env is ready:
Linux/macOS (Bash):
bash scripts/generate-plane-secrets.sh
Windows (PowerShell):
pwsh -File scripts/generate-plane-secrets.ps1
Optional explicit infra source path:
- Bash:
--infra-env-file path/to/production-infra.env - PowerShell:
-InfraEnvFile path/to/production-infra.env
Disable infra sync only for special cases:
- Bash:
--no-infra-sync - PowerShell:
-NoInfraSync
Optional force rotation:
- passwords only:
--force-passwords/-ForcePasswords - secrets only:
--force-secrets/-ForceSecrets - all generated values:
--force-all/-ForceAll
Optional custom path:
- Bash:
--env-file path/to/plane.env - PowerShell:
-EnvFile path/to/plane.env
Notes:
- generated values are non-destructive by default
- infra-sourced Plane credentials are kept as infra values (they are not rotated by Plane generator force flags)
- dependent URLs are synchronized when needed:
DATABASE_URLREDIS_URLAMQP_URL
2) Create Plane resource in Coolify
Optional: render compose with values from bootstrap-artifacts/plane.env first:
bash scripts/prepare-plane-compose.sh
pwsh -File scripts/prepare-plane-compose.ps1
Default rendered output:
bootstrap-artifacts/plane-coolify-compose.community.v1.2.3.full-with-proxy.yml
Rendered behavior:
- output keeps
${VAR}expressions so Coolify detects environment variables in UI - defaults are rewritten from
plane.env(for example${SECRET_KEY:-<value-from-plane.env>})
- Open
Projects -> <project> -> <environment>. - Create a new
Docker Composeresource. - Use a clear name (for example
planeorprojects). - Paste the full content of one of:
- rendered file:
bootstrap-artifacts/plane-coolify-compose.community.v1.2.3.full-with-proxy.yml(recommended after running renderer) - raw template:
templates/plane-coolify-compose.community.v1.2.3.full-with-proxy.yml
- rendered file:
- Save compose.
3) Configure Plane environment values
- Open env variables for the Plane resource.
- Start from
bootstrap-artifacts/plane.env(generated in Step 1), or fromenv/plane-coolify.env.example. - Replace all remaining
CHANGE_ME_*values before first deploy. - Save env values.
Critical required values before deploy:
SECRET_KEYDATABASE_URLREDIS_URLRABBITMQ_DEFAULT_PASSAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_S3_ENDPOINT_URL(internal SeaweedFS endpoint, e.g.http://seaweedfs-plane:8333)SILO_HMAC_SECRET_KEYLIVE_SERVER_SECRET_KEY
4) Configure public domain routing
Use Plane proxy service as public entrypoint.
Recommended mapping:
https://projects.example.com-> serviceproxy-> port80
Keep these services internal-only (no direct public domain):
web,api,space,admin,live,worker,beat-worker,migrator
5) Attach Plane services to infra network
Only Plane services that must reach shared dependencies should join infra:
plane-minioapiworkerbeat-workerlivemigrator
Keep these services on the stack-local default network only:
proxywebspaceadmin
Reason:
proxyis the public ingress target and should not need direct access to shared infra services- attaching the public entrypoint to extra shared networks can make ingress routing less deterministic on multi-network Coolify installs
If UI exposes a service-level predefined network setting, do not use it to attach the entire Plane resource to infra unless your Coolify build supports per-container scoping. Prefer the compose-defined selective attachment from the template.
If UI does not expose it, keep compose network block as provided:
networks:
infra:
external: true
name: infra
The recommended template already declares infra only on the services that need shared dependencies.
6) Deploy and verify
Deploy resource in Coolify, then verify:
docker ps --format 'table \t' | grep -E 'proxy|web|api|worker|plane-minio'
Health checks to run:
curl -sSI https://projects.example.com/
curl -sSI https://projects.example.com/api/instances/
curl -i -X OPTIONS https://projects.example.com/auth/email-check/
7) Upgrade and rollback (safe path)
Recommended approach:
- Keep compose unchanged.
- Change only version env values.
- Redeploy.
- Rollback by restoring previous version values and redeploy.
Primary switch:
PLANE_APP_VERSION
Optional explicit image pins (set all together when used):
PLANE_PROXY_IMAGEPLANE_WEB_IMAGEPLANE_BACKEND_IMAGEPLANE_SPACE_IMAGEPLANE_ADMIN_IMAGEPLANE_LIVE_IMAGE
Before upgrade:
- take verified DB backup
- keep previous env snapshot and image tag snapshot
Community upgrade policy:
- Keep the compose file unchanged.
- Change only
PLANE_APP_VERSION(and optional explicitPLANE_*_IMAGEpins). - Redeploy once.
- If anything fails, rollback by restoring previous version variables and redeploy.
8) Common failure signals
Mixed Contenton uploads502on/plane-uploads504on root/API paths- public routing to wrong service (not
proxy)
Use:
Back to Docs Home