Skip to main content

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.

Variable expansion

Any variable's value can reference another variable with ${VAR} — useful for composing one value (e.g. a connection string) from a secret or setting defined elsewhere, without repeating it. VAR isn't limited to variables Sentinel itself recognizes — any custom, user-defined variable works too:

DB_PASSWORD=s3cr3t
POSTGRES_URL=postgres://user:${DB_PASSWORD}@localhost:5432/app
  • ${VAR} — the value of VAR, or an empty string if it's unset.
  • ${VAR:-fallback} — the value of VAR, or fallback if it's unset or empty.
  • \${VAR} — the literal text ${VAR}, left un-expanded.

References resolve recursively — a variable's value may itself reference another variable — and a cyclic reference resolves to an empty string rather than erroring.

Required secrets

These are auto-generated on first start if unset (and persisted to .env in the data directory) — or derive them deterministically across a cluster with SECRET_SEED, see Clustering. CONTEXT_DATA_KEY (see AI providers) is auto-generated the same way.

VariableDefaultNotes
ALTCHA_HMAC_SECRETauto-generatedSigns ALTCHA challenges. Minimum 24 characters.
CODE_CHALLENGE_SECRETauto-generatedSigns code challenges. Minimum 24 characters.
JWT_SECRETauto-generatedSigns admin session JWTs. Minimum 24 characters.
EXOTDB_HMAC_SECRETauto-generatedHMAC secret for data signatures (mainly access logs). Minimum 24 characters.
HASHING_SALTauto-generatedSalt used for IP and other hashing.
NODE_IDauto-generatedUnique identifier for this node — see Clustering.
SECRET_SEED(empty)If set, deterministically derives all of the above (except NODE_ID) instead of generating them randomly.

Licensing

See License for how these are used.

VariableDefaultPurpose
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

VariableDefaultPurpose
PORT8080 (Docker image), 3000 otherwisePort the app listens on.
DATA_DIR/data (Docker image), ./data otherwiseDirectory for application data. Relative storage paths below resolve against it.
BASE_URL(empty)Base URL for generating absolute links.
APP_BASE_PATH(empty)Serve the app under a path prefix.
DEFAULT_ACCOUNT_NAMEDefault AccountName of the account created on first setup.
DEFAULT_ROOT_PASSWORDrootInitial root password — change immediately after first login.
NODE_NAME(empty)Human-readable name for this node.
TZsystem timezoneApplication timezone.
USER_AGENTaltcha-sentinel/{version}User-Agent used for Sentinel's own outbound requests. {version} is replaced with VERSION.
API_DOCS_ENABLED1Serve API docs at /v1/docs.
INSPECT_ROUTE_ENABLED1Enable GET /v1/inspect.

Security & access

VariableDefaultPurpose
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/CIDRs allowed to set X-Forwarded-For — see Reverse Proxy. Empty value trusts all.
PASSWORD_LOGIN_ENABLED1Enable/disable password-based login.
PASSWORD_MIN_LENGTH8Minimum admin password length.
JWT_ISSUERALTCHA_SENTINELIssuer identifier used when generating admin session JWTs.
JWT_TTL24hTime-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), used for outbound HTTP, Redis, and database connections.
HTTP2_CERT(empty)TLS certificate (PEM) to terminate HTTPS directly on the container.
HTTP2_KEY(empty)Private key (PEM) for HTTP2_CERT.
ANONYMIZE_IP_ADDRESS1Anonymize IPs generally.
ACCESS_LOG_ANONYMIZE_IP_ADDRESS1Anonymize IPs specifically in access logs.
IP_HEADERS_SECRET(empty)Secret to validate incoming IP-related headers.
HEADER_ENTROPY_MAX_ENTRIES100Max header-combination hashes stored per IP — see Detection Signals.

Networking

VariableDefaultPurpose
HTTP_PROXY(empty)Outbound proxy for Sentinel's own HTTP requests (also used for HTTPS if HTTPS_PROXY is unset).
HTTPS_PROXY(empty)Outbound proxy for Sentinel's own HTTPS requests.
HTTPS_PROXY_REJECT_UNAUTHORIZED1When an outbound proxy is set, reject untrusted TLS certificates from the proxy and from upstream servers. Set 0 to disable certificate verification (e.g. for a TLS-intercepting proxy).
NO_PROXYlocalhost,127.0.0.1,::1,0.0.0.0Hosts that bypass the outbound proxy.

Database

