Configuration

Storsko is configured entirely through environment variables. All variables are read at startup. Changes require a process restart.

Configuration

Storsko is configured entirely through environment variables. All variables are read at startup. Changes require a process restart.


Configuration File

Storsko reads from a .env file in the repository root, or from environment variables set in your shell / container runtime. Environment variables always take precedence over .env file values.

A complete .env template:

# .env.example — copy to .env and fill in your values

# ── Database ───────────────────────────────────────────────────────────────
DATABASE_URL=postgresql://storsko:storsko@localhost:5432/storsko

# ── Auth ───────────────────────────────────────────────────────────────────
ROOT_API_KEY_SECRET=
JWT_SECRET=
JWT_EXPIRES_IN=7d

# ── API Server ─────────────────────────────────────────────────────────────
PORT=3000
NODE_ENV=development
LOG_LEVEL=info

# ── LLM Gateway (optional) ────────────────────────────────────────────────
OPENAI_API_KEY=
ANTHROPIC_API_KEY=

# ── Commercial: Application URLs ──────────────────────────────────────────
NEXT_PUBLIC_API_URL=http://localhost:3000
NEXT_PUBLIC_LANDING_URL=http://localhost:3002

# ── Commercial: Keycloak SSO ──────────────────────────────────────────────
KEYCLOAK_URL=
KEYCLOAK_REALM=storsko
KEYCLOAK_CLIENT_ID=storsko-api
KEYCLOAK_CLIENT_SECRET=

# ── Commercial: Stripe Billing ────────────────────────────────────────────
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=

Database

DATABASE_URL

The PostgreSQL connection string.

FieldValue
RequiredYes
DefaultNone
Formatpostgresql://[user]:[password]@[host]:[port]/[database]
DATABASE_URL=postgresql://storsko:storsko@localhost:5432/storsko

For production, use a connection pooler (e.g. PgBouncer) and set ?pgbouncer=true in the query string if using Prisma-style pooling. With Drizzle ORM and plain pg, no special flags are needed.

# Example with Neon serverless PostgreSQL
DATABASE_URL=postgresql://storsko:supersecret@ep-calm-sun-abc123.us-east-1.aws.neon.tech/storsko?sslmode=require

# Example with Supabase
DATABASE_URL=postgresql://postgres:supersecret@db.abcdefghijklmnop.supabase.co:5432/postgres

# Example with Railway
DATABASE_URL=postgresql://postgres:supersecret@roundhouse.proxy.rlwy.net:12345/railway

DATABASE_POOL_MIN

Minimum number of database connections in the pool.

FieldValue
RequiredNo
Default2

DATABASE_POOL_MAX

Maximum number of database connections in the pool.

FieldValue
RequiredNo
Default10

Auth

ROOT_API_KEY_SECRET

The secret used to sign and verify the root API key. This is generated automatically by make setup.

FieldValue
RequiredYes
DefaultNone (auto-generated by make setup)
Format32+ byte random hex string

JWT_SECRET

The secret used to sign JSON Web Tokens issued by the API server.

FieldValue
RequiredYes
DefaultNone (auto-generated by make setup)
Format32+ byte random string
Minimum length32 characters

In production, this should be a cryptographically random string of at least 64 characters:

# Generate a suitable secret
openssl rand -hex 64

JWT_EXPIRES_IN

How long issued JWTs are valid.

FieldValue
RequiredNo
Default7d
Formatms duration string
JWT_EXPIRES_IN=7d       # 7 days (default)
JWT_EXPIRES_IN=24h      # 24 hours
JWT_EXPIRES_IN=1h       # 1 hour (recommended for production)
JWT_EXPIRES_IN=30m      # 30 minutes

API Server

PORT

The port the Fastify API server listens on.

FieldValue
RequiredNo
Default3000
PORT=3000
PORT=8080   # common alternative

NODE_ENV

The Node.js environment. Affects logging verbosity, error detail in responses, and some internal behaviours.

FieldValue
RequiredNo
Defaultdevelopment
Allowed valuesdevelopment, production, test

LOG_LEVEL

The minimum log level. Storsko uses Pino for structured JSON logging.

FieldValue
RequiredNo
Defaultinfo
Allowed valuestrace, debug, info, warn, error, fatal
LOG_LEVEL=info    # default — logs info, warn, error, fatal
LOG_LEVEL=debug   # useful for development
LOG_LEVEL=warn    # quieter in production

CORS_ORIGINS

Comma-separated list of allowed CORS origins. Applies to the API server.

FieldValue
RequiredNo
Defaulthttp://localhost:3001 (the web dashboard)
CORS_ORIGINS=http://localhost:3001,https://dashboard.example.com

HITL_DEFAULT_TIMEOUT_MINUTES

How many minutes a HITL request stays pending before it times out automatically.

FieldValue
RequiredNo
Default30
HITL_DEFAULT_TIMEOUT_MINUTES=30    # 30 minutes (default)
HITL_DEFAULT_TIMEOUT_MINUTES=60    # 1 hour
HITL_DEFAULT_TIMEOUT_MINUTES=1440  # 24 hours

When a HITL request times out, a hitl.timeout event is written to the audit log. The requesting agent receives a HITL_TIMEOUT error.


LLM Gateway

The LLM gateway is optional. It is only used if you call POST /api/v1/llm/chat. You can configure one or both providers.

