Environment Variables Reference

Complete reference for all environment variables used in Temps.


Server Configuration

These environment variables configure the Temps server itself:

VariableCLI FlagDefaultDescription
TEMPS_ADDRESS--address127.0.0.1:3000HTTP server address and port
TEMPS_TLS_ADDRESS--tls-address(optional)HTTPS server address and port
TEMPS_DATA_DIR--data-dir~/.tempsData directory for keys and configuration
TEMPS_LOG_LEVEL--log-levelinfoLog level: trace, debug, info, warn, error
TEMPS_CONSOLE_ADDRESS--console-address(optional)Console listener (public ingest + admin if no split)

Admin Listener (optional)

When the admin listener is configured, admin/management routes bind to a separate address while TEMPS_CONSOLE_ADDRESS only serves public ingest endpoints (analytics events, error tracking ingest, AI gateway, worker route sync, email tracking pixels). See the admin listener guide for the full route classification and deployment patterns.

VariableCLI FlagDefaultDescription
TEMPS_CONSOLE_ADMIN_ADDRESS--console-admin-address(optional)Dedicated bind for admin/management routes. Unset = single listener mode (backwards-compat)
TEMPS_ADMIN_ALLOWED_IPS(optional)Comma-separated IPs/CIDRs allowed to reach the admin listener (e.g. 10.0.0.0/8,127.0.0.1)
TEMPS_ADMIN_ALLOWED_HOSTS(optional)Comma-separated Host header values allowed on the admin listener
TEMPS_ADMIN_TRUST_FORWARDED_FORfalseHonor X-Forwarded-For for the IP gate — only from loopback peers (anti-spoof)

Example

# Single listener (backwards-compatible default)
export TEMPS_ADDRESS=0.0.0.0:8080
export TEMPS_TLS_ADDRESS=0.0.0.0:8443
export TEMPS_LOG_LEVEL=debug
export TEMPS_DATA_DIR=/var/lib/temps

# Two listeners with admin on loopback + IP allowlist
export TEMPS_CONSOLE_ADDRESS=0.0.0.0:8080
export TEMPS_CONSOLE_ADMIN_ADDRESS=127.0.0.1:8081
export TEMPS_ADMIN_ALLOWED_IPS=127.0.0.1/32,10.0.0.0/8
export TEMPS_ADMIN_ALLOWED_HOSTS=admin.temps.example.com

Database Configuration

VariableCLI FlagDefaultDescription
TEMPS_DATABASE_URL--database-url(required)PostgreSQL connection string

Database URL Format

postgresql://[user[:password]@][host][:port][/database][?param1=value1&...]

Example

export TEMPS_DATABASE_URL=postgresql://temps:password@localhost:5432/temps

Connection Pool Tuning

Control the PostgreSQL connection pool size and timeouts:

VariableDefaultDescription
TEMPS_DB_MAX_CONNECTIONS100Maximum connections in the pool
TEMPS_DB_MIN_CONNECTIONS5Minimum idle connections kept open
TEMPS_DB_ACQUIRE_TIMEOUT30Seconds to wait for a connection
TEMPS_DB_IDLE_TIMEOUT600Seconds before idle connections are closed

For small servers (2GB RAM), reduce TEMPS_DB_MAX_CONNECTIONS to 20-30. If you see slow_acquire_threshold warnings in logs, it means the pool is saturated — either increase the max or investigate long-running queries.

# Example: tuning for a small VPS
export TEMPS_DB_MAX_CONNECTIONS=30
export TEMPS_DB_MIN_CONNECTIONS=2
export TEMPS_DB_IDLE_TIMEOUT=300

Data Directory

Temps stores sensitive data in the data directory (~/.temps by default):

~/.temps/
├── encryption_key    # AES-256 encryption key (auto-generated)
└── auth_secret       # Session authentication secret (auto-generated)

ClickHouse Analytics Backend

By default Temps is a single binary and serves analytics reads from PostgreSQL/TimescaleDB — no extra config required. For large analytics workloads you can route analytics reads to a ClickHouse cluster instead, at runtime, by setting four environment variables on temps serve. There is no rebuild and no cargo feature flag: the ClickHouse backend and its fan-out worker are always compiled in, and stay dormant until you configure them.