Set one connection-string variable matching your engine — see Databases for examples. If none is set, the embedded default database is used.

VariableDefaultPurpose
POSTGRES_URL(empty)PostgreSQL connection URL.
MYSQL_URL(empty)MySQL connection URL.
MARIADB_URL(empty)MariaDB connection URL.
MSSQL_URL(empty)Microsoft SQL Server connection URL.
ORACLE_URL(empty)Oracle Database connection URL.
LIBSQL_URLBUNNY_DATABASE_URL, if setLibSQL/Turso connection URL.
TURBOLITE_URL(empty)S3 connection string for the Turbolite (S3-backed SQLite) main database.

PostgreSQL

VariableDefaultPurpose
POSTGRES_CONNECT_TIMEOUT10000Connection timeout, ms.
POSTGRES_IDLE_TIMEOUT10000Idle connection timeout, ms (0 disables).
POSTGRES_MAX_CONNECTIONS10Max pool size.
POSTGRES_MIN_CONNECTIONS0Min pool size.
POSTGRES_TLS_CA(empty)TLS CA certificate (PEM contents).
POSTGRES_TLS_CERT(empty)TLS client certificate (PEM contents).
POSTGRES_TLS_KEY(empty)TLS client private key (PEM contents).

POSTGRES_SSL_CA, POSTGRES_SSL_CERT, and POSTGRES_SSL_KEY are deprecated aliases for POSTGRES_TLS_CA, POSTGRES_TLS_CERT, and POSTGRES_TLS_KEY.

MySQL

VariableDefaultPurpose
MYSQL_CONNECT_TIMEOUT10000Connection timeout, ms.
MYSQL_MAX_CONNECTIONS10Max pool size.
MYSQL_TLS_CA(empty)TLS CA certificate (PEM contents).
MYSQL_TLS_CERT(empty)TLS client certificate (PEM contents).
MYSQL_TLS_KEY(empty)TLS client private key (PEM contents).
MYSQL_TLS_REJECT_UNAUTHORIZED1Reject untrusted TLS connections.

MariaDB

VariableDefaultPurpose
MARIADB_CONNECT_TIMEOUT10000Connection timeout, ms.
MARIADB_MAX_CONNECTIONS10Max pool size.
MARIADB_TLS_CA(empty)TLS CA certificate (PEM contents).
MARIADB_TLS_CERT(empty)TLS client certificate (PEM contents).
MARIADB_TLS_KEY(empty)TLS client private key (PEM contents).
MARIADB_TLS_REJECT_UNAUTHORIZED1Reject untrusted TLS connections.

Microsoft SQL Server

VariableDefaultPurpose
MSSQL_CONNECT_TIMEOUT10000Connection timeout, ms.
MSSQL_MAX_CONNECTIONS10Max pool size.
MSSQL_TLS_CA(empty)TLS CA certificate (PEM contents).
MSSQL_TLS_CERT(empty)TLS client certificate (PEM contents).
MSSQL_TLS_KEY(empty)TLS client private key (PEM contents).
MSSQL_TLS_REJECT_UNAUTHORIZED1Reject untrusted TLS connections.

Oracle

VariableDefaultPurpose
ORACLE_CONNECT_TIMEOUT10000Connection timeout, ms.
ORACLE_MAX_CONNECTIONS10Max pool size.
ORACLE_TLS_CA(empty)Wallet CA certificate (PEM contents). For AWS RDS hosts, the bundled AWS global CA is used if unset.
ORACLE_TLS_REJECT_UNAUTHORIZED1Reject untrusted TLS connections.

LibSQL

VariableDefaultPurpose
LIBSQL_AUTH_TOKENBUNNY_DATABASE_AUTH_TOKEN, if setAuth token for the LibSQL/Turso database.
LIBSQL_MAX_CONNECTIONS10Max number of open connections.

Turbolite

These configure S3-based leader election for Turbolite, used by the embedded database and KV store to run across multiple nodes (e.g. with TURBOLITE_URL / EXOTDB_REDIS_STORAGE=turbolite).

VariableDefaultPurpose
CLUSTER_ELECTOR_S3_URL(empty, disabled)S3 URL for storing the leader lease, e.g. https://ACCESS_KEY_ID:SECRET_ACCESS_KEY@s3.eu-west-1.amazonaws.com/prefix?bucket=my-bucket. Credentials fall back to AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY, region to the region URL parameter, then the hostname, then AWS_REGION.
CLUSTER_ADVERTISE_HTTP_ADDRhttp://{hostname}:{EXOTDB_DATABASE_ADDR port}Address other nodes use to reach this node's embedded database when it's the leader.
CLUSTER_ADVERTISE_REDIS_ADDRredis://{hostname}:{EXOTDB_REDIS_ADDR port}Address other nodes use to reach this node's embedded KV store when it's the leader.

