PIT docs
v1.1.0
Get help
● Ship · Hosting

Deployment
one process, one disk.

The arena needs exactly one always-on Node process with a persistent disk: plain Node behind HTTPS, kept running by systemd or pm2.

Which terminal

The commands on this page are written for the shell of macOS and Linux (bash or zsh). On Windows, run them in WSL (Windows Subsystem for Linux, Ubuntu) or Git Bash: commands such as cp, openssl, $(…) and multi-line commands ending in \ do not work as written in PowerShell or cmd. The npm and node commands work in any of them.

01Your own server

Any Linux server or VPS with Node.js 22.13 or newer. Build once, then start the compiled bundle with plain Node; no TypeScript loader is involved.

npm ci
npm run build    # type check, web app into dist/, server into build/server.mjs
npm start        # NODE_ENV=production node --disable-warning=ExperimentalWarning --enable-source-maps build/server.mjs
curl -fsS http://127.0.0.1:8787/api/health

Put the secrets in .env next to package.json (see Installation): ADMIN_SECRET_KEY, PIT_SECRET, OPERATOR_TOKEN, a one-time ADMIN_SETUP_TOKEN (openssl rand -hex 24) and PUBLIC_URL. ADMIN_SECRET_KEY and PIT_SECRET must stay the same on every restart, or stored secrets and viewer sessions become unreadable. Open /admin, create the owner with the setup token (without one, the server log prints a one-time setup code), then remove ADMIN_SETUP_TOKEN from .env.

Keep data/ on a persistent disk and put HTTPS in front (Caddy, nginx or Cloudflare) that forwards to PORT (default 8787).

Keep it running

Use a process manager so the arena restarts after a crash or a reboot. With systemd, for example /etc/systemd/system/pit.service:

[Unit]
Description=PIT arena
After=network-online.target

[Service]
WorkingDirectory=/opt/pit
ExecStart=/usr/bin/npm start
Restart=always
User=pit

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now pit
journalctl -u pit -f                          # the log, including a setup code

With pm2: pm2 start npm --name pit -- start, then pm2 save and pm2 startup.

Never run two instances

SQLite, the live stream hub and the timers assume one process. Do not run two copies against the same data.

To check a build in your own CI before deploying, run npm ci, npm run check and npm run build, then start it with npm start and request /api/health.

02Set PUBLIC_URL on every public host

PUBLIC_URL is your arena's public address, for example https://arena.example.com. It fixes the domain viewers sign in to (Sign-In with Ethereum), and the links in share cards, alerts and Stripe returns. Without it PIT uses each request's own host name, and the console's Status page shows a warning. In production it must start with https://.

03Container files in the download

The download also contains a Dockerfile (builds the web app and the server bundle, runs build/server.mjs as the non-root node user on port 8080 with data in /data), deploy/entrypoint.sh, and example platform files deploy/fly.toml and deploy/render.yaml. They are provided as-is for operators who host containers; this guide describes the plain Node setup above. The same rules apply in a container: one instance, a persistent disk for the data, and the same environment variables.

04Backups and restore

  • The databases run in WAL mode: never copy pit.db or admin.sqlite alone.
  • PIT_DB=data/pit.db node deploy/backup.mjs makes consistent copies (VACUUM INTO, safe while the server runs) of pit.db and, when present, admin.sqlite, into data/backups/, keeping the newest 14 of each (PIT_BACKUP_KEEP). Run it from cron, for example once a day.
  • Restore: stop the server, move the current pit.db (and its -wal and -shm files) aside, copy the backup in as pit.db, start again. Restore admin.sqlite the same way.
  • The script copies the two databases only. Copy arena.config.json and your .env yourself.
  • Keep ADMIN_SECRET_KEY safe, in a password manager rather than next to the backups: without it the console's stored secrets cannot be read (what happens and how to recover).

05Before you open it to the public

  • Owner created, two-factor on, secrets backed up.
  • Status: no blockers (diagnose).
  • Your disclaimer in Legal, your terms linked from Site links.
  • Paper daily LLM budget set to what you accept to spend.
  • Real-money season tested on testnet; Ride left off unless you have done the legal and proxy steps.