ENV Variables
Sentinel is configured entirely through environment variables. Everything below is optional with a sensible default unless noted otherwise — set only what you need to change.
Required secrets
These are auto-generated on first start if unset (and persisted to the data volume) — or derive them deterministically across a cluster with SECRET_SEED, see Clustering.
| Variable | Default | Notes |
|---|
ALTCHA_HMAC_SECRET | auto-generated | Signs ALTCHA challenges. Minimum 24 characters. |
CODE_CHALLENGE_SECRET | auto-generated | Signs code challenges. Minimum 24 characters. |
JWT_SECRET | auto-generated | Signs admin session JWTs. Minimum 24 characters. |
EXOTDB_HMAC_SECRET | (empty) | HMAC secret for data signatures (mainly access logs). Minimum 24 characters. |
HASHING_SALT | auto-generated | Salt used for IP and other hashing. |
NODE_ID | auto-generated | Unique identifier for this node — see Clustering. |
SECRET_SEED | (empty) | If set, deterministically derives all of the above instead of auto-generating them. |
Licensing
See License for how these are used.
| Variable | Default | Purpose |
|---|
LICENSE_KEY | (empty) | License key; verified periodically via call-home to eu.altcha.org. |
LICENSE_JSON | (empty) | Full license file contents — set instead of LICENSE_KEY to disable call-home entirely. |
Application
| Variable | Default | Purpose |
|---|
PORT | 8080 | Port the app listens on. |
DATA_DIR | /data | Directory for application data. |
BASE_URL | (empty) | Base URL for generating absolute links. |
APP_BASE_PATH | (empty) | Serve the app under a path prefix. |
DEFAULT_ACCOUNT_NAME | Default Account | Name of the account created on first setup. |
DEFAULT_ROOT_PASSWORD | root | Initial root password — change immediately after first login. |
NODE_NAME | (empty) | Human-readable name for this node. |
TZ | system timezone | Application timezone. |
USER_AGENT | altcha-sentinel/{version} | User-Agent used for Sentinel's own outbound requests. |
API_DOCS_ENABLED | 1 | Serve API docs at /v1/docs. |
INSPECT_ROUTE_ENABLED | 1 | Enable GET /v1/inspect. |
Security & access
| Variable | Default | Purpose |
|---|
APP_IP_WHITELIST | (empty, unrestricted) | Restrict admin/app access to given IPs/CIDRs. |
ALLOWED_HOSTS | (empty) | Comma-separated, wildcard-supported allowed hostnames. |
CORS_ORIGINS | (empty, unrestricted) | Comma-separated allowed CORS origins. |
X_FORWARDED_FOR_TRUSTED | (empty) | Trusted proxy IPs allowed to set X-Forwarded-For — see Reverse Proxy. |
PASSWORD_LOGIN_ENABLED | 1 | Enable/disable password-based login. |
PASSWORD_MIN_LENGTH | 8 | Minimum admin password length. |
JWT_ISSUER | ALTCHA_SENTINEL | Issuer identifier used when generating admin session JWTs. |
JWT_TTL | 24h | Time-to-live for generated JWTs. |
SECURITY_TXT | (empty) | Overrides or disables /.well-known/security.txt. |
TLS_EXTRA_CA_CERTS | (empty) | Extra trusted CA bundle (PEM). |
HTTP2_CERT / HTTP2_KEY | (empty) | TLS cert/key to terminate HTTPS directly on the container. |
ANONYMIZE_IP_ADDRESS | 1 | Anonymize IPs generally. |
ACCESS_LOG_ANONYMIZE_IP_ADDRESS | 1 | Anonymize IPs specifically in access logs. |
IP_HEADERS_SECRET | (empty) | Secret to validate incoming IP-related headers. |
HEADER_ENTROPY_MAX_ENTRIES | 100 | Max header-combination hashes stored per IP — see Detection Signals. |
Networking
| Variable | Default | Purpose |
|---|
HTTP_PROXY / HTTPS_PROXY | (empty) | Outbound proxy for Sentinel's own HTTP/HTTPS requests. |
NO_PROXY | localhost,127.0.0.1,::1,0.0.0.0 | Hosts that bypass the outbound proxy. |
Database
Set one connection-string variable matching your engine — see Databases for the full list (POSTGRES_URL, MYSQL_URL, MARIADB_URL, MSSQL_URL, ORACLE_URL, LIBSQL_URL, TURBOLITE_URL) and examples. Each engine also accepts connection-tuning variables following the same prefix, most commonly:
| Suffix | Applies to | Purpose |
|---|
_CONNECT_TIMEOUT | MariaDB, MSSQL, MySQL, PostgreSQL | Connection timeout, in ms (default 10000). |
_MAX_CONNECTIONS | MariaDB, MSSQL, MySQL, PostgreSQL, LibSQL | Max pool size (default 10). |
_MIN_CONNECTIONS | PostgreSQL | Min pool size (default 0). |
_IDLE_TIMEOUT | PostgreSQL | Idle connection timeout, in ms (default 10000; 0 disables). |
_TLS_CA / _TLS_CERT / _TLS_KEY | MariaDB, MSSQL, MySQL, PostgreSQL | Custom TLS certificate material. |
_TLS_REJECT_UNAUTHORIZED | MariaDB, MSSQL, MySQL | Reject untrusted TLS connections (default 1). |
LIBSQL_AUTH_TOKEN | LibSQL | Auth token for the LibSQL/Turso database. |
POSTGRES_SSL_CA / POSTGRES_SSL_CERT / POSTGRES_SSL_KEY are deprecated aliases for the POSTGRES_TLS_* variables above.
The embedded default database is configured via EXOTDB_DATABASE_ADDR (default :::4080), EXOTDB_DATABASE_LOCATION (default ./db/altcha-sentinel.db), EXOTDB_ROOT_PASSWORD (default root), and EXOTDB_ENCRYPTION_KEY (optional, not generally recommended). DATABASE_URL (default http://root:root@localhost:4080?bootstrap=1) is the connection URL Sentinel uses internally to reach this embedded server — you don't need to set it yourself unless you're customizing the embedded setup directly.
KV store (Redis)
See Databases for enabling an external instance. Additional tuning:
| Variable | Default | Purpose |
|---|
REDIS_COMMAND_TIMEOUT | 5000 | Command timeout, ms. |
REDIS_CONNECT_TIMEOUT | 10000 | Connection timeout, ms. |
REDIS_MAX_RETRIES | 2 | Max retry attempts. |
REDIS_KEY_PREFIX | (empty) | Prefix applied to all Redis keys. |
REDIS_SENTINEL_HOSTS | (empty) | Comma-separated host:port list for Redis Sentinel mode. |
REDIS_SENTINEL_MASTER_NAME | (empty) | Monitored master name, for Sentinel mode. |
REDIS_SENTINEL_AUTH / REDIS_SENTINEL_REDIS_AUTH | (empty) | Auth for the Sentinel endpoints / the Redis nodes behind them. |
REDIS_SENTINEL_TLS / REDIS_SENTINEL_REDIS_TLS | 0 | Enable TLS to Sentinel endpoints / Redis nodes. |
The embedded default store is configured via EXOTDB_REDIS_ADDR (default :::6389) and EXOTDB_REDIS_LOCATION (default ./db/redis.db).
Snapshots
See Backups & Recovery for how these fit together.
| Variable | Default | Purpose |
|---|
SNAPSHOTS_MAIN_SCHEDULE | (empty, disabled) | Cron schedule for automatic main-database snapshots. |
SNAPSHOTS_REDIS_SCHEDULE | (empty, disabled) | Cron schedule for automatic Redis snapshots. |
SNAPSHOTS_STORAGE_PROVIDER | local | local, s3, or azure. |
SNAPSHOTS_DB_PREFIX | altcha-sentinel-backups/db:${iso_date()} | Path prefix for stored snapshots. |
SNAPSHOTS_ENCRYPTION_KEY | (empty) | Optional encryption key for snapshots. |
SNAPSHOTS_STORAGE_LOCAL_DIR | backups | Local directory, if using the local provider. |
SNAPSHOTS_STORAGE_S3_URL | (empty) | S3 URL, e.g. https://s3.eu-west-1.amazonaws.com/?bucket=my-bucket&prefix=storage. |
SNAPSHOTS_STORAGE_AZURE_CONTAINER / SNAPSHOTS_STORAGE_AZURE_CONNECTION_STRING | (empty) | Azure container + connection string. |
SNAPSHOTS_STORAGE_S3_BUCKET / _ACCESS_KEY_ID / _SECRET_ACCESS_KEY / _REGION / _ENDPOINT, and SNAPSHOTS_CRON_SCHEDULE, are deprecated — use SNAPSHOTS_STORAGE_S3_URL and SNAPSHOTS_MAIN_SCHEDULE/SNAPSHOTS_REDIS_SCHEDULE instead.
File storage
See Storage Providers for details.
| Variable | Default | Purpose |
|---|
STORAGE_PROVIDER | local | local, s3, or azure. |
STORAGE_LOCAL_DIR | uploads | Local directory, if using the local provider. |
STORAGE_S3_BUCKET / STORAGE_S3_ACCESS_KEY_ID / STORAGE_S3_SECRET_ACCESS_KEY / STORAGE_S3_REGION / STORAGE_S3_ENDPOINT | (empty) | S3 (or S3-compatible, e.g. MinIO) credentials and location. |
STORAGE_AZURE_CONTAINER / STORAGE_AZURE_CONNECTION_STRING | (empty) | Azure Blob Storage container + connection string. |
Caching
| Variable | Default | Purpose |
|---|
CACHE_DURATION_API_KEYS | 10s | How long API keys are cached before refresh. |
CACHE_DURATION_TRAINING_DATA | 1h | How long training data is cached before refresh. |
CACHE_DURATION_USED_CHALLENGES | 4h | How long used-challenge records are cached, to prevent reuse. |
Logging
| Variable | Default | Purpose |
|---|
LOG_LEVEL | info | trace, debug, info, warn, error, fatal, silent. |
LOG_FORMAT | json | json or plain. |
REQUEST_LOGS_TTL | 72h | How long request logs are retained. |
ACCESS_LOG_ENABLED | 1 | Enable/disable access logging. |
Monitoring
See Monitoring & Logging.
| Variable | Default | Purpose |
|---|
MONITORING_IP_WHITELIST | (private ranges, see below) | IPs/CIDRs allowed to reach /.health, /.metrics, etc. |
MONITORING_HTTP_CREDENTIALS | (empty) | user:password for Basic Auth on monitoring endpoints. |
MONITORING_IP_WHITELIST defaults to 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32,::1/128,fd00::/8,100.64.0.0/10 — the standard private/loopback/link-local ranges.
OpenTelemetry (Enterprise)
| Variable | Default | Purpose |
|---|
OTEL_EXPORTER_OTLP_ENDPOINT | (empty) | OTLP collector URL. |
OTEL_SERVICE_NAME | altcha-sentinel | Service name in traces/logs. |
OTEL_EXPORTER_OTLP_HEADERS | (empty) | Extra headers for OTLP requests (e.g. auth). |
OTEL_EXPORTER_OTLP_TIMEOUT | 10000 | Timeout, ms. |
ClickHouse (Enterprise)
See ClickHouse for the table schema and full setup.
| Variable | Default | Purpose |
|---|
CLICKHOUSE_URL | (empty) | e.g. http://user:password@localhost:8123/db_name. |
CLICKHOUSE_BATCH_INTERVAL | 1000 | Max ms before flushing the batch buffer. |
CLICKHOUSE_BATCH_MAX | 100 | Max entries before flushing. |
CLICKHOUSE_TLS_CA / _TLS_CERT / _TLS_KEY | (empty) | TLS certificate material. |
SSO (Enterprise)
See SSO.
| Variable | Purpose |
|---|
SSO_AZURE / SSO_GOOGLE / SSO_KEYCLOAK / SSO_OKTA | OIDC configuration per provider. |
SSO_LDAP | LDAP configuration. |
SSO_LDAP_TLS_CA / _TLS_CERT / _TLS_KEY | LDAP TLS certificate material (SSO_LDAP_SSL_CA / _SSL_CERT / _SSL_KEY are deprecated aliases). |
Email / SMTP
| Variable | Default | Purpose |
|---|
SMTP_URL | (empty) | SMTP connection URL for outgoing email — see Forms. |
EML_BODY_LIMIT | 5MB | Max body size for POST /v1/eml. |
AI providers
See AI Providers.
| Variable | Purpose |
|---|
AI_PROVIDER | anthropic, azure, google, mistral, ollama, or openai. |
AI_PROVIDER_MODEL | Model name. |
AI_PROVIDER_OPTIONS / AI_PROVIDER_REQUEST_OPTIONS | Extra JSON-encoded provider/request options. |
CONTEXT_DATA_KEY | Shared AES-GCM key for encrypting/decrypting Context Override data passed to AI Security Rules. |
Threat intelligence
See Threat Intelligence.
| Variable | Default | Purpose |
|---|
THREATS_ENABLED | 1 | Enable/disable threat intelligence. |
THREATS_INDEX_STORE | auto | auto, memory, or sqlite. |
THREATS_MALICIOUS_LIMIT | 10/5m(expire=48h) | Rate limit for malicious-kind threats. |
THREATS_PROBE_LIMIT | 2/5m(expire=48h) | Rate limit for probe-kind threats. |
THREATS_BOT_LIMIT / THREATS_PROXY_LIMIT / THREATS_TOR_LIMIT | (empty) | Same rate-limit syntax, for the bot/proxy/tor kinds. |
Geolocation & risk detection
See Detection Signals and IP Resolvers.
| Variable | Default | Purpose |
|---|
CLOUDFLARE_IP_COUNTRY_ENABLED | (empty) | Use Cloudflare's CF-IPCountry header for geolocation. |
HIGH_RISK_COUNTRIES | (19 country codes, see below) | Country codes flagged high-risk. |
IP_API_COM_TOKEN / IPINFO_IO_TOKEN / IPSTACK_COM_TOKEN | (empty) | API tokens for third-party geolocation providers. |
IPINFO_IO_LITE_ENABLED | (empty) | Use ipinfo.io's Lite API endpoint instead of the standard one. |
IPINFO_IO_MMDB_DOWNLOAD_URL | (empty) | URL to download a local ipinfo.io MMDB database (local mode, instead of per-request API calls). |
IPINFO_IO_MMDB_DOWNLOAD_SCHEDULE | 0 0 * * * | Update schedule (cron) for the local ipinfo.io MMDB database. |
IPINFO_IO_MMDB_DOWNLOAD_HEADERS | (empty) | Extra HTTP headers to send with the MMDB download request. |
MAXMIND_ACCOUNT_ID / MAXMIND_LICENSE_KEY | (empty) | MaxMind GeoIP credentials. |
MAXMIND_DOWNLOAD_URL | GeoLite2-City download URL | Download URL for the MaxMind database. |
MAXMIND_DOWNLOAD_SCHEDULE | 0 0 * * * | Update schedule (cron) for the MaxMind database. |
MAXMIND_DOWNLOAD_HEADERS | (empty) | Extra HTTP headers to send with the MaxMind download request. |
PENALTY_TTL | 30m | How long an accumulated penalty score persists before resetting. |
HIGH_RISK_COUNTRIES defaults to by,cd,cf,cu,il,iq,ir,kp,lb,ly,mm,ng,ru,sd,so,sy,ua,ve,zw.
HIGH_RISK_COUNTRIES_EXCLUDE is deprecated — use HIGH_RISK_COUNTRIES directly instead.
Lists (phishing, disposable email, user agents)
| Variable | Default | Purpose |
|---|
PHISHING_LIST_URL | PhishTank's public feed | Source list for Phishing Detection — see that page for the exact default URL. |
PHISHING_LIST_SCHEDULE | 0 */12 * * * | Update schedule (cron). |
PHISHING_LIST_SIZE_LIMIT | 20MB | Max file size for the downloaded list. |
PHISHING_LIST_MAX_ENTRIES | 100000 | Max entries read from the list. |
EMAIL_LIST_DISPOSABLE | GitHub disposable-email-domains list | Source list of disposable email domains. |
EMAIL_LIST_DISPOSABLE_SCHEDULE | 0 0 * * * | Update schedule (cron). |
EMAIL_LIST_DISPOSABLE_SIZE_LIMIT | 5MB | Max file size for the downloaded list. |
EMAIL_LIST_DISPOSABLE_MAX_ENTRIES | 100000 | Max entries read from the list. |
USER_AGENT_LIST_URL | intoli/user-agents dataset | Source list of known user agents. |
USER_AGENT_LIST_SCHEDULE | 0 0 * * * | Update schedule (cron). |
USER_AGENT_LIST_SIZE_LIMIT | 20MB | Max file size for the downloaded list. |
USER_AGENT_LIST_MAX_ENTRIES | 10000 | Max entries read from the list. |
Rate limiting & proof-of-work
See Rate Limiters.
| Variable | Default | Purpose |
|---|
FLOOD_RATE_LIMIT | 100/1m | Global flood-protection rate limit. Set empty to disable — useful when benchmarking. |
FLOOD_RATE_LIMIT_KEY | ip | Key used for flood-protection rate limiting. |
AUDIO_CHALLENGE_RATE_LIMIT | 10/5m(key=ip&block=10m) | Rate limit for the audio challenge endpoint. |
AUDIO_CHALLENGE_DELAY | 3s | Delay before generating/returning an audio challenge. |
POW_MAX_MEMORY | 128MB | Max memory PoW algorithms may request. |
POW_MAX_THREADS | ~half of hardware concurrency | Max threads for challenge creation/validation. |
Spam handling
| Variable | Default | Purpose |
|---|
DELETE_SPAM_SUBMISSIONS_IN | 14d | Auto-delete spam-flagged submissions after this duration. |
Container resource limits
Covered in Install with Docker and Performance Tuning.
| Variable | Purpose |
|---|
CONTAINER_CPUS | Manual override for available CPU cores (e.g. 2). Auto-detected if unset. |
CONTAINER_MEMORY_LIMIT_MB | Manual override for the memory limit (e.g. 4096). Auto-detected if unset. |
HEAP_LIMIT_MB | Manual override for heap memory — keep lower than CONTAINER_MEMORY_LIMIT_MB. |