Embedded database

VariableDefaultPurpose
EXOTDB_DATABASE_ADDR:::4080Address the embedded database server binds to.
EXOTDB_DATABASE_LOCATION./db/altcha-sentinel.dbDatabase file path, relative to DATA_DIR.
EXOTDB_ROOT_PASSWORDrootRoot password for the embedded database.
EXOTDB_ENCRYPTION_KEY(empty)Encryption key for the embedded database and KV store files. Optional, not generally recommended.
DATABASE_URLhttp://root:root@localhost:4080?bootstrap=1Connection URL Sentinel uses internally to reach the embedded server — you don't need to set it unless you're customizing the embedded setup directly.

KV store (Redis)

See Databases for enabling an external instance.

VariableDefaultPurpose
REDIS_URLredis://root:root@localhost:6389Redis/Valkey connection URL. Leaving the default starts and uses the embedded KV store; any other value connects to an external instance.
REDIS_CLUSTER_URL(empty)Redis Cluster: a comma-separated list of node URLs, or a single cluster-configuration URL. Takes precedence over REDIS_URL. Use rediss:// for TLS.
REDIS_COMMAND_TIMEOUT5000Command timeout, ms.
REDIS_CONNECT_TIMEOUT10000Connection timeout, ms.
REDIS_MAX_RETRIES2Max 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(empty)Auth for the Redis Sentinel endpoints.
REDIS_SENTINEL_REDIS_AUTH(empty)Auth for the Redis nodes behind Redis Sentinel.
REDIS_SENTINEL_TLS0Enable TLS to the Redis Sentinel endpoints.
REDIS_SENTINEL_REDIS_TLS0Enable TLS to the Redis nodes behind Redis Sentinel.

Embedded KV store

VariableDefaultPurpose
EXOTDB_REDIS_ADDR:::6389Address the embedded KV store binds to.
EXOTDB_REDIS_STORAGElocalStorage backend: local (SQLite file), memory (non-persistent), or turbolite (S3-backed, supports clustering).
EXOTDB_REDIS_LOCATION./db/redis.dbKV store file path, relative to DATA_DIR (local storage).
TURBOLITE_REDIS_URL(empty)S3 connection string for the turbolite storage backend. Required when EXOTDB_REDIS_STORAGE=turbolite.

Snapshots

See Backups & Recovery for how these fit together.

VariableDefaultPurpose
SNAPSHOTS_ENABLED1Enable/disable the snapshots feature.
SNAPSHOTS_MAIN_SCHEDULE(empty, disabled)Cron schedule for automatic main-database snapshots.
SNAPSHOTS_REDIS_SCHEDULE(empty, disabled)Cron schedule for automatic Redis snapshots.
SNAPSHOTS_KEY_PREFIXaltcha-sentinel-snapshotsPath prefix for stored snapshots.
SNAPSHOTS_AGE_PUBLIC_KEY(empty)age public key (recipient) used to encrypt snapshots. Encrypted snapshots get an .age extension.
SNAPSHOTS_AGE_SECRET_KEY(empty)age secret key (identity) used to decrypt snapshots on restore. If unset while SNAPSHOTS_AGE_PUBLIC_KEY is set, the key must be entered when restoring.
SNAPSHOTS_STORAGE_PROVIDERlocallocal, s3, or azure.
SNAPSHOTS_STORAGE_LOCAL_DIRbackupsLocal directory, relative to DATA_DIR, 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(empty)Azure Blob Storage container name.
SNAPSHOTS_STORAGE_AZURE_CONNECTION_STRING(empty)Azure Blob Storage connection string.

File storage

See Storage Providers for details.

