Skip to content

Deploy TraceLLM To tracellm.in

This guide deploys the first production TraceLLM stack:

  • tracellm.in and www.tracellm.in: Vercel frontend
  • api.tracellm.in: TraceLLM backend on a Hostinger VPS
  • signoz.tracellm.in: private SigNoz UI on the same VPS
  • Caddy handles HTTPS
  • Docker Compose runs the backend and reverse proxy
  • SQLite persists in a Docker volume

DNS

Create these records before starting Caddy:

A      api       <VPS_PUBLIC_IP>
A      signoz    <VPS_PUBLIC_IP>

For the frontend, add the Vercel records for:

tracellm.in
www.tracellm.in

VPS Base Setup

Assume Ubuntu on Hostinger VPS.

sudo apt update
sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg git ufw
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER

Log out and back in, then verify:

docker --version
docker compose version

Use a current Docker Compose v2 release. The SigNoz production override uses Compose's !override merge tag so public ports are replaced with localhost-only bindings.

Firewall:

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
sudo ufw status

Do not publicly open ports 4319, 4318, or 8080.

Clone The Repo

mkdir -p ~/tracellm
cd ~/tracellm
git clone <your-github-repo-url> .

Prepare Production Env Files

Copy examples:

cp infra/production/server.env.example infra/production/server.env
cp infra/production/caddy.env.example infra/production/caddy.env

Edit infra/production/server.env:

NODE_ENV=production
TRACELLM_PUBLIC_API_URL=https://api.tracellm.in
TRACELLM_DB_PATH=/app/data/tracellm.sqlite
TRACELLM_AUTH_REQUIRED=true
TRACELLM_AUTH_COOKIE_SECURE=true
TRACELLM_OTEL_EXPORTER_OTLP_ENDPOINT=http://signoz-ingester:4318
TRACELLM_EXPORT_SECRET_KEY=<strong-stable-secret>

Generate a stable export secret:

openssl rand -hex 32

Keep TRACELLM_EXPORT_SECRET_KEY stable. If it changes, saved external export headers must be re-entered.

Generate the Caddy basic-auth hash:

docker run --rm caddy:2-alpine caddy hash-password --plaintext '<strong-password>'

Put the result in infra/production/caddy.env:

SIGNOZ_BASIC_AUTH_USER=admin
SIGNOZ_BASIC_AUTH_HASH=<hashed-password>

Do not commit server.env or caddy.env.

Start SigNoz

The generated SigNoz compose stack is committed under:

infra/signoz/pours/deployment/compose.yaml

Start SigNoz with the production override. The override binds SigNoz host ports to 127.0.0.1 so Caddy is the only public entry point.

docker compose \
  -f infra/signoz/pours/deployment/compose.yaml \
  -f infra/production/signoz-production.override.yml \
  up -d

Confirm the shared Docker network exists:

docker network inspect signoz-network

Start TraceLLM Backend And Caddy

Build and run:

docker compose -f infra/production/docker-compose.yml up -d --build

If you install Node and pnpm on the VPS, the equivalent helper commands are:

pnpm signoz:prod:up
pnpm prod:up

Check containers:

docker compose -f infra/production/docker-compose.yml ps
docker compose -f infra/production/docker-compose.yml logs -f tracellm-server

Verify public endpoints:

curl https://api.tracellm.in/health
curl https://api.tracellm.in/openapi.json

Open:

https://api.tracellm.in/api-docs
https://signoz.tracellm.in

SigNoz should ask for the Caddy basic-auth credentials.

Vercel Frontend

Vercel project settings:

Framework: Vite
Install command: pnpm install --frozen-lockfile
Build command: pnpm --filter @tracellm/web build
Output directory: apps/web/dist

Set Vercel env:

VITE_API_BASE_URL=https://api.tracellm.in
VITE_DOCS_BASE_URL=https://docs.tracellm.in
VITE_OPENAPI_URL=https://api.tracellm.in/api-docs
VITE_DEFAULT_OTLP_ENDPOINT=http://localhost:4318

Smoke Test

  1. Open https://tracellm.in.
  2. Create an account.
  3. Create a project API key.
  4. Run a real app locally:
TRACELLM_ENDPOINT=https://api.tracellm.in
TRACELLM_API_KEY=<project-api-key>
  1. Confirm traces appear in TraceLLM UI.
  2. Confirm backend platform telemetry appears in private SigNoz.
  3. Create an external OTLP destination from the Exports page and use Test trace.

Backup And Restore

The backend SQLite database lives in the tracellm-data Docker volume at:

/app/data/tracellm.sqlite

Create a backup:

mkdir -p ~/tracellm-backups
docker run --rm \
  -v tracellm-production_tracellm-data:/data:ro \
  -v ~/tracellm-backups:/backup \
  alpine sh -c 'cp /data/tracellm.sqlite /backup/tracellm-$(date +%Y%m%d-%H%M%S).sqlite'

Restore from a backup:

docker compose -f infra/production/docker-compose.yml down
docker run --rm \
  -v tracellm-production_tracellm-data:/data \
  -v ~/tracellm-backups:/backup \
  alpine sh -c 'cp /backup/<backup-file>.sqlite /data/tracellm.sqlite'
docker compose -f infra/production/docker-compose.yml up -d

Back up before changing production env, rotating secrets, or upgrading the backend.

Useful Commands

docker compose -f infra/production/docker-compose.yml logs -f
docker compose -f infra/production/docker-compose.yml restart tracellm-server
docker compose -f infra/production/docker-compose.yml pull
docker compose -f infra/production/docker-compose.yml up -d --build
docker compose -f infra/production/docker-compose.yml down