VariableCLI FlagDefaultDescription
TEMPS_CLICKHOUSE_URL(optional)ClickHouse HTTP endpoint URL
TEMPS_CLICKHOUSE_DATABASE(optional)ClickHouse database name
TEMPS_CLICKHOUSE_USER(optional)ClickHouse username
TEMPS_CLICKHOUSE_PASSWORD(optional)ClickHouse password

Fail-closed activation

The ClickHouse backend activates only when all four variables are present and non-empty. Partial or empty configuration is treated as off, and Temps stays in single-binary PostgreSQL/TimescaleDB-only mode (the default). A variable that is set but empty counts as unset, so a half-configured operator never silently loses analytics.

# Enable the ClickHouse analytics read backend
export TEMPS_CLICKHOUSE_URL=http://clickhouse:8123
export TEMPS_CLICKHOUSE_DATABASE=temps_analytics
export TEMPS_CLICKHOUSE_USER=temps
export TEMPS_CLICKHOUSE_PASSWORD=your-clickhouse-password

When all four are set, the analytics-events plugin:

  1. Applies the embedded ClickHouse schema migrations — events, events_5m_mv, and sessions, tracked in a _temps_ch_migrations table.
  2. Spawns the ChFanoutWorker on the tokio runtime.
  3. Swaps the read-side analytics events service to ClickHouseEventsBackend.

Migrations and the worker run on background tasks so plugin init does not block on remote calls. If migrations fail, queries surface the error per-call rather than crashing startup.

PostgreSQL stays the system of record

PostgreSQL/TimescaleDB remains the source of truth. record_event writes the event to PostgreSQL synchronously, then enqueues the event id into an events_ch_outbox table (INSERT ... ON CONFLICT (event_id) DO NOTHING). The worker drains that outbox asynchronously, claiming batches with FOR UPDATE SKIP LOCKED and inserting into ClickHouse.

This makes ingestion resilient:

  • The outbox enqueue is best-effort. If it fails, the event is still recorded in PostgreSQL (the failure is logged at debug); that single event simply won't replicate to ClickHouse.
  • A ClickHouse outage never blocks ingestion. The write path never waits on ClickHouse — rows queue in the outbox and are retried on later poll cycles.
  • Retries are safe. The ClickHouse events table uses ReplacingMergeTree(_version) and dedupes over its sort key (with event_id as the most granular component), so re-delivering the same event collapses to one row.

The worker also runs an hourly retention sweep that deletes delivered outbox rows older than 7 days, and a 5-minute dead-letter scan that warn-logs the count of rows that hit the retry ceiling (attempts >= max_attempts, default 10) without deleting them.

Behavior differences from the PostgreSQL backend

Only the events read path has a ClickHouse backend. A few behaviors differ by design:

  • Unique counts are approximate. The ClickHouse backend uses uniq() (HyperLogLog), accurate to within ~1% at scale, instead of the exact COUNT(DISTINCT) used by PostgreSQL.
  • The self-referral filter is PostgreSQL-only. The referrer-hostname self-referral filter checks the project_custom_domains table, which is not replicated to ClickHouse.
  • Visitor/session queries stay on PostgreSQL. The separate visitor/session analytics path always uses PostgreSQL — only the events read path can be backed by ClickHouse.

Geolocation (country/region/city) is denormalized onto each ClickHouse event row at fan-out time, so breakdowns and timelines group on plain ClickHouse columns without a cross-database join.


Application Environment Variables

These are environment variables you configure for your deployed applications:

Setting Environment Variables

Environment variables can be set per project and environment:

Via Dashboard:

  1. Navigate to Project → Environment → Settings
  2. Go to Environment Variables section
  3. Add or edit variables

Via CLI:

# Set for all environments (project context from login)
bunx @temps-sdk/cli environments vars set \
  DATABASE_URL "postgresql://user:pass@host/db"

# Set for a specific environment
bunx @temps-sdk/cli environments vars set \
  --environments production \
  DATABASE_URL "postgresql://user:pass@host/db"

