Self-host Tracker
Tracker's core is AGPLv3 and runs anywhere you can run a Node.js app and a Postgres database. This page covers the three deployment shapes most teams use; pick the one that fits your stage.
1. Local — for evaluation and development
The fastest way to see Tracker working end-to-end on your own machine. Postgres in Docker, Tracker via npm run dev. About 5 minutes from clone to first sign-in.
Prerequisites
- Node.js 22.x.
- Docker Desktop or any Docker-compatible runtime.
- Git.
Steps
# 1. Clone
git clone https://gitlab.com/jalderman/tracker.git
cd tracker
# 2. Install dependencies
npm install
# 3. Start a Postgres container for local dev. Pick any password
# you like for the local DB.
docker run -d --name tracker-dev-db \
-e POSTGRES_USER=tracker \
-e POSTGRES_PASSWORD=CHANGEME \
-e POSTGRES_DB=tracker \
-p 5432:5432 \
postgres:16.13-alpine
# 4. Copy .env.example to .env and fill it in. The minimum:
# - DATABASE_URL with the password from step 3
# - AUTH_SECRET (generate one with the command in the file)
# - MAIL_DRIVER=none (skips email entirely; signups auto-verify)
cp .env.example .env
${EDITOR:-vi} .env
# 5. Apply the schema
npx prisma migrate deploy
# 6. Bootstrap a first admin user via CLI
npm run admin:create
# Prompts you for email + name; prints a generated password.
# Save it — you'll need it for first sign-in.
# 7. Start Tracker
npm run devOpen http://localhost:3000, sign in with the email + generated password from step 6. You're in.
Note on email: MAIL_DRIVER=none auto-verifies new signups and skips outbound email entirely — fine for evaluation. To wire SMTP for password reset and verification, see docs/ops/email-and-admin-bootstrap.md in the repo.
2. Production — Kubernetes via the bundled Ansible playbook
The path the Tracker maintainers use to deploy production instances. Ships an opinionated Ansible playbook that produces a repeatable Kubernetes deployment with sensible defaults.
Prerequisites
- A Kubernetes cluster (1.30+; tested against 1.35). A
ReadWriteOnceStorageClass withallowVolumeExpansion: truefor Postgres. - An image registry the cluster can pull from (Harbor, GHCR, ECR, Docker Hub).
- An ingress controller (ingress-nginx is the default).
- Ansible 2.16+ on your workstation.
- Optional: cert-manager (for public TLS), an SMTP relay (for password-reset / email verification), external DNS (for a real hostname).
Steps
- Read
docs/ops/infrastructure-requirements.mdfor the full sizing and dependency table. - Build a Tracker image in your registry (Dockerfile is at the repo root).
- Edit
ansible/group_vars/for your cluster — image registry, hostnames, Postgres backup mode (local | s3 | none), email settings. - Apply:
ansible-playbook deploy.yml. - Bootstrap the first admin user inside the cluster:
kubectl exec -n tracker deploy/tracker-app -- npm run admin:create.
Sizing: a 50-user instance fits comfortably in 1 vCPU / 1Gi memory per pod, with Postgres starting at 5Gi storage and growing on demand. Full per-component breakdown in the infrastructure-requirements doc.
3. Single-host (docker-compose, Render, Fly, etc.)
A docker-compose recipe for one-host self-host hasn't shipped yet — there's an open issue against ROADMAP.md tracking it. Until then, the local-dev steps above also work for a small production deployment if you swap npm run dev for npm run build && npm run start and run the Postgres container with persistent storage and a real password.
Platform-as-a-service deploys (Render, Fly, Railway, etc.) generally work — Tracker is a stock Next.js app — but aren't officially supported. The provider's standard Next.js + Postgres recipe applies.
After deploy
- Test the backup/restore drill before you put real data in. Runbook:
docs/ops/postgres-backup-restore.md. - If you plan to use commercial / overlay features later, see
docs/ops/licensing.mdfor how the license-token verification works (offline, Ed25519-signed; no phone-home). - Wire the MCP from your team's laptops: Claude Code + MCP.
Upgrades
Self-host tracks tagged releases (the SaaS instance runs main). To upgrade:
git fetch --tags git checkout v<release> npm install npx prisma migrate deploy # k8s: rebuild image + ansible-playbook deploy.yml --tags app # local: npm run build && npm run start
Migrations are designed to be safe to apply unattended; destructive schema changes go through a two-release deprecation (add → dual-write → remove). You can always upgrade one tag at a time.
Help
Everything operational lives under docs/ops/ in the repo. If something is missing or wrong, open an issue on the GitLab project and tag it docs.