[{"data":1,"prerenderedAt":161},["ShallowReactive",2],{"seo-verification":3,"blog-deploy-plane-self-hosted-on-a-linux-vps-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"id":7,"slug":8,"slugs":9,"title":12,"excerpt":13,"readTime":14,"views":15,"isPinned":16,"publishedAt":17,"category":18,"categories":23,"featuredImage":25,"bgImage":26,"posterImage":27,"relatedSolution":28,"intro":31,"sections":32,"ctaTitle":95,"ctaBody":96,"ctaButton":97,"ctaUrl":98,"relatedPosts":99},252,"deploy-plane-self-hosted-on-a-linux-vps",{"fr":10,"en":8,"ar":11},"deployer-plane-vps","نشر-plane-كاستضافة-ذاتية-على-خادم-vps-لينكس","Deploy Plane on a VPS: guide and post-2.3.7 regressions","Install Plane AIO on your VPS with Docker. Complete guide including known regressions in versions 2.3.7 to 2.4.1, the safe update procedure and troubleshooting.",12,0,false,"2026-08-13T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},2,"Automation","automatisation","bg-brand-action\u002F10 text-brand-action",[24],{"id":19,"name":20,"slug":21,"color":22,"icon":21},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdeployer-plane-vps-poster.svg",{"categorySlug":29,"appSlug":30},"collaboration-productivity","plane","Linear or Jira bills grow with every new seat, and storing your project tickets with a third-party vendor is not always acceptable. Plane is an AGPL-3.0 alternative with over 54,000 GitHub stars, a maintained Docker AIO image — `makeplane\u002Fplane-aio-community:stable` — and a single container that groups all internal services under supervisord. This guide shows you how to deploy it on a Linux VPS, secure it behind an HTTPS reverse proxy, and open it to your team.",[33,37,49,52,80,83,86,89,92],{"type":34,"title":35,"body":36},"h2","Why self-host Plane instead of paying per seat","The most common objection to the AIO image is that 'all-in-one supervisord' hides several internal services, making debugging harder when something goes wrong. In practice, the image groups five components — Django API, Celery worker, PostgreSQL, Redis and a file server — into a single supervisord process, which drastically simplifies startup. You do not need to compose a multi-container stack, synchronise migrations, or manage five separate Docker logs. When an error occurs, `docker logs \u003Ccontainer>` and `docker exec \u003Ccontainer> supervisorctl status` cover the vast majority of cases. Plane's official blog reports over 100,000 Docker deployments and over 44,000 Kubernetes deployments, which gives a measure of the image's operational maturity. The economic model is straightforward: you pay for the VPS, not the seat.",{"type":38,"title":39,"items":40},"ul","What you gain by hosting Plane on your own VPS",[41,42,43,44,45,46,47,48],"**Fixed cost, independent of team size** — a single VPS handles 5 to 50 users; pricing does not vary with seat count.","**Data under your control** — tickets, comments, files and team members stay in your own PostgreSQL database, on your own disk.","**AGPL-3.0 licence** — commercial use and self-hosting authorised without royalties; source code is auditable.","**Issues, cycles, modules, pages and inbox** — Plane covers task tracking, sprints, functional groupings, lightweight documentation and incoming triage, with no separate module.","**Stable, maintained image** — `makeplane\u002Fplane-aio-community:stable` is updated by the publisher and tested as a coherent unit before each release.","**Controlled updates** — you pull the new image when you choose to; no vendor can modify your production environment without your consent.","**Integration with your toolchain** — Plane exposes a documented REST API, usable to synchronise issues from a CI pipeline or from GitHub.","**Simple incident resolution** — one container, one log, one restart point; no multi-service stack to orchestrate manually.",{"type":34,"title":50,"body":51},"Minimum requirements for a stable deployment","The AIO image bundles several services in a single container: plan for **2 vCPU and 4 GB of RAM** as a minimum for team use. Below that threshold, the Celery worker and PostgreSQL share too little memory and indexing queries take several seconds. For teams of more than ten people or heavy use of pages and cycles, move to 8 GB. You need Docker installed on the host (version 20 or higher), a domain or subdomain pointing to your VPS, ports 80 and 443 open in your firewall, and around 10 GB of disk space for data volumes and Docker images. A TLS certificate is mandatory: Plane sets session cookies with `Secure`, making them unusable over plain HTTP.",{"type":53,"title":54,"steps":55},"steps","Deploy Plane AIO in eight steps",[56,59,62,65,68,71,74,77],{"title":57,"body":58},"Prepare the host and install Docker","On a freshly installed Debian or Ubuntu VPS, update packages, then install Docker via the official script or Docker's APT repositories:\n\n```bash\ncurl -fsSL https:\u002F\u002Fget.docker.com | sh\nsystemctl enable --now docker\n```\n\nVerify that Docker is running: `docker version`.",{"title":60,"body":61},"Create the working directory and environment file","Create a dedicated folder and prepare the minimal `.env` file:\n\n```bash\nmkdir -p \u002Fopt\u002Fplane && cd \u002Fopt\u002Fplane\n```\n\nThen create `\u002Fopt\u002Fplane\u002F.env` with the required variables:\n\n```bash\nSECRET_KEY=$(openssl rand -hex 32)\nWEB_URL=https:\u002F\u002Fplane.your-domain.com\nDATABASE_URL=postgresql:\u002F\u002Fplane:plane@127.0.0.1:5432\u002Fplane\n```\n\n`SECRET_KEY` must be a long random string; `WEB_URL` is the final public URL of your instance — this is the most critical value. If it is wrong, post-login redirects and asset loading will fail.",{"title":63,"body":64},"Start the AIO container","Launch Plane with the following command, specifying the path to your `.env` file and mounting a volume for persistent data:\n\n```bash\ndocker run -d \\\n  --name plane \\\n  --restart unless-stopped \\\n  --env-file \u002Fopt\u002Fplane\u002F.env \\\n  -v plane-data:\u002Fapp\u002Fplane-data \\\n  -p 127.0.0.1:8080:8080 \\\n  makeplane\u002Fplane-aio-community:stable\n```\n\nPort `8080` is exposed on loopback only: only the local reverse proxy can reach it. On first start, supervisord runs Django migrations; the interface is not available for one to two minutes.",{"title":66,"body":67},"Check internal service status","Before configuring the reverse proxy, verify that all sub-processes are active:\n\n```bash\ndocker exec plane supervisorctl status\n```\n\nYou should see the `api`, `worker`, `beat`, `web` and `nginx` services in `RUNNING` state. If any is in `FATAL`, read the logs with `docker logs plane` to identify the error.",{"title":69,"body":70},"Obtain a TLS certificate with Certbot","Install Certbot and the Nginx plugin, then request a certificate for your subdomain:\n\n```bash\napt install -y certbot python3-certbot-nginx\ncertbot certonly --nginx -d plane.your-domain.com\n```\n\nCertbot will place the certificate files in `\u002Fetc\u002Fletsencrypt\u002Flive\u002Fplane.your-domain.com\u002F`.",{"title":72,"body":73},"Configure Nginx as HTTPS reverse proxy","Create `\u002Fetc\u002Fnginx\u002Fsites-available\u002Fplane.conf`:\n\n```bash\nserver {\n    listen 80;\n    server_name plane.your-domain.com;\n    return 301 https:\u002F\u002F$host$request_uri;\n}\n\nserver {\n    listen 443 ssl;\n    server_name plane.your-domain.com;\n    ssl_certificate \u002Fetc\u002Fletsencrypt\u002Flive\u002Fplane.your-domain.com\u002Ffullchain.pem;\n    ssl_certificate_key \u002Fetc\u002Fletsencrypt\u002Flive\u002Fplane.your-domain.com\u002Fprivkey.pem;\n\n    location \u002F {\n        proxy_pass http:\u002F\u002F127.0.0.1:8080;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}\n```\n\nEnable the site and reload Nginx:\n\n```bash\nln -s \u002Fetc\u002Fnginx\u002Fsites-available\u002Fplane.conf \u002Fetc\u002Fnginx\u002Fsites-enabled\u002F\nnginx -t && systemctl reload nginx\n```",{"title":75,"body":76},"Create the first administrator account","Open `https:\u002F\u002Fplane.your-domain.com` in a browser. Plane shows a sign-up page on first access. Create an administrator account, then from the admin panel — accessible at `\u002Fgod-mode\u002F` — enable email sign-ups or configure a domain allowlist to restrict access to your organisation.",{"title":78,"body":79},"Invite the team and create the first project","In Plane, a project groups issues, cycles (sprints), modules (features) and pages (lightweight wiki). Create a project from the interface, then invite collaborators by email from the project settings. Invitations are sent by the mail server configured in your `.env` via `EMAIL_HOST` and `EMAIL_PORT`.",{"type":34,"title":81,"body":82},"Post-installation configuration: key environment variables","The most important variables after the initial startup are:\n\n— `WEB_URL` — the full public URL of the instance, without a trailing slash. An incorrect URL causes broken post-login redirects and assets that fail to load (images, CSS, JS). This is the most common error on first startup.\n\n— `SECRET_KEY` — secret string for signing Django sessions. Do not change it after the first startup without invalidating all active sessions.\n\n— `EMAIL_HOST`, `EMAIL_PORT`, `EMAIL_HOST_USER`, `EMAIL_HOST_PASSWORD` — required for invitations and notifications. Without these variables, email invitations are not sent.\n\n— `ENABLE_SIGNUP` — `1` to allow open sign-ups, `0` to disable them (only the admin can create accounts).\n\nAfter any change to the `.env` file, restart the container: `docker restart plane`.",{"type":84,"body":85},"tip","To update Plane, pull the new image then recreate the container while keeping the data volume:\n\n```bash\ndocker pull makeplane\u002Fplane-aio-community:stable\ndocker stop plane && docker rm plane\n```\n\nThen re-run the `docker run` command from step 3 with the same arguments. Database migrations are applied automatically on startup. If an update breaks the environment, roll back to the previous version by replacing `stable` with the exact tag of the previous image — `docker images` lists locally available images.",{"type":34,"title":87,"body":88},"Post-2.3.7 regressions and safe update procedure","Plane AIO versions 2.3.7 to 2.4.1 introduced several documented regressions. Loss of real-time notifications when upgrading the Python server between these versions. 500 errors on outgoing webhooks if the `webhook_trigger` column is missing in the PostgreSQL migration — symptom: `django.db.utils.ProgrammingError: column webhook_trigger does not exist` in the `plane-backend` container logs. Slowdown of filter queries on workspaces with more than 5,000 issues (index regression fixed in 2.4.2).\n\nBefore any update from a version earlier than 2.4.2, back up your PostgreSQL database: `docker compose exec -T db pg_dump -U plane plane > plane-backup-$(date +%F).sql`. Then update: `docker compose pull && docker compose up -d`. If the backend does not start after the update, force the migrations manually: `docker compose exec plane-backend python manage.py migrate --run-syncdb`. For instances on 2.3.6 or earlier, a direct update to 2.4.2+ is recommended to skip the defective intermediate versions.",{"type":34,"title":90,"body":91},"Troubleshooting: common errors and their fixes","**Broken redirects or assets not loading after login.** Typical symptom: the interface redirects to `http:\u002F\u002Flocalhost` or images and scripts fail to load. Cause: `WEB_URL` in the `.env` file does not match the actual public URL. Fix the value and restart the container.\n\n**Internal service startup failure.** Typical message in `docker logs plane`: `FATAL: api: exited too quickly`. Check `DATABASE_URL` — an incorrect connection URL or a non-existent database name prevents migrations from running and causes this kind of fatal exit.\n\n**The `\u002Fgod-mode\u002F` panel is inaccessible.** Access to the admin interface requires creating the first account via the main interface first, then signing in with those credentials. If you disabled sign-ups before creating the first account, temporarily restore `ENABLE_SIGNUP=1`, create the account, then set it back to `0`.\n\n**Invitation emails are not sent.** Check that `EMAIL_HOST` and `EMAIL_HOST_USER` are set in `.env` and that the SMTP port (often `587` with STARTTLS or `465` with SSL) is reachable from your VPS. Test with `docker exec plane python manage.py sendtestemail your@email.com`.\n\n**Degraded performance with many concurrent users.** If Celery workers struggle to process tasks, increase VPS RAM before adjusting internal concurrency. The AIO image is configured for standard team use; a very high-load configuration requires switching to a multi-container setup with dedicated resources per component.",{"type":34,"title":93,"body":94},"Keep control of your infrastructure without maintaining the OS layer","Self-hosting Plane shows that dependency on SaaS subscriptions is not inevitable: a stable image, a properly sized VPS and a TLS reverse proxy are enough for a professional-sized team. ServOrbit offers root VPS instances with dedicated IPv4, ready in minutes, with full `root` access to install Docker and manage your own tools. If you want to delegate the system layer — kernel updates, SSH hardening, backups — the VPS administration option lets you keep control of your data while outsourcing host maintenance. To go further in your DevOps practice, see the guide on automating your servers with Ansible and the Docker Compose guide for production.","Deploy Plane from the ServOrbit Marketplace","ServOrbit offers Plane pre-configured on VPS: PostgreSQL 16, Redis 7, RabbitMQ and MinIO set up automatically. Domain required, included in the recipe — first access in minutes, data under your control.","Deploy Plane","\u002Fmarketplace\u002Fcollaboration-productivity\u002Fplane",[100,115,132,146],{"id":101,"slug":102,"slugs":103,"title":106,"excerpt":107,"readTime":108,"views":109,"isPinned":16,"publishedAt":110,"category":111,"categories":112,"featuredImage":25,"bgImage":26,"posterImage":114,"relatedSolution":25},221,"huly-replace-linear-notion-and-slack-on-your-vps",{"fr":104,"en":102,"ar":105},"huly-gestion-projet-self-hosted-vps","huly-استبدل-linear-وnotion-وslack-على-خادمك-الافتراضي","Huly: replace Linear, Notion and Slack on your VPS","Deploy Huly on your VPS to centralise issues, docs and chat in one open-source tool — no per-seat subscription required.",3,1,"2026-08-04T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[113],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Fhuly-gestion-projet-self-hosted-vps-poster.svg",{"id":116,"slug":117,"slugs":118,"title":121,"excerpt":122,"readTime":123,"views":15,"isPinned":16,"publishedAt":124,"category":125,"categories":129,"featuredImage":25,"bgImage":26,"posterImage":131,"relatedSolution":25},229,"docker-compose-in-production-10-point-checklist",{"fr":119,"en":117,"ar":120},"docker-compose-production-checklist","docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط","Docker Compose in Production: 10-Point Checklist","10 Docker Compose settings to verify before any production deployment: restart, healthchecks, limits, secrets and logs.",14,"2026-08-06T00:00:00+00:00",{"id":108,"name":126,"slug":127,"color":128,"icon":127},"Deployment","deploiement","bg-success\u002F10 text-success",[130],{"id":108,"name":126,"slug":127,"color":128,"icon":127},"\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg",{"id":133,"slug":134,"slugs":135,"title":138,"excerpt":139,"readTime":140,"views":109,"isPinned":16,"publishedAt":141,"category":142,"categories":143,"featuredImage":25,"bgImage":26,"posterImage":145,"relatedSolution":25},236,"automating-vps-server-management-with-ansible",{"fr":136,"en":134,"ar":137},"ansible-automatiser-serveurs-vps","أتمتة-إدارة-خوادم-vps-باستخدام-ansible","Automating VPS Server Management with Ansible","Learn how to automate VPS fleet management with Ansible: inventory, playbooks, roles and Vault for a reproducible, auditable infrastructure.",11,"2026-08-08T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[144],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Fansible-automatiser-serveurs-vps-poster.svg",{"id":147,"slug":148,"slugs":149,"title":152,"excerpt":153,"readTime":154,"views":109,"isPinned":16,"publishedAt":155,"category":156,"categories":157,"featuredImage":25,"bgImage":26,"posterImage":159,"relatedSolution":160},270,"migrating-from-jira-data-center-to-openproject-or-plane-on-vps",{"fr":150,"en":148,"ar":151},"migrer-jira-openproject-plane-vps-2026","هجرة-jira-data-center-إلى-openproject-أو-plane-على-vps","Migrating from Jira Data Center to OpenProject or Plane on VPS","Jira Data Center stopped selling new licenses in March 2026 and goes read-only on March 28, 2029. Migrate to OpenProject or Plane on your VPS in a single working day.",13,"2026-08-16T00:00:00+00:00",{"id":108,"name":126,"slug":127,"color":128,"icon":127},[158],{"id":108,"name":126,"slug":127,"color":128,"icon":127},"\u002Fblog\u002Fcovers\u002Fmigrer-jira-openproject-plane-vps-2026-poster.svg",{"categorySlug":29,"appSlug":30},1787580994649]