Via API:

await fetch("/api/projects/my-app/environments/production/env-vars", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    key: "DATABASE_URL",
    value: "postgresql://user:pass@host/db",
  }),
});

Reserved Variables

Temps automatically sets these variables in your containers:

VariableDescription
HOSTSet to 0.0.0.0 to bind to all interfaces
PORTPort number your application should listen on
TEMPS_PROJECT_IDCurrent project ID
TEMPS_ENVIRONMENT_IDCurrent environment ID
TEMPS_DEPLOYMENT_IDCurrent deployment ID

Framework-Specific Variables

Common environment variables for popular frameworks:

Next.js:

NODE_ENV=production
NEXT_PUBLIC_API_URL=https://api.example.com

React/Vite:

VITE_API_URL=https://api.example.com

Node.js:

NODE_ENV=production
PORT=3000

Python:

PYTHONUNBUFFERED=1
FLASK_ENV=production

CLI Configuration

These environment variables configure the Temps CLI:

VariableDescription
TEMPS_API_URLAPI endpoint URL (e.g., https://app.temps.davidviejo.dev)
TEMPS_API_TOKENAPI authentication token
TEMPS_API_KEYAPI key (alternative to token)
NO_COLORDisable colored output (set to 1 or true)

Example

export TEMPS_API_URL=https://app.temps.davidviejo.dev
export TEMPS_API_TOKEN=your-token-here

Configuration Files

CLI configuration is stored in:

  • Config file: ~/.temps/config.json
  • Credentials: ~/.temps/.secrets

Use bunx @temps-sdk/cli configure show to view current configuration.


SDK Configuration

Node.js SDK

VariableDescription
TEMPS_API_URLYour Temps API URL
TEMPS_TOKENYour API key or deployment token
TEMPS_PROJECT_IDProject ID (optional, can be set in code)

React Analytics SDK

VariableDescription
NEXT_PUBLIC_TEMPS_API_URLTemps API URL (for Next.js)
NEXT_PUBLIC_TEMPS_PROJECT_IDProject ID (for Next.js)

Example

# Node.js SDK
export TEMPS_API_URL=https://app.temps.davidviejo.dev
export TEMPS_TOKEN=your-token-here

# Next.js with React Analytics
export NEXT_PUBLIC_TEMPS_API_URL=https://app.temps.davidviejo.dev
export NEXT_PUBLIC_TEMPS_PROJECT_ID=123

Precedence Rules

Environment variables are resolved in the following order (highest to lowest priority):

  1. Container Environment Variables (set at deployment time)
  2. Environment-Specific Variables (set in dashboard/CLI for the environment)
  3. Project-Level Variables (set in dashboard/CLI for the project)
  4. System Environment Variables (from the host system)
  5. Default Values (if any)

Example

If you set:

  • Project-level: DATABASE_URL=postgres://project/db
  • Environment-level: DATABASE_URL=postgres://env/db
  • Container-level: DATABASE_URL=postgres://container/db

The container will use: postgres://container/db (highest priority).

Variable Override

You can override any variable at a more specific level:

# Project-level (applies to all environments)
bunx @temps-sdk/cli environments vars set \
  API_URL "https://api.example.com"

# Environment-level (overrides project-level)
bunx @temps-sdk/cli environments vars set \
  --environments production \
  API_URL "https://api-prod.example.com"

Best Practices

Security

  • Never commit secrets: Use environment variables for sensitive data
  • Use different values per environment: Production should have different credentials than staging
  • Rotate secrets regularly: Update API keys and tokens periodically
  • Use secure storage: Consider using secret management tools for production

Organization

  • Use descriptive names: DATABASE_URL is better than DB
  • Document variables: Keep a list of required variables in your README
  • Group related variables: Use prefixes like DATABASE_, API_, REDIS_
  • Set defaults when possible: Provide sensible defaults in your application code

Debugging

  • Check variable precedence: Verify which value is actually being used
  • Use logging: Log variable names (not values) to verify they're set
  • Test locally: Use .env files for local development
  • Verify in dashboard: Check environment variables in the Temps dashboard

Additional Resources

Was this page helpful?