Skip to content

Documentation

Secrets & Tokens Inventory

Complete inventory of all secrets, tokens, and security keys in SveltyCMS — where they live, who can access them, and how to rotate them.

7/7/2026
10 min read Edit on GitHub

SveltyCMS stores secrets in two tiers:

flowchart TB subgraph Setup["Setup Wizard"] GEN["Generate keys
(CSPRNG + RSA-2048)"] WRITE["Write config/private.ts"] SEED["Seed database"] end subgraph Bootstrap["Bootstrap Tier"] PRIV["config/private.ts
DB creds, JWT, encryption
MULTI_TENANT, DEMO"] end subgraph Dynamic["Dynamic Tier"] DB["system_preferences
SAML, SMTP, OAuth
Rate limit, AI, Cache TTLs"] UI["System Settings UI"] end subgraph Runtime["Runtime"] AUTH["Auth hooks"] API["API handlers"] TOKEN["Content token engine"] CLIENT["Browser
(public only)"] end GEN --> WRITE --> PRIV GEN --> SEED --> DB DB <--> UI PRIV --> AUTH PRIV --> API DB --> AUTH DB --> API DB --> TOKEN DB -.->|"public only"| CLIENT
Tier Location When loaded Managed via
Bootstrap config/private.ts At server start, before DB connection File-only (generated during setup)
Dynamic Database (system_preferences) After DB initializes System Settings UI (/config/system-settings)

Bootstrap Secrets (config/private.ts)

These must be available before the database connection is established. The server cannot start without them.

Key Purpose Generated Rotatable
DB_TYPE Which database adapter to load (sqlite, mariadb, postgresql, mongodb) ❌ User-configured ⚠️ Requires setup re-run
DB_HOST Database server hostname or file path (SQLite) ❌ User-configured ⚠️ Requires setup re-run
DB_PORT Database server port ❌ User-configured ⚠️ Requires setup re-run
DB_NAME Database name ❌ User-configured ⚠️ Requires setup re-run
DB_USER Database username ❌ User-configured ⚠️ Requires setup re-run
DB_PASSWORD Database password ❌ User-configured ✅ Change in DB + update file
DB_RETRY_ATTEMPTS Max connection retry attempts (default: 5) ❌ Default ✅ Edit file
DB_RETRY_DELAY Delay between retries in ms (default: 3000) ❌ Default ✅ Edit file
JWT_SECRET_KEY Signs all session tokens and JWTs ✅ CSPRNG (32-char) ⚠️ Invalidates all sessions
ENCRYPTION_KEY Encrypts sensitive fields at rest ✅ CSPRNG (32-char) ⚠️ Requires data re-encryption
MULTI_TENANT Enables multi-tenant isolation mode ❌ Default false ✅ Edit file + restart
DEMO Enables ephemeral demo tenant mode ❌ Default false ✅ Edit file + restart
Caution

Rotating JWT_SECRET_KEY invalidates all user sessions. Rotating ENCRYPTION_KEY requires re-encrypting all stored encrypted data. Plan maintenance windows accordingly.


Dynamic Secrets (Database)

These are seeded into the database during setup and managed via the System Settings UI at /config/system-settings. Changes take effect on next request (no restart required unless noted).

Security & Authentication

Key Type Default UI Group Notes
PASSWORD_MIN_LENGTH Public 8 Security Enforced by Auth.validatePasswordStrength()
RATE_LIMIT_SECRET Private "" (auto-gen) Security Signing secret for rate limiter cookies; falls back to JWT_SECRET_KEY + "-ratelimit" if empty
USE_2FA Private false Enable two-factor authentication globally
TWO_FACTOR_AUTH_BACKUP_CODES_COUNT Private 10 Number of backup codes per 2FA user
USE_GOOGLE_OAUTH Public false OAuth Enable Google OAuth login
GOOGLE_CLIENT_ID Private "" OAuth OAuth 2.0 client ID
GOOGLE_CLIENT_SECRET Private "" OAuth OAuth 2.0 client secret
GOOGLE_API_KEY Private "" OAuth Google services API key
GOOGLE_MAPS_API_KEY Public "" OAuth Google Maps client-side key

SAML / Enterprise SSO

Key Type Default UI Group Notes
SAML_CLIENT_SECRET_VERIFIER Private "" (auto-gen) SAML / Enterprise SSO Validates identity provider assertions
SAML_ENCRYPTION_KEY Private "" (auto-gen) SAML / Enterprise SSO Encrypts SAML assertions
SAML_JWT_SIGNING_PRIVATE_KEY Private "" (auto-gen) SAML / Enterprise SSO RSA-2048 PEM private key
SAML_JWT_SIGNING_PUBLIC_KEY Private "" (auto-gen) SAML / Enterprise SSO RSA-2048 PEM public key

SMTP / Email

Key Type Default UI Group Notes
SMTP_HOST Private "" Email / SMTP SMTP server hostname
SMTP_PORT Private 587 Email / SMTP SMTP port
SMTP_USER Private "" Email / SMTP SMTP username
SMTP_PASS Private "" Email / SMTP SMTP password (sensitive)
SMTP_MAIL_FROM Private "" Email / SMTP From address for sent emails
SMTP_EMAIL Private "" Email / SMTP Reply-to address

Redis / Caching

Key Type Default UI Group Notes
USE_REDIS Private false Enable Redis L2 cache
REDIS_HOST Private "localhost" Redis host
REDIS_PORT Private 6379 Redis port
REDIS_PASSWORD Private "" Redis password

Cache TTLs (seconds)

Key Default Description
CACHE_TTL_SCHEMA 600 Schema/collection definitions (10 min)
CACHE_TTL_WIDGET 600 Widget data (10 min)
CACHE_TTL_THEME 300 Theme configurations (5 min)
CACHE_TTL_CONTENT 180 Content data (3 min)
CACHE_TTL_MEDIA 300 Media metadata (5 min)
CACHE_TTL_SESSION 86400 User sessions (24 hours)
CACHE_TTL_USER 60 User permissions (1 min)
CACHE_TTL_API 300 API responses (5 min)

Sessions & Authentication Lifecycle

Key Default Description
COOKIE_PATH "/" Custom cookie path for session/demo cookies
SESSION_CLEANUP_INTERVAL 300000 Expired session cleanup interval (ms)
MAX_IN_MEMORY_SESSIONS 1000 Max sessions in memory cache
DB_VALIDATION_PROBABILITY 0.1 Probability of DB re-validation per request
SESSION_EXPIRATION_SECONDS 86400 Session lifetime (24 hours)

AI / LLM

Key Type Default Notes
AI_PROVIDER Private "ollama" AI backend
OLLAMA_URL Private "http://localhost:11434" Local Ollama endpoint
AI_MODEL_CHAT Private "ministral-3:latest" Chat/assistant model
AI_MODEL_VISION Private "llava:latest" Image tagging model
USE_AI_TAGGING Private false Enable AI image tagging
USE_REMOTE_AI_KNOWLEDGE Private false Remote knowledge base (mcp.sveltycms.com)

Third-Party Integrations

Key Type Default Notes
CF_API_TOKEN Private "" Cloudflare cache purging
CF_ZONE_ID Private "" Cloudflare zone identifier
CF_PURGE_MODE Private "tags" tags or all
USE_MAPBOX Private false Mapbox integration toggle
MAPBOX_API_TOKEN Private "" Mapbox public token
SECRET_MAPBOX_API_TOKEN Private "" Mapbox server-side token
TWITCH_TOKEN Private "" Twitch API token
TIKTOK_TOKEN Private "" TikTok API token
DEMO_TTL Public 60 Demo session TTL in minutes

Runtime-Generated Tokens

These are generated at runtime and never stored in configuration files.

Token Location Lifetime Notes
Session cookies Browser (__Host-session_id or session_id) Session TTL (default 24h) Signed with JWT_SECRET_KEY
CSRF tokens Browser (__Host-csrf_token) Session Double-submit cookie pattern
Demo tenant cookies Browser (__Host-demo_tenant_id) DEMO_TTL minutes Ephemeral tenant assignment
API keys (sck_...) Database (SHA-256 hashed) Permanent until revoked Plaintext shown once on creation
Website tokens Database (SHA-256 hashed) Permanent until revoked Bearer auth for external clients
TOTP replay registry In-memory (per-process) 30-second window Prevents code reuse
Rate limit counters In-memory (per-process) Per-window IP/Cookie-scoped

Security Properties

Category: public vs private

  • Public settings are exposed to the client via +layout.server.tsglobal-settings.svelte.ts. They are safe for browser access (e.g., SITE_NAME, PASSWORD_MIN_LENGTH, DEMO_TTL).
  • Private settings never leave the server. They are loaded via getPrivateSettingSync() / getPrivateSetting() and only accessible in .server.ts files, hooks, and API handlers.

Content Token Leak Prevention

Bootstrap secrets (DB_USER, DB_PASSWORD, JWT_SECRET_KEY, ENCRYPTION_KEY) are impossible to leak through the content templating system ({{ }}):

Token prefix Data source Can access bootstrap secrets?
{{ entry.* }} Collection data (user content) No
{{ user.* }} Hardcoded allowlist of 7 fields No — blocked fields return empty string
{{ site.* }} publicEnv (public settings only) No — private settings never reach the store
{{ system.* }} Hardcoded timestamps No

No user — regardless of role — can access DB_USER, DB_PASSWORD, or any bootstrap secret through the content token engine, API, or UI.

Schema Validation

All settings are validated against two Valibot schemas:

Schema File Validates
privateConfigSchema src/databases/private-config-schema.ts All private settings (bootstrap + DB-driven)
publicConfigSchema src/databases/public-config-schema.ts All public settings exposed to client

Environment Variable Overrides

All settings can be overridden via environment variables (e.g., SVELTYCMS_DEMO=true bun run dev). Environment variables take precedence over both private.ts and database values. The config-state.ts module handles the merge order:

Environment variable → config/private.ts → Database (system_preferences) → Schema default

Key Rotation

Secret Rotation Interval Impact
JWT_SECRET_KEY Every 90 days All sessions invalidated
ENCRYPTION_KEY Every 180 days Encrypted data must be re-encrypted
RATE_LIMIT_SECRET Every 90 days Rate limit states unaffected
TEST_API_SECRET Every 30 days Integration tests need update
LOG_CHAIN_SECRET Every 90 days Past logs/app.log chains unverifiable; keep old secret to verify archives
API keys (sck_...) Every 90 days Create new → update service → revoke old
SAML signing keys Every 180 days Update identity provider metadata

Related

securitysecretstokenskeysconfiguration
Was this page helpful?