Skip to main content

Installation

This section guides you through setting up TestPlanIt for local development.

Choose the method that best suits your environment:

  • Manual Setup: Recommended if you prefer to manage Node.js, pnpm, and PostgreSQL directly on your host machine.
  • Docker Setup (Development): Recommended for a simpler, containerized setup where Docker manages the application and database environment.
  • Kubernetes (Helm): Deploy a self-hosted production instance to a Kubernetes cluster (EKS, GKE, AKS, or k3s) with the official Helm chart.

After completing a setup guide, proceed to the Getting Started guide for a quick tour of the application.

Upgrading​

TestPlanIt applies database schema changes with versioned migrations (zenstack migrate deploy), which never drop data. Docker deployments apply pending migrations automatically when the container starts; source installs apply them with pnpm db:deploy.

A routine upgrade with Docker:

docker pull ghcr.io/testplanit/testplanit-selfhost:latest
docker compose up -d # pending migrations apply on startup
Which image to pull

Self-hosted deployments use testplanit-selfhost. It is domain-agnostic, so one image serves any hostname, and it is published for both linux/amd64 and linux/arm64. The testplanit image is built for the hosted service, bakes its domain in at build time, and is arm64 only — pulling it on an x86 host fails with no matching manifest for linux/amd64.

A routine upgrade from source:

git pull origin main
pnpm install
pnpm generate
pnpm db:deploy # apply pending migrations
pnpm build

Upgrading from a pre-1.0 release​

Databases created by a 0.x release predate versioned migrations and have no migration history, so the first v1.0 startup would try to re-create the baseline schema and fail. Back up your database, then record the baseline as already applied — once, before the first v1.0 start:

# From a source checkout:
cd testplanit
npx zenstack migrate resolve --applied 20260625193632_init --schema schema.zmodel
# Or with the official image (Compose users: substitute
# `docker compose run --rm --no-deps --entrypoint "" prod` for `docker run --rm --entrypoint ""`):
docker run --rm --entrypoint "" \
-e DATABASE_URL="postgresql://user:password@host:5432/testplanit" \
ghcr.io/testplanit/testplanit-selfhost:latest \
npx zenstack migrate resolve --applied 20260625193632_init --schema schema.zmodel

The baseline matches the schema your database already has, so it is recorded without being run; the next startup applies the remaining migrations normally. A few notes:

  • Use a direct database connection — migrations need a real session, not a transaction-mode pooler such as pgbouncer.
  • Starting v1.0 against a pre-1.0 database without the baseline is safe: the startup migrate deploy fails and the app won't start, but nothing is changed. Run the baseline and start again.
  • If you followed the 1.0 beta channel, you already did this step — nothing further is needed. Fresh installs need nothing special.

See the migrations README for details.