VariableDefaultPurpose
STORAGE_PROVIDERlocallocal, s3, or azure.
STORAGE_LOCAL_DIRstorageLocal directory, relative to DATA_DIR, if using the local provider.
STORAGE_S3_URL(empty)S3 (or S3-compatible, e.g. MinIO) URL, e.g. https://s3.eu-west-1.amazonaws.com/?bucket=my-bucket&prefix=uploads. Takes precedence over the discrete STORAGE_S3_* variables below.
STORAGE_S3_BUCKET(empty)S3 bucket name.
STORAGE_S3_ACCESS_KEY_IDAWS_ACCESS_KEY_ID, if setS3 access key ID.
STORAGE_S3_SECRET_ACCESS_KEYAWS_SECRET_ACCESS_KEY, if setS3 secret access key.
STORAGE_S3_REGIONAWS_REGION, if setS3 region.
STORAGE_S3_ENDPOINT(empty)S3 endpoint URL (for S3-compatible services).
STORAGE_AZURE_CONTAINER(empty)Azure Blob Storage container name.
STORAGE_AZURE_CONNECTION_STRING(empty)Azure Blob Storage connection string.

Caching

VariableDefaultPurpose
CACHE_DURATION_API_KEYS10sHow long API keys are cached before refresh.
CACHE_DURATION_TRAINING_DATA1hHow long training data is cached before refresh.
CACHE_DURATION_USED_CHALLENGES4hHow long used-challenge records are cached, to prevent reuse.

Logging

VariableDefaultPurpose
LOG_LEVELinfotrace, debug, info, warn, error, fatal, silent.
LOG_FORMATjsonjson or plain.
REQUEST_LOGS_TTL72hHow long request logs are retained.
ACCESS_LOG_ENABLED1Enable/disable access logging.

Monitoring

See Monitoring & Logging.

VariableDefaultPurpose
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)

VariableDefaultPurpose
OTEL_EXPORTER_OTLP_ENDPOINT(empty)OTLP collector URL.
OTEL_SERVICE_NAMEaltcha-sentinelService name in traces/logs.
OTEL_EXPORTER_OTLP_HEADERS(empty)Extra headers for OTLP requests (e.g. auth).
OTEL_EXPORTER_OTLP_TIMEOUT10000Timeout, ms.

ClickHouse (Enterprise)

See ClickHouse for the table schema and full setup.

VariableDefaultPurpose
CLICKHOUSE_URL(empty)e.g. http://user:password@localhost:8123/db_name.
CLICKHOUSE_BATCH_INTERVAL1000Max ms before flushing the batch buffer.
CLICKHOUSE_BATCH_MAX100Max entries before flushing.
CLICKHOUSE_TLS_CA(empty)TLS CA certificate (PEM contents).
CLICKHOUSE_TLS_CERT(empty)TLS client certificate (PEM contents).
CLICKHOUSE_TLS_KEY(empty)TLS client private key (PEM contents).

SSO (Enterprise)

See SSO.

VariablePurpose
SSO_AZUREAzure (Entra ID) OIDC configuration.
SSO_GOOGLEGoogle OIDC configuration.
SSO_KEYCLOAKKeycloak OIDC configuration.
SSO_OKTAOkta OIDC configuration.
SSO_LDAPLDAP configuration.
SSO_LDAP_TLS_CALDAP TLS CA certificate (PEM contents).
SSO_LDAP_TLS_CERTLDAP TLS client certificate (PEM contents).
SSO_LDAP_TLS_KEYLDAP TLS client private key (PEM contents).

SSO_LDAP_SSL_CA, SSO_LDAP_SSL_CERT, and SSO_LDAP_SSL_KEY are deprecated aliases for SSO_LDAP_TLS_CA, SSO_LDAP_TLS_CERT, and SSO_LDAP_TLS_KEY.

Email / SMTP

VariableDefaultPurpose
SMTP_URL(empty)SMTP connection URL for outgoing email — see Forms.
EML_BODY_LIMIT5MBMax body size for POST /v1/eml.

AI providers

See AI Providers.

VariablePurpose
AI_PROVIDERanthropic, azure, google, mistral, ollama, or openai.
AI_PROVIDER_MODELModel name.
AI_PROVIDER_OPTIONSExtra JSON-encoded provider options (e.g. baseURL, apiKey).
AI_PROVIDER_REQUEST_OPTIONSExtra JSON-encoded parameters passed with each API request.
CONTEXT_DATA_KEYShared AES-GCM key for encrypting/decrypting Context Override data passed to AI Security Rules. Auto-generated if unset, like the required secrets.

Threat intelligence

See Threat Intelligence.

