VPS Setup Checklist

Use this checklist to rebuild the current 3plates VPS database and API validation path from a clean server.

Server prerequisites

VPS operating constraints

Repository setup

  1. Clone the repository onto the VPS.
  2. Check out the branch or commit you intend to run.
  3. Run pnpm install --frozen-lockfile.
  4. Copy .env.example to .env.
  5. Fill in .env with VPS values.

Required .env values for the database and API validation path:

Keep .env out of git.

Database setup

  1. Confirm docker-compose.yml publishes Postgres only on 127.0.0.1:${POSTGRES_PORT}.
  2. Confirm DATABASE_URL uses localhost or 127.0.0.1 with the same port.
  3. Start Postgres and apply migrations:
pnpm db:setup
  1. Confirm the container is healthy:
docker compose ps postgres || docker-compose ps postgres
  1. If setup fails, inspect database logs:
pnpm db:logs

API validation

Run the API in one shell:

pnpm dev:api

Run the database smoke test in another shell:

pnpm db:test

The smoke test must pass these checks:

Network and security checks

  1. Confirm Postgres is not listening publicly:
ss -tulpn | grep 5432

The expected bind address is 127.0.0.1:${POSTGRES_PORT}, not 0.0.0.0:${POSTGRES_PORT}.

  1. Confirm the API binds to loopback when it is running behind the VPS web proxy:
API_HOST=127.0.0.1
  1. Confirm the API health route from the VPS:
curl -fsS "http://127.0.0.1:${API_PORT}/health"
  1. Confirm the public firewall does not expose Postgres or the API port.
  2. Confirm SSH access still works before ending the maintenance session.

Public web proxy

The VPS uses Caddy as the public HTTP/S front door. Keep Caddy on public 80 and 443, and keep backend services on loopback-only ports.

Current production routing:

Current backend bind rules:

Validate the public routes after any proxy or deployment change:

curl -I https://forum.christitus.com
curl -I https://3spinningplates.com
curl -fsS https://api.3spinningplates.com/health

Validate the expected listener layout on the VPS:

ss -tulpn | grep -E ':(80|443|3000|8080|8443)\b'

Web deployment

Deploy the static Expo web build with:

pnpm deploy:web

The deploy command builds a clean production web export with EXPO_PUBLIC_API_URL=https://api.3spinningplates.com, creates a timestamped backup of /var/www/3plates, syncs the export to the VPS, and validates the public Progress and Workouts routes. If an SSH or rsync connection times out, it waits 30 seconds and retries the same operation up to 2 times before failing.

Ready criteria