[{"data":1,"prerenderedAt":210},["ShallowReactive",2],{"seo-verification":3,"blog-deploy-plane-self-hosted-on-a-linux-vps-ma-en":6,"promo-bar-likely":209},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-deploy-plane-self-hosted-on-a-linux-vps-ma-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":32,"intro":35,"sections":36,"ctaTitle":137,"ctaBody":138,"ctaButton":139,"ctaUrl":140,"relatedPosts":141},252,"deploy-plane-self-hosted-on-a-linux-vps",{"fr":12,"en":10,"ar":13,"es":14},"deployer-plane-vps","نشر-plane-كاستضافة-ذاتية-على-خادم-vps-لينكس","desplegar-plane-en-un-vps-linux","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.",13,1,false,"2026-08-13T00:00:00+00:00","2026-11-04T16:30:26+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},2,"Automation","automatisation","bg-brand-action\u002F10 text-brand-action",[28],{"id":23,"name":24,"slug":25,"color":26,"icon":25},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdeployer-plane-vps-poster.svg",{"categorySlug":33,"appSlug":34},"collaboration-productivity","plane","Your Linear or Jira bill grows with every new seat, and handing your project tickets to a third-party vendor is not always acceptable. Plane is an alternative under the AGPL-3.0 license, distributed as a self-hostable Community edition with an official Docker Compose installer. This guide shows how to deploy it on a Linux VPS, put it behind an HTTPS reverse proxy, understand what the AIO image really requires, and diagnose the failures that keep coming back in public issues: a missing MinIO image, a redirect loop on the profile page, and problems after a version upgrade.",[37,41,53,56,84,87,90,93,96,128,131,134],{"type":38,"title":39,"body":40},"h2","Why host Plane yourself instead of paying per seat","An issue tracker holds the most talkative part of a team: decisions, attachments, customer names, deadlines. Hosting it on your VPS moves the cost from the number of seats to the capacity of the server: you pay for resources, not for users. Plane has more than 61,000 stars on GitHub, its code is published under AGPL-3.0, and the vendor reports on its blog more than 100,000 Docker deployments and more than 44,000 Kubernetes deployments, which gives an idea of the installed base and of how much public field experience is available.\n\nThere is a trade-off to know before you start. The Community stack has several services: web interface, API, workers, real-time server, PostgreSQL database, Valkey cache, RabbitMQ message queue, S3-compatible object storage and a reverse proxy. The official installer orchestrates them with Docker Compose, but you remain responsible for backups, upgrades and the state of the object storage. The sections below detail each point, separating what the maintainers have confirmed from what only users have reported.",{"type":42,"title":43,"items":44},"ul","What you gain by hosting Plane on your own VPS",[45,46,47,48,49,50,51,52],"**A cost tied to the machine, not to seats** — the VPS price does not change with the number of accounts; what limits the team is memory and disk.","**Data under your control** — tickets, comments, files and members stay in your PostgreSQL database and your object storage, on your own disk.","**An AGPL-3.0 license** — the code can be audited; the license requires you to publish your changes if you expose a modified version to users.","**Issues, cycles, modules, pages and inbox** — task tracking, sprints, functional groupings, light documentation and incoming requests, with no separate module.","**An official installer** — the `setup.sh` script fetches a `docker-compose.yaml` and a `plane.env` published with the release, then handles start, stop, upgrade and backup.","**Upgrades at your own pace** — you pick the moment of the version upgrade, after a backup, and the script archives the old Compose file before replacing it.","**Storage you can move out** — the PostgreSQL database and S3 storage can live outside the VPS; Plane's documentation recommends it for production.","**A documented REST API** — useful to sync issues from a CI pipeline or from GitHub.",{"type":38,"title":54,"body":55},"Sized prerequisites for a stable deployment","Plane's documentation states 2 cores and 4 GB of RAM as a minimum, with 8 GB recommended in production. Plan for 2 vCPU and 8 GB of RAM if the team exceeds about ten people or makes heavy use of pages and cycles: PostgreSQL, RabbitMQ, the workers and the API share the same machine. Provide 20 GB of disk or more: Docker images and the database are small at first, it is the uploaded files that make the `uploads` volume grow.\n\nYou need a recent Docker with the Compose plugin (the script calls `docker compose`), a domain name or subdomain whose A record points to the VPS, and ports 80 and 443 open. A TLS certificate is essential in production: without HTTPS, passwords and sessions travel in clear text.",{"type":57,"title":58,"steps":59},"steps","Deploy Plane Community in eight steps",[60,63,66,69,72,75,78,81],{"title":61,"body":62},"Prepare the host and install Docker","On an up-to-date Debian or Ubuntu VPS, install Docker with the official script: `curl -fsSL https:\u002F\u002Fget.docker.com | sh`. Enable the service with `systemctl enable --now docker`, then check `docker version` and `docker compose version`. Open ports 80 and 443 in the firewall and restrict port 22 to your own addresses.",{"title":64,"body":65},"Download the official installer","Create a dedicated folder with `mkdir -p \u002Fopt\u002Fplane-selfhost && cd \u002Fopt\u002Fplane-selfhost`, then download the script from the latest release: `curl -fsSL -o setup.sh https:\u002F\u002Fgithub.com\u002Fmakeplane\u002Fplane\u002Freleases\u002Flatest\u002Fdownload\u002Fsetup.sh` and `chmod +x setup.sh`. The script works in the current folder: it creates the `plane-app` subfolder there.",{"title":67,"body":68},"Run the installation","Run `.\u002Fsetup.sh` as root or as a member of the docker group, then choose option 1 (Install). The script downloads `docker-compose.yaml` and `plane.env` into `plane-app\u002F` and, in recent versions, generates credentials for the bundled object storage. Leave the menu with option 8 before configuring: the documentation asks you to stop the stack before editing `plane.env`.",{"title":70,"body":71},"Fill in plane.env","Open `plane-app\u002Fplane.env` and set at least `APP_DOMAIN=plane.your-domain.com`, `WEB_URL=https:\u002F\u002Fplane.your-domain.com` and `CORS_ALLOWED_ORIGINS=https:\u002F\u002Fplane.your-domain.com`. To let Nginx hold ports 80 and 443, add `LISTEN_HTTP_PORT=8080`. Check that `SECRET_KEY` and `LIVE_SERVER_SECRET_KEY` hold unique values, never examples: `openssl rand -hex 32` produces one.",{"title":73,"body":74},"Start the stack and check the containers","Run `.\u002Fsetup.sh` again and choose option 2 (Start). The first start downloads the images, then the `migrator` container prepares the database and exits. Check the state with `docker compose -f plane-app\u002Fdocker-compose.yaml --env-file plane-app\u002Fplane.env ps`: all the other containers must be running. Option 6 of the menu shows the logs.",{"title":76,"body":77},"Get a TLS certificate with Certbot","Install Nginx and Certbot with `apt install -y nginx certbot python3-certbot-nginx`, then request the certificate: `certbot certonly --nginx -d plane.your-domain.com`. The files are placed in `\u002Fetc\u002Fletsencrypt\u002Flive\u002Fplane.your-domain.com\u002F`. The domain name must already point to the VPS.",{"title":79,"body":80},"Configure Nginx as an HTTPS reverse proxy","Create an Nginx site that listens on port 443 with the certificate you obtained and forwards everything to `http:\u002F\u002F127.0.0.1:8080`. Add the `Host`, `X-Real-IP`, `X-Forwarded-For` and `X-Forwarded-Proto` headers, as well as `Upgrade` and `Connection` for the real-time server WebSockets. A second `server` block redirects port 80 to HTTPS with `return 301 https:\u002F\u002F$host$request_uri;`. Enable the site, then `nginx -t && systemctl reload nginx`. Docker publishes port 8080 without going through UFW: close it from the outside with your provider's firewall.",{"title":82,"body":83},"Create the instance administrator and the team","Open `https:\u002F\u002Fplane.your-domain.com\u002Fgod-mode\u002F` to create the instance administrator account. Keep the trailing slash: one user reports that an address without it stayed stuck, a point the maintainers have not confirmed. Then open the application, create the workspace and the first project, and invite your collaborators.",{"type":38,"title":85,"body":86},"Post-installation configuration: the variables that matter","`WEB_URL` and `CORS_ALLOWED_ORIGINS`: the documentation asks you to set both to the address the browser actually uses. It is the first thing to check when behavior looks odd after login.\n\n`LISTEN_HTTP_PORT` and `LISTEN_HTTPS_PORT`: ports published by the bundled proxy, 80 and 443 by default. Change them if Nginx already holds the standard ports.\n\n`TRUSTED_PROXIES` and `NUM_PROXIES`: they determine the client IP address seen by the API, hence rate limiting. Behind your own reverse proxy, the installer README asks you to raise `NUM_PROXIES` by one per extra hop; left empty, the default behavior applies.\n\n`UNSPLASH_ACCESS_KEY`: optional, it feeds the cover image picker. Leave it empty if you do not use Unsplash; it is the first setting to re-read in case of a redirect loop, described below.\n\n`APP_RELEASE`: the release being followed, `stable` at first. The script resolves it to a version number at install time and on every upgrade.\n\nStop the stack with option 3 before editing `plane.env`, then restart with option 4.",{"type":88,"body":89},"tip","Before any upgrade, back up: option 7 of the script, plus a PostgreSQL dump with `docker compose -f plane-app\u002Fdocker-compose.yaml --env-file plane-app\u002Fplane.env exec -T plane-db pg_dump -U plane plane > plane-backup-$(date +%F).sql`. Then run option 5 (Upgrade): the script compares the installed release with the latest one, asks for confirmation, archives the old `docker-compose.yaml` in `plane-app\u002Farchive\u002F` and keeps a `plane.env.bak` copy. Re-read `plane.env` afterwards to spot new variables. Never upgrade with `docker compose down -v`: the `-v` option deletes the `uploads` volume, hence your attachments. The release notes of v1.4.3, published in October 2026, fix several access control flaws and ask self-hosted instances to upgrade.",{"type":38,"title":91,"body":92},"Object storage: the missing MinIO image and the fix in release 1.4.3","Symptom. On a fresh install or an upgrade, the image download fails on the storage service with the message `pull access denied for minio\u002Fminio, repository does not exist or may require 'docker login'`. The registry answers 401 rather than 404 to an anonymous client, so the message looks like a credentials problem: no `docker login` will change anything.\n\nConfirmed by the Plane team. The `minio` organization is gone from Docker Hub. PR #9829, merged in September 2026, notes it and switches the images to quay.io. The release notes of v1.4.3 then state that the bundled object storage uses the `pgsty\u002Fsilo` image, pinned to a release tag rather than `latest`. A repository contributor also stated in issue #9834, opened in September 2026, that the release had been updated with another image.\n\nReported by users only. The `quay.io\u002Fminio\u002Fminio` workaround worked for some, then several participants reported 401 errors on that registry from September 24, 2026. Those reports predate the release fix; do not apply them to a recent installation.\n\nWhat to do. On a fresh install, use the script from the latest release, then check with `grep -n 'image:' plane-app\u002Fdocker-compose.yaml` that no line mentions `minio\u002Fminio`. On an existing install that still mentions it, back up then run option 5 of the script. For production, PR #9829 itself recommends favoring external S3 storage over the bundled MinIO, whose community branch is frozen upstream according to its author: this is a direction from the Plane team, not a guarantee.",{"type":38,"title":94,"body":95},"After a version upgrade: what issue 8708 establishes, and what it does not","In March 2026, a user opened issue #8708 to describe a difficult installation. After moving from version 2.3.3 to 2.3.7, the permissions of uploaded files were broken; a volume declared with single quotes in a file of the AIO image was parsed incorrectly; and the first button offered to the administrator led to `\u002Fgod-mode` without a trailing slash, a page that stayed stuck.\n\nWhat the maintainers confirmed fits in one sentence: version 2.3.7 is not an official release, it was produced for a specific customer, and 2.4.0 fixes the problem. They did not confirm any of the three anomalies. The author replied that the quote defect persisted in the Dockerfile, and the issue was closed with no associated fix.\n\nKeep three rules. Install only releases published on the repository's Releases page, the latest being v1.4.3; do not pull an intermediate version. Back up before every version upgrade. After the upgrade, open an old attachment and a recent one: if opening fails, inspect the rights of the uploads volume with `docker volume inspect` before changing anything, keeping the backup within reach.",{"type":97,"title":98,"headers":99,"rows":103},"comparison","Compose installer or AIO image: what each one requires",[100,101,102],"Criterion","Compose installer (Community)","Community AIO image",[104,108,112,116,120,124],[105,106,107],"Services included","PostgreSQL, Valkey, RabbitMQ, object storage and proxy in the Compose stack","Applications, API, workers and Caddy proxy in a single container",[109,110,111],"External services","None required; recommended in production","PostgreSQL, Redis, RabbitMQ and S3 storage to provide yourself",[113,114,115],"Entry point","`.\u002Fsetup.sh` and the `plane.env` file","`docker run` with `DOMAIN_NAME`, `DATABASE_URL`, `REDIS_URL`, `AMQP_URL` and the S3 variables",[117,118,119],"Secrets","Values to check in `plane.env`","`SECRET_KEY` and `LIVE_SERVER_SECRET_KEY` required: the container stops if they are empty",[121,122,123],"Upgrade","Option 5 of the script, archiving the old Compose file","Pull the new image and recreate the container",[125,126,127],"Described use","Single server, external storage advised in production","Simple deployment and testing, according to its README",{"type":38,"title":129,"body":130},"Troubleshooting: redirect loop between \u002Fprofile\u002F and \u002F?next_path=\u002Fprofile\u002F","Symptom (issue #6694, opened in March 2025, still open on October 24, 2026). Behind a domain name, opening `https:\u002F\u002Fyour-domain.com\u002Fprofile\u002F` redirects to `https:\u002F\u002Fyour-domain.com\u002F?next_path=\u002Fprofile\u002F`, then the page loops. In the author's API log, almost every request answers 200, except one that comes back on each turn: `GET \u002Fapi\u002Funsplash\u002F?query= HTTP\u002F1.1\" 401`, followed by `Unauthorized: \u002Fapi\u002Funsplash\u002F`.\n\nEstablished. The author used Docker Compose with an external Nginx in front of Plane. The maintainers asked for the deployment mode, then whether a reverse proxy was in place, and replied in March 2025 that they were investigating. They have published no cause.\n\nReported. In July 2026, a participant found the same symptom: they had entered the Unsplash secret key instead of the access key in `UNSPLASH_ACCESS_KEY`. A PR proposed by an external contributor, #10108, still open on October 31, 2026, puts forward the explanation: the API returns Unsplash's 401 as is and the web application treats any 401 as an expired session, hence the redirect; it proposes answering 502 instead. This is a contributor's hypothesis, backed by a single testimony, not a finding by the maintainers, and it does not necessarily cover every redirect loop.\n\nWhat to do, in order. First, look for the line in the log: `docker compose -f plane-app\u002Fdocker-compose.yaml --env-file plane-app\u002Fplane.env logs api | grep unsplash`. If it does not appear, your loop has another cause: re-read `WEB_URL` and `CORS_ALLOWED_ORIGINS`. If it appears with a 401, re-read `UNSPLASH_ACCESS_KEY` in `plane.env` and in the Images section of the `\u002Fgod-mode\u002F` panel: you need the Access Key, not the secret key. If you do not use Unsplash, empty the value and restart the stack; according to the PR, a missing key returns an empty list with no error.",{"type":38,"title":132,"body":133},"Troubleshooting: other frequent errors and their fixes","**Redirects to `http:\u002F\u002Flocalhost` or resources that do not load.** `WEB_URL` and `CORS_ALLOWED_ORIGINS` do not match the public address. Fix both, then stop and restart the stack.\n\n**`pull access denied for minio\u002Fminio`.** See the object storage section: move to a recent release with option 5 of the script.\n\n**502 Bad Gateway returned by Nginx.** The bundled proxy is not listening on the targeted port. Compare `LISTEN_HTTP_PORT` in `plane.env` with the `proxy_pass` target, then test `curl -I http:\u002F\u002F127.0.0.1:8080` from the VPS. If the answer is slow, `docker compose -f plane-app\u002Fdocker-compose.yaml --env-file plane-app\u002Fplane.env ps` shows which container keeps restarting.\n\n**Invitation emails do not go out.** Fill in the SMTP server in the instance email settings, from `\u002Fgod-mode\u002F`, then send a test invitation. Also check that the host does not filter the outgoing SMTP port.\n\n**Slowness with many users.** Watch `docker stats`: if memory is saturated, increase RAM before any other tuning, then consider moving PostgreSQL and object storage off the VPS.",{"type":38,"title":135,"body":136},"Keep control of your infrastructure without maintaining the system layer","Hosting Plane yourself shows that depending on SaaS subscriptions is not inevitable: the official installer, a correctly sized VPS and a TLS reverse proxy are enough for a professional-size team. ServOrbit offers root VPS with a dedicated IPv4 address, ready in a few minutes, on which you have full `root` access to install Docker and run 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 production guide.","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","\u002Fapplications\u002Fcollaboration-productivity\u002Fplane",[142,158,178,194],{"id":143,"slug":144,"slugs":145,"title":149,"excerpt":150,"readTime":151,"views":23,"isPinned":19,"noindex":19,"publishedAt":152,"updatedAt":153,"category":154,"categories":155,"featuredImage":29,"bgImage":30,"posterImage":157,"relatedSolution":29},221,"huly-replace-linear-notion-and-slack-on-your-vps",{"fr":146,"en":144,"ar":147,"es":148},"huly-gestion-projet-self-hosted-vps","huly-استبدل-linear-وnotion-وslack-على-خادمك-الافتراضي","huly-gestion-proyectos-self-hosted-vps","Huly: replace Linear, Notion and Slack on your VPS","Deploy Huly on your VPS to centralise issues, docs and chat — system requirements, installation, MongoDB backup, troubleshooting and version updates.",7,"2026-08-04T00:00:00+00:00","2026-10-20T23:18:05+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[156],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fhuly-gestion-projet-self-hosted-vps-poster.svg",{"id":159,"slug":160,"slugs":161,"title":165,"excerpt":166,"readTime":167,"views":18,"isPinned":19,"noindex":19,"publishedAt":168,"updatedAt":169,"category":170,"categories":175,"featuredImage":29,"bgImage":30,"posterImage":177,"relatedSolution":29},229,"docker-compose-in-production-10-point-checklist",{"fr":162,"en":160,"ar":163,"es":164},"docker-compose-production-checklist","docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط","checklist-docker-compose-en-produccion","Docker Compose in Production: 10-Point Checklist","Docker Compose in production: 10 settings, health checks, secrets, rollback, troubleshooting and moving from docker-compose v1 to docker compose on Ubuntu 26.04.",12,"2026-08-06T00:00:00+00:00","2026-10-23T13:27:09+00:00",{"id":171,"name":172,"slug":173,"color":174,"icon":173},3,"Deployment","deploiement","bg-success\u002F10 text-success",[176],{"id":171,"name":172,"slug":173,"color":174,"icon":173},"\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg",{"id":179,"slug":180,"slugs":181,"title":185,"excerpt":186,"readTime":187,"views":23,"isPinned":19,"noindex":19,"publishedAt":188,"updatedAt":189,"category":190,"categories":191,"featuredImage":29,"bgImage":30,"posterImage":193,"relatedSolution":29},236,"automating-vps-server-management-with-ansible",{"fr":182,"en":180,"ar":183,"es":184},"ansible-automatiser-serveurs-vps","أتمتة-إدارة-خوادم-vps-باستخدام-ansible","automatizar-servidores-vps-con-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.",10,"2026-08-08T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[192],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fansible-automatiser-serveurs-vps-poster.svg",{"id":195,"slug":196,"slugs":197,"title":201,"excerpt":202,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":203,"updatedAt":21,"category":204,"categories":205,"featuredImage":29,"bgImage":30,"posterImage":207,"relatedSolution":208},270,"migrating-from-jira-data-center-to-openproject-or-plane-on-vps",{"fr":198,"en":196,"ar":199,"es":200},"migrer-jira-openproject-plane-vps-2026","هجرة-jira-data-center-إلى-openproject-أو-plane-على-vps","migrar-de-jira-a-openproject-o-plane-en-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.","2026-08-16T00:00:00+00:00",{"id":171,"name":172,"slug":173,"color":174,"icon":173},[206],{"id":171,"name":172,"slug":173,"color":174,"icon":173},"\u002Fblog\u002Fcovers\u002Fmigrer-jira-openproject-plane-vps-2026-poster.svg",{"categorySlug":33,"appSlug":34},true,1794270387226]