Deployment guide

Plane

Overview

This SecureAnyCloud image runs Plane v1.3.1, the open source project and issue tracking tool from makeplane, on Ubuntu 24.04 LTS. Plane is a self-hosted alternative to Jira and Linear. Teams organise work into workspaces and projects, then track it as issues (work items) with states, priorities, labels, assignees and estimates. Work items are grouped into cycles and modules and viewed as lists, kanban boards, calendars or spreadsheets.

The image ships the stock upstream Plane Community self-host stack, run with Docker Compose under a systemd service that starts it on boot. The stack bundles a PostgreSQL 15 database, a Valkey cache, a RabbitMQ queue and a MinIO object store for attachments. It also includes the Plane API, background workers, the web, space and admin front ends and a websocket service, all behind a built-in reverse proxy on port 80. Every image is pinned by tag or digest and baked into the image, so nothing is pulled on first boot.

What you get:

  • Plane v1.3.1 (stock upstream makeplane/plane-* images, pinned), run by systemd through Docker Compose
  • The Plane web console, REST API and websocket service behind a reverse proxy on :80
  • A bundled PostgreSQL 15, Valkey, RabbitMQ and MinIO, all on the same VM
  • A per-VM database password, storage keys, application secret key and queue password, generated on first boot
  • A first administrator user with a per-VM password, and a per-VM administrative REST API key, generated on first boot and recorded in a root-only file
  • A ready-to-use workspace and "Getting Started" project, seeded on first boot
  • docker.service, plane-configure.service, plane-firstboot.service and plane.service as systemd units, enabled and active
  • No baked-in administrator account or shipped data, and an 8 GiB swapfile so the stack runs comfortably on Standard_B2s
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point. Size up for heavier teams.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp for the web console. Also allow 443/tcp if you terminate TLS.

Plane serves plain HTTP on port 80. For production, front it with your own domain and TLS (see the production hardening step). After the VM comes up, the stack takes two to four minutes to finish its first-boot database migrations.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Plane by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).

Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:plane-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name plane \
  --image sac1647283583153:plane-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name plane --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the stack is running

The systemd units bring the whole Docker Compose stack up on boot. Confirm that the units are active and every container is running:

sudo systemctl is-active docker plane-configure plane-firstboot plane
sudo docker compose -f /opt/plane/docker-compose.yaml --env-file /opt/plane/plane.env ps --format '{{.Service}}\t{{.Status}}' | sort

The units should show active, and all twelve services should be up: api, worker, beat-worker, web, space, admin, live, proxy, plane-db, plane-redis, plane-mq and plane-minio.

Step 5 - Retrieve your per-VM credentials

On first boot, the appliance generates every secret uniquely for this VM. It writes the ones you need to a root-only file. Read the file with the secret values redacted:

sudo sed -E 's/^(PLANE_ADMIN_PASSWORD=).*/\1********/; s/^(PLANE_API_KEY=).*/\1********/' /root/plane-credentials.txt

The file holds your web console URL, the administrator email and password, the per-VM REST API key, and the seeded workspace slug and project id. Store the password and API key somewhere safe.

Step 6 - Confirm the API and the REST API key

Confirm that the Plane instance API and web app answer through the proxy on port 80:

curl -s http://127.0.0.1/api/instances/ | jq '{instance: .instance.instance_name, version: .instance.current_version, setup: .instance.is_setup_done}'
curl -s -o /dev/null -w "web app -> HTTP %{http_code}\n" http://127.0.0.1/

Next, test the per-VM REST API key end to end. A bogus key is rejected, the real key lists projects, and you can create a work item and read it back. The commands read the key, workspace slug and project id straight from the credentials file:

API_KEY=$(sudo grep '^PLANE_API_KEY=' /root/plane-credentials.txt | cut -d= -f2-)
SLUG=$(sudo grep '^PLANE_WORKSPACE_SLUG=' /root/plane-credentials.txt | cut -d= -f2-)
PROJECT=$(sudo grep '^PLANE_PROJECT_ID=' /root/plane-credentials.txt | cut -d= -f2-) BASE="http://127.0.0.1/api/v1/workspaces/$SLUG" curl -s -o /dev/null -w "bogus key -> HTTP %{http_code} (rejected)\n" -H "X-API-Key: bogus" "$BASE/projects/" curl -s -o /dev/null -w "per-VM key -> HTTP %{http_code}\n" -H "X-API-Key: $API_KEY" "$BASE/projects/"
ITEM=$(curl -s -X POST "$BASE/projects/$PROJECT/issues/" -H "X-API-Key: $API_KEY" -H 'Content-Type: application/json' -d '{"name":"Ship the release"}' | jq -r .id)
curl -s "$BASE/projects/$PROJECT/issues/$ITEM/" -H "X-API-Key: $API_KEY" | jq -r '"created + read back: " + .name'

Step 7 - Sign in to the web console

Open http://<vm-public-ip>/ in a browser. Sign in with the administrator email and password from your credentials file. The image has no default account, and the credentials are unique to this VM.

Step 8 - Open your workspace and project

After you sign in, Plane opens the seeded SecureAnyCloud workspace. Its Projects view lists the "Getting Started" project that first boot created for you. Create more projects from here, or open the seeded one to start working.

Step 9 - Work with issues on the board

Open a project's Work items to see its issues. Each work item carries a state, priority, assignees, labels and estimates.

Switch between list, board (kanban), calendar and spreadsheet layouts. Group work into cycles and modules.

Step 10 - Open a work item

Select a work item to open its detail panel. There you set its state, assignees, priority, dates, labels and description. You can also add sub-items, links and comments, and follow its full activity history.

Step 11 - Production hardening

For a production deployment, put Plane behind your own domain name and TLS. The appliance re-derives its public address on every boot, so the console works over the VM's public IP out of the box. Point a DNS record at the VM and serve HTTPS before you invite your team.

Plane's built-in proxy can terminate TLS for you. Edit /opt/plane/plane.env and set APP_DOMAIN, WEB_URL, CORS_ALLOWED_ORIGINS and SITE_ADDRESS. For automatic certificates, also set CERT_EMAIL. Then run sudo systemctl restart plane.

Keep the credentials file readable only by root. Restrict the network security group to the smallest set of source addresses that need access.

Source code and licensing

Plane is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). This image ships stock, unmodified upstream Plane Community Edition images, configured only through the environment file and systemd.

Under section 13 of the AGPL, the complete corresponding source for the version running on this appliance is the pinned upstream release, available at github.com/makeplane/plane (release v1.3.1).

The SecureAnyCloud charge covers packaging, security patching, image maintenance and support. It does not cover the Plane software itself, which remains free.

Maintenance

The Ubuntu base is patched at build time and ships with unattended security upgrades enabled. To update Plane itself, follow the upstream self-host upgrade process for the pinned release line.

The bundled PostgreSQL data lives on the VM's OS disk in a Docker volume. Before you upgrade, back it up with your normal disk-snapshot or pg_dump workflow.

Support

SecureAnyCloud maintains this image and provides 24/7 support. For help deploying or operating Plane on Azure, contact SecureAnyCloud support through the Azure Marketplace listing or at secureanycloud.com.

Deploy on Azure

Launch Plane on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure