Self-Hosted Configuration
Self-hosted deployments require configuration for tokens, providers, networking, and browser connectivity. This page documents all environment variables and configuration options for the self-hosted stack.
Environment File Location
The stack reads configuration from a stack.env file in the workspace root (one level up from the stack/ directory):
cp stack/stack.env.example stack.envRequired Variables
These variables must be set before starting the stack:
| Variable | Description | Example |
|---|---|---|
ENCRYPTION_KEY | 32+ character secret for encrypting stored API keys | abcd1234... (64 char hex) |
ENGINE_API_KEY | Server-side API key for engine authentication | my-secure-api-key |
JWT_SECRET | 32+ character secret for JWT token signing | my-jwt-secret-min-32-chars |
CORE_BOOTSTRAP_PUBLISHABLE_KEY | Publishable key for Core to auto-create on first boot | vkey_... (64 char hex) |
DEEPGRAM_API_KEY | Deepgram API key for STT and TTS | Get from deepgram.com |
GROQ_API_KEY or OPENROUTER_API_KEY | LLM provider API key | Get from provider console |
Generating Secure Keys
Generate secure random keys for secrets:
# 64-character hex string for ENCRYPTION_KEY and CORE_BOOTSTRAP_PUBLISHABLE_KEY
openssl rand -hex 32
# 32+ character random string for JWT_SECRET and ENGINE_API_KEY
openssl rand -base64 32Provider Configuration
LLM Provider
Choose one LLM provider:
# Option 1: Groq (default, fast)
LLM_PROVIDER=groq
GROQ_API_KEY=gsk_your_groq_key
GROQ_MODEL=openai/gpt-oss-20b
# Option 2: OpenRouter (100+ models)
LLM_PROVIDER=openrouter
OPENROUTER_API_KEY=sk-or-v1-your_key
OPENROUTER_MODEL=openrouter/healer-alpha
# Option 3: OpenAI-compatible gateway
LLM_PROVIDER=openai-compatible
OPENAI_COMPATIBLE_BASE_URL=http://host.docker.internal:8000/v1
OPENAI_COMPATIBLE_API_KEY=your_key
OPENAI_COMPATIBLE_MODEL=gpt-4o-miniLLM Provider Variables:
| Variable | Default | Description |
|---|---|---|
LLM_PROVIDER | openrouter | groq, openrouter, or openai-compatible |
GROQ_API_KEY | - | Groq API key |
GROQ_MODEL | openai/gpt-oss-20b | Groq model ID |
GROQ_WHISPER_MODEL | whisper-large-v3 | Groq Whisper model for STT |
OPENROUTER_API_KEY | - | OpenRouter API key |
OPENROUTER_MODEL | openrouter/healer-alpha | OpenRouter model ID |
OPENAI_COMPATIBLE_BASE_URL | http://host.docker.internal:8000/v1 | Base URL for compatible gateway |
OPENAI_COMPATIBLE_API_KEY | - | API key for compatible gateway |
OPENAI_COMPATIBLE_MODEL | gpt-4o-mini | Model ID for compatible gateway |
STT/TTS Configuration
Deepgram is the default provider for both speech-to-text and text-to-speech:
STT_PROVIDER=deepgram
DEEPGRAM_API_KEY=your_deepgram_key
DEEPGRAM_STT_MODEL=nova-3
DEEPGRAM_STT_LANGUAGE=en-US
TTS_PROVIDER=deepgram
DEEPGRAM_TTS_MODEL=aura-2-thalia-enSTT/TTS Variables:
| Variable | Default | Description |
|---|---|---|
STT_PROVIDER | deepgram | Speech-to-text provider |
DEEPGRAM_STT_MODEL | nova-3 | Deepgram STT model |
DEEPGRAM_STT_LANGUAGE | en-US | STT language code |
TTS_PROVIDER | deepgram | Text-to-speech provider |
DEEPGRAM_TTS_MODEL | aura-2-thalia-en | Deepgram TTS voice model |
VAD Configuration
Voice Activity Detection (VAD) detects when users start and stop speaking:
VAD_PROVIDER=silero
VAD_ENABLED=trueVAD Variables:
| Variable | Default | Description |
|---|---|---|
VAD_PROVIDER | silero | VAD provider (silero or none) |
VAD_ENABLED | true | Enable server-side VAD |
Bootstrap Configuration
Core auto-creates an app and publishable API key on first boot using these variables:
CORE_BOOTSTRAP_APP_ID=default
CORE_BOOTSTRAP_APP_NAME=Local Stack App
CORE_BOOTSTRAP_APP_DESCRIPTION=Bootstrap app for the self-hosted Docker stack
CORE_BOOTSTRAP_API_KEY_LABEL=Local Stack Key
CORE_BOOTSTRAP_SCOPES=mint_ephemeral
CORE_BOOTSTRAP_ALLOWED_PROVIDERS=vowel-prime
CORE_BOOTSTRAP_ALLOWED_ENDPOINT_PRESETS=staging
CORE_BOOTSTRAP_DEFAULT_ENDPOINT_PRESET=staging
CORE_BOOTSTRAP_PUBLISHABLE_KEY=vkey_0123456789abcdef...Bootstrap Variables:
| Variable | Default | Description |
|---|---|---|
CORE_BOOTSTRAP_APP_ID | default | App ID to create |
CORE_BOOTSTRAP_APP_NAME | Local Stack App | Display name |
CORE_BOOTSTRAP_APP_DESCRIPTION | Bootstrap app for the self-hosted Docker stack | Description |
CORE_BOOTSTRAP_API_KEY_LABEL | Local Stack Key | API key label |
CORE_BOOTSTRAP_SCOPES | mint_ephemeral | Comma-separated scopes |
CORE_BOOTSTRAP_ALLOWED_PROVIDERS | vowel-prime | Comma-separated allowed providers |
CORE_BOOTSTRAP_ALLOWED_ENDPOINT_PRESETS | staging | Comma-separated allowed presets |
CORE_BOOTSTRAP_DEFAULT_ENDPOINT_PRESET | staging | Default preset |
CORE_BOOTSTRAP_PUBLISHABLE_KEY | - | Required. Plaintext publishable key to seed |
The publishable key is what client applications use to request tokens from Core. It should be a 64-character hex string prefixed with vkey_.
Port Configuration
Override default ports when they conflict with existing services:
CORE_HOST_PORT=3001
ENGINE_HOST_PORT=8788Port Variables:
| Variable | Default | Description |
|---|---|---|
CORE_HOST_PORT | 3000 | Host port for Core service |
ENGINE_HOST_PORT | 8787 | Host port for Engine service |
After changing ports, update the Core environment to reflect the new engine port:
# In stack.env
ENGINE_URL=http://engine:8787
ENGINE_WS_URL=ws://localhost:8788/v1/realtime
ENDPOINT_PRESET_VOWEL_PRIME_STAGING_HTTP_URL=http://engine:8787
ENDPOINT_PRESET_VOWEL_PRIME_STAGING_WS_URL=ws://localhost:8788/v1/realtimeRuntime Config Ownership
The engine persists its runtime configuration as YAML at /app/data/config/runtime.yaml on the engine-data Docker volume. Environment variables in stack.env act as bootstrap defaults for the first boot and as fallback values when a key is missing from the YAML.
HTTP Config Endpoints
The engine exposes HTTP endpoints for inspecting and updating runtime configuration without rebuilding:
| Endpoint | Method | Description |
|---|---|---|
/config | GET | Retrieve current runtime config |
/config | PUT | Update runtime config |
/config/validate | POST | Validate a config change |
/config/reload | POST | Reload config from disk |
/presets | GET | List available presets |
All config endpoints require the engine admin API key via Authorization: Bearer ${ENGINE_API_KEY}.
Example: Update Runtime Config
# Get current config
curl http://localhost:8787/config \
-H "Authorization: Bearer ${ENGINE_API_KEY}"
# Update a setting
curl -X PUT http://localhost:8787/config \
-H "Authorization: Bearer ${ENGINE_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"llm": {"provider": "groq", "model": "openai/gpt-oss-20b"}}'
# Validate before applying
curl -X POST http://localhost:8787/config/validate \
-H "Authorization: Bearer ${ENGINE_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"llm": {"provider": "openrouter"}}'
# Reload from disk
curl -X POST http://localhost:8787/config/reload \
-H "Authorization: Bearer ${ENGINE_API_KEY}"Core Configuration Areas
Provider Credentials
Store all provider API keys in stack.env. Core encrypts provider keys before storing them in its SQLite database using the ENCRYPTION_KEY.
Service URLs
Core needs to know how to reach the engine:
# Internal Docker network URL (Core -> Engine)
ENGINE_URL=http://engine:8787
# External URL for clients (used in token responses)
ENGINE_WS_URL=ws://localhost:8787/v1/realtimeToken Issuance Settings
Control who can request tokens and which providers they can use:
CORE_BOOTSTRAP_SCOPES: Controls API key capabilities (mint_ephemeral,mint_trusted_session)CORE_BOOTSTRAP_ALLOWED_PROVIDERS: Which voice providers can be usedCORE_BOOTSTRAP_ALLOWED_ENDPOINT_PRESETS: Which endpoint presets are available
Browser-Facing Origins
For CORS, Core accepts requests from any origin by default in development. In production, configure your reverse proxy to handle CORS policy.
Environment-Specific Configuration
Development
TEST_MODE=true
NODE_ENV=developmentProduction
TEST_MODE=false
NODE_ENV=productionSecurity Guidance
- Rotate provider secrets regularly (every 90 days recommended)
- Scope credentials to the environments that need them
- Terminate TLS before exposing browser-facing endpoints
- Avoid embedding long-lived credentials in any client bundle
- Never commit
stack.envto version control - Use
STACK_ENV_FILEto switch between environment files for different stages
Complete Example Configuration
# stack.env - Production Example
# === REQUIRED SECRETS ===
ENCRYPTION_KEY=your-64-char-hex-encryption-key
ENGINE_API_KEY=your-secure-server-api-key
JWT_SECRET=your-32-char-minimum-jwt-secret
CORE_BOOTSTRAP_PUBLISHABLE_KEY=vkey_your-64-char-hex-key
# === PROVIDER CREDENTIALS ===
DEEPGRAM_API_KEY=your-deepgram-key
# LLM Provider (pick one)
LLM_PROVIDER=groq
GROQ_API_KEY=gsk_your_groq_key
# === OPTIONAL OVERRIDES ===
CORE_HOST_PORT=3000
ENGINE_HOST_PORT=8787
# === BOOTSTRAP CONFIG ===
CORE_BOOTSTRAP_APP_ID=production-app
CORE_BOOTSTRAP_APP_NAME=Production Voice App
CORE_BOOTSTRAP_SCOPES=mint_ephemeral,mint_trusted_session
CORE_BOOTSTRAP_ALLOWED_PROVIDERS=vowel-prime