VariableDefaultPurpose
THREATS_ENABLED1Enable/disable threat intelligence.
THREATS_INDEX_STOREautoauto, memory, or sqlite.
THREATS_MALICIOUS_LIMIT10/5m(expire=48h)Rate limit for malicious-kind threats.
THREATS_PROBE_LIMIT2/5m(expire=48h)Rate limit for probe-kind threats.
THREATS_BOT_LIMIT(empty)Rate limit for bot-kind threats, same syntax.
THREATS_PROXY_LIMIT(empty)Rate limit for proxy-kind threats, same syntax.
THREATS_TOR_LIMIT(empty)Rate limit for tor-kind threats, same syntax.

Geolocation & risk detection

See Detection Signals and IP Resolvers.

VariableDefaultPurpose
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(empty)API token for ip-api.com.
IPINFO_IO_TOKEN(empty)API token for ipinfo.io.
IPSTACK_COM_TOKEN(empty)API token for ipstack.com.
IPINFO_IO_LITE_ENABLED1Use 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_SCHEDULE0 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(empty)MaxMind account ID for GeoIP database downloads.
MAXMIND_LICENSE_KEY(empty)MaxMind license key for GeoIP database downloads.
MAXMIND_DOWNLOAD_URLGeoLite2-City download URLDownload URL for the MaxMind database.
MAXMIND_DOWNLOAD_SCHEDULE0 0 * * *Update schedule (cron) for the MaxMind database.
MAXMIND_DOWNLOAD_HEADERS(empty)Extra HTTP headers to send with the MaxMind download request.
PENALTY_TTL30mHow long an accumulated penalty score persists before resetting.
HIGH_RISK_COUNTRIES_EXCLUDE(empty)Deprecated — edit HIGH_RISK_COUNTRIES directly instead. Comma-separated country codes never flagged high-risk.

HIGH_RISK_COUNTRIES defaults to by,cd,cf,cu,il,iq,ir,kp,lb,ly,mm,ng,ru,sd,so,sy,ua,ve,zw.

Lists (phishing, disposable email, user agents)

VariableDefaultPurpose
PHISHING_LIST_URLPhishTank's public feedSource list for Phishing Detection — see that page for the exact default URL.
PHISHING_LIST_SCHEDULE0 */12 * * *Update schedule (cron).
PHISHING_LIST_SIZE_LIMIT20MBMax file size for the downloaded list.
PHISHING_LIST_MAX_ENTRIES100000Max entries read from the list.
EMAIL_LIST_DISPOSABLEGitHub disposable-email-domains listSource list of disposable email domains.
EMAIL_LIST_DISPOSABLE_SCHEDULE0 0 * * *Update schedule (cron).
EMAIL_LIST_DISPOSABLE_SIZE_LIMIT5MBMax file size for the downloaded list.
EMAIL_LIST_DISPOSABLE_MAX_ENTRIES100000Max entries read from the list.
USER_AGENT_LIST_URLintoli/user-agents datasetSource list of known user agents.
USER_AGENT_LIST_SCHEDULE0 0 * * *Update schedule (cron).
USER_AGENT_LIST_SIZE_LIMIT20MBMax file size for the downloaded list.
USER_AGENT_LIST_MAX_ENTRIES10000Max entries read from the list.

Rate limiting & proof-of-work

See Rate Limiters.

VariableDefaultPurpose
FLOOD_RATE_LIMIT100/1mGlobal flood-protection rate limit. Set empty to disable — useful when benchmarking.
FLOOD_RATE_LIMIT_KEYipKey used for flood-protection rate limiting.
AUDIO_CHALLENGE_RATE_LIMIT10/5m(key=ip&block=10m)Rate limit for the audio challenge endpoint.
AUDIO_CHALLENGE_DELAY3sDelay before generating/returning an audio challenge.
POW_MAX_MEMORY128MBMax memory PoW algorithms may request.
POW_MAX_THREADS~half of hardware concurrencyMax threads for challenge creation/validation.

Spam handling

VariableDefaultPurpose
DELETE_SPAM_SUBMISSIONS_IN14dAuto-delete spam-flagged submissions after this duration.

Container resource limits

Covered in Install with Docker and Performance Tuning.

VariablePurpose
CONTAINER_CPUSManual override for available CPU cores (e.g. 2). Auto-detected if unset.
CONTAINER_MEMORY_LIMIT_MBManual override for the memory limit (e.g. 4096). Auto-detected if unset.
HEAP_LIMIT_MBManual override for heap memory — keep lower than CONTAINER_MEMORY_LIMIT_MB.

Start typing to search...

↑ ↓ Navigate ↵ Select