OPENAI_API_KEY

The OpenAI API key. Required to route LLM requests to OpenAI models.

FieldValue
RequiredNo
DefaultNone
OPENAI_API_KEY=sk-proj-...

ANTHROPIC_API_KEY

The Anthropic API key. Required to route LLM requests to Anthropic models (e.g. Claude).

FieldValue
RequiredNo
DefaultNone
ANTHROPIC_API_KEY=sk-ant-...

LLM_GATEWAY_PII_DETECTION

Whether to run PII detection on LLM request and response content before logging.

FieldValue
RequiredNo
Defaulttrue
Allowed valuestrue, false
LLM_GATEWAY_PII_DETECTION=true

When enabled, detected PII patterns (email addresses, phone numbers, national ID numbers, credit card numbers) are redacted in audit log entries.

LLM_GATEWAY_RATE_LIMIT_RPM

Maximum LLM requests per minute across all agents.

FieldValue
RequiredNo
Default60
LLM_GATEWAY_RATE_LIMIT_RPM=60    # 60 requests/minute (default)
LLM_GATEWAY_RATE_LIMIT_RPM=120   # doubled

Application URLs (Commercial)

These variables are used by the Next.js web dashboard (apps/web). Prefix NEXT_PUBLIC_ makes them available to the browser bundle.

NEXT_PUBLIC_API_URL

The base URL of the Storsko API server, as seen from the browser.

FieldValue
RequiredYes (for web dashboard)
Defaulthttp://localhost:3000
NEXT_PUBLIC_API_URL=http://localhost:3000          # local development
NEXT_PUBLIC_API_URL=https://api.example.com        # production

NEXT_PUBLIC_LANDING_URL

The base URL of the public landing site.

FieldValue
RequiredNo
Defaulthttp://localhost:3002
NEXT_PUBLIC_LANDING_URL=http://localhost:3002
NEXT_PUBLIC_LANDING_URL=https://storsko.example.com

Keycloak SSO (Commercial — Enterprise Tier)

Keycloak integration enables SAML, LDAP, and enterprise SSO. It is only available on the Enterprise commercial tier.

KEYCLOAK_URL

The base URL of your Keycloak instance.

FieldValue
RequiredCommercial Enterprise only
DefaultNone
KEYCLOAK_URL=https://auth.example.com

KEYCLOAK_REALM

The Keycloak realm name for Storsko.

FieldValue
RequiredCommercial Enterprise only
Defaultstorsko
KEYCLOAK_REALM=storsko

KEYCLOAK_CLIENT_ID

The Keycloak client ID for the Storsko API.

FieldValue
RequiredCommercial Enterprise only
Defaultstorsko-api
KEYCLOAK_CLIENT_ID=storsko-api

KEYCLOAK_CLIENT_SECRET

The Keycloak client secret. Found in Keycloak Admin → Clients → storsko-api → Credentials.

FieldValue
RequiredCommercial Enterprise only
DefaultNone
KEYCLOAK_CLIENT_SECRET=abc123...

Stripe Billing (Commercial)

Stripe integration handles subscription management for the commercial platform.

STRIPE_SECRET_KEY

Your Stripe secret key. Use test keys (sk_test_...) in development and live keys (sk_live_...) in production.

FieldValue
RequiredCommercial only
DefaultNone
STRIPE_SECRET_KEY=sk_test_...    # development
STRIPE_SECRET_KEY=sk_live_...    # production

STRIPE_WEBHOOK_SECRET

The Stripe webhook signing secret. Used to verify that webhook events come from Stripe.

FieldValue
RequiredCommercial only
DefaultNone
STRIPE_WEBHOOK_SECRET=whsec_...

To get the webhook secret:

  1. Go to stripe.com/dashboard → Webhooks
  2. Add an endpoint pointing to https://your-domain.com/api/v1/billing/webhook
  3. Copy the signing secret

Summary Table

VariableRequiredDefaultSection
DATABASE_URLYesDatabase
DATABASE_POOL_MINNo2Database
DATABASE_POOL_MAXNo10Database
ROOT_API_KEY_SECRETYesauto-generatedAuth
JWT_SECRETYesauto-generatedAuth
JWT_EXPIRES_INNo7dAuth
PORTNo3000API Server
NODE_ENVNodevelopmentAPI Server
LOG_LEVELNoinfoAPI Server
CORS_ORIGINSNohttp://localhost:3001API Server
HITL_DEFAULT_TIMEOUT_MINUTESNo30API Server
OPENAI_API_KEYNoLLM Gateway
ANTHROPIC_API_KEYNoLLM Gateway
LLM_GATEWAY_PII_DETECTIONNotrueLLM Gateway
LLM_GATEWAY_RATE_LIMIT_RPMNo60LLM Gateway
NEXT_PUBLIC_API_URLWeb onlyhttp://localhost:3000App URLs
NEXT_PUBLIC_LANDING_URLNohttp://localhost:3002App URLs
KEYCLOAK_URLEnterpriseKeycloak
KEYCLOAK_REALMEnterprisestorskoKeycloak
KEYCLOAK_CLIENT_IDEnterprisestorsko-apiKeycloak
KEYCLOAK_CLIENT_SECRETEnterpriseKeycloak
STRIPE_SECRET_KEYCommercialStripe
STRIPE_WEBHOOK_SECRETCommercialStripe