Local Setup
This guide walks you through setting up Traceway on your local machine for development.
Prerequisites
- Go 1.26 (the
toolchainline inbackend/go.modis the exact version) - Node.js 22 and npm (
frontend/package.jsonpins22.xand the repo setsengine-strict) - Nothing else for the default build: both databases are SQLite files created on first start
- ClickHouse and PostgreSQL only when building with
-tags "transactional_pg telemetry_ch"
Database Setup
ClickHouse
-
Install ClickHouse following the official installation guide (opens in a new tab)
-
Start ClickHouse server
-
Create a database:
CREATE DATABASE traceway- The default user (
defaultwith empty password) works for local development
PostgreSQL
-
Install PostgreSQL following the official installation guide (opens in a new tab)
-
Create a user and database:
CREATE USER traceway WITH PASSWORD 'your_password';
CREATE DATABASE traceway OWNER traceway;Backend Setup
- Navigate to the backend folder:
cd backend- Create a
.envfile with your configuration:
JWT_SECRET=your-secret-key-minimum-32-characters-long
CLICKHOUSE_SERVER=localhost:9000
CLICKHOUSE_DATABASE=traceway
CLICKHOUSE_USERNAME=default
CLICKHOUSE_PASSWORD=
CLICKHOUSE_TLS=false
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DATABASE=traceway
POSTGRES_USERNAME=traceway
POSTGRES_PASSWORD=your_password
POSTGRES_SSLMODE=disableEnvironment Variables
| Variable | Description |
|---|---|
JWT_SECRET | Signs all authentication tokens (dashboard sessions and CLI/MCP device logins). Must be at least 32 characters; use a strong, unique secret and keep it stable. See CLI Authentication. |
CLICKHOUSE_SERVER | ClickHouse server address (host:port) |
CLICKHOUSE_DATABASE | ClickHouse database name |
CLICKHOUSE_USERNAME | ClickHouse username |
CLICKHOUSE_PASSWORD | ClickHouse password (empty for default) |
CLICKHOUSE_TLS | Enable TLS for ClickHouse connection |
POSTGRES_HOST | PostgreSQL server host |
POSTGRES_PORT | PostgreSQL server port |
POSTGRES_DATABASE | PostgreSQL database name |
POSTGRES_USERNAME | PostgreSQL username |
POSTGRES_PASSWORD | PostgreSQL password |
POSTGRES_SSLMODE | PostgreSQL SSL mode (disable, require, etc.) |
APP_BASE_URL | Public URL of your Traceway instance. Used for SDK connection instructions, email links, deep links in notifications, OAuth callback URLs, and the CLI/MCP OAuth issuer plus device-login verification URL. For local dev set this to http://localhost:5173 so OAuth callbacks land on the Vite dev server (which proxies /api back to the Go backend). |
GOOGLE_CLIENT_ID | Optional. Google OAuth client ID. Setting both Google variables enables the Continue with Google button. See the SSO guide. |
GOOGLE_CLIENT_SECRET | Optional. Google OAuth client secret. |
GITHUB_CLIENT_ID | Optional. GitHub OAuth App client ID. Setting both GitHub variables enables the Continue with GitHub button. See the SSO guide. |
GITHUB_CLIENT_SECRET | Optional. GitHub OAuth App client secret. |
OAUTH_SESSION_SECRET | Optional. Cookie signing secret for the OAuth round-trip. Falls back to JWT_SECRET when unset. |
SESSION_RECORDING_RETENTION_DAYS | Optional. Days to keep session recording files on disk under STORAGE_PATH/recordings/. Defaults to 30. Worker runs hourly and on startup. 0 disables; no effect when STORAGE_TYPE=s3. |
SQLITE_RETENTION_DAYS | Optional. Days to keep SQLite telemetry rows. Defaults to 30. 0 disables. Only applies when running with DB_TYPE=sqlite. |
DUCKDB_RETENTION_DAYS | Optional. Days to keep telemetry rows on the DuckDB backend (-tags telemetry_duckdb build). Defaults to 30, falling back to SQLITE_RETENTION_DAYS when unset. 0 disables. Pruning runs hourly, so expired rows can linger between runs. |
LOG_RECORDS_MAX_ROWS | Optional. Caps the log table via a cleanup task that runs every minute and keeps only the newest N rows. Not a hard limit: ingesting more than N rows within a minute exceeds the cap until the next run. Unset or 0 disables. Only applies when running with DB_TYPE=sqlite (SQLite or DuckDB telemetry). |
For local OAuth testing, register the provider's callback URL as http://localhost:5173/api/auth/callback/github (or .../google).
- Run the backend with the standalone build tags. Without them you get the embedded build, which ignores the ClickHouse and PostgreSQL variables above and opens a local SQLite database instead:
go run -tags "transactional_pg telemetry_ch" ./cmd/tracewayThe backend will start on port 8082 and automatically run database migrations.
Frontend Setup
- Navigate to the frontend folder:
cd frontend- Install dependencies:
npm install- Start the development server:
npm run devThe frontend will start on port 5173 and proxy API requests to the backend.
First-Time Registration
When running locally for the first time:
- Open your browser to http://localhost:5173 (opens in a new tab)
- The login page will automatically redirect you to registration (since no users exist)
- Create your user account with email and password
- After registration, create your first organization
- Create your first project to get a project token
The project token is used by the SDK to send telemetry data.
Connecting Your Application
Once you have a project token, point your application's OpenTelemetry exporter at the local instance. The endpoint is http://localhost:8082/api/otel and the token goes on the Authorization header:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8082/api/otel
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer your_project_token"
export OTEL_SERVICE_NAME=my-serviceSee OpenTelemetry for the full setup, including the per-framework guides.
Troubleshooting
Backend won't start
- Verify ClickHouse is running:
clickhouse-client --query "SELECT 1" - Verify PostgreSQL is running:
psql -U traceway -d traceway -c "SELECT 1" - Check that all environment variables are set correctly
Frontend can't connect to backend
- Ensure the backend is running on port 8082
- Check the browser console for CORS or network errors
- Verify the proxy configuration in
vite.config.ts
No data appearing in dashboard
- Verify your project token matches the one in the SDK configuration
- Check that your application is making requests
- Look at the backend logs for any ingestion errors