Configuration
ZinTrust configuration is driven primarily by environment variables and exposed through the sealed Env namespace (src/config/env.ts) and the config modules in src/config/*.
Project-owned middleware customization lives in config/middleware.ts. That file now supports global, route, and responders, so fresh apps can either replace a built-in middleware key or only reshape its failure payloads. See docs/middleware.md for the responder contract and stable failure reasons.
Overview
- Source of truth:
process.env(or the equivalent in your runtime). - Type-safe access:
Env.get(),Env.getInt(),Env.getBool(). - Defaults: Many values have defaults; some are validated at startup.
Loading .env Files (Node.js)
ZinTrust includes a small .env loader for the CLI and Node tooling (src/cli/utils/EnvFileLoader.ts).
Load order (when present):
.env.env.<mode>(only whenNODE_ENVis set and notproduction; e.g..env.dev).env.local.env.<mode>.local
Notes:
- If
APP_PORTis set butPORTis not, the loader setsPORT=APP_PORT.
If you run the framework via the CLI, or through the standard @zintrust/core/boot Node entrypoint, this is handled for you. If you run a fully custom Node entrypoint, call EnvFileLoader.ensureLoaded() early.
Service Directory Env Loading
When you run a generated microservice from its own service directory with zin s or zin s --wg, ZinTrust now loads env files in two layers:
- project root env files first
- service-directory env files second
That means a generated service can inherit the root app defaults from the project root while still overriding selected values with a service-local .env, .env.local, .env.<mode>, or .env.<mode>.local file.
Example:
- root app at
./.env - service at
./src/services/ecommerce/users/.env
If both define APP_PORT, the service-local value wins for a service-directory start.
The CLI still passes ZINTRUST_PROJECT_ROOT to the runtime so project-owned files such as src/zintrust.runtime.ts, config modules, and other project-relative loaders continue resolving from the application root.
Startup Configuration Validation
During Application.boot(), ZinTrust validates a small set of critical startup configuration using StartupConfigValidator (src/config/StartupConfigValidator.ts).
Currently validated:
NODE_ENV: one ofdevelopment,production,testing,testAPP_PORT: integer in[1, 65535]LOG_FORMAT: one oftext,jsonLOG_LEVEL: one ofdebug,info,warn,errorLOG_ROTATION_SIZE: positive integerLOG_ROTATION_DAYS: positive integer- In
production:APP_KEYmust be set and at least 16 characters
If validation fails, boot throws a structured ConfigError.
Core Application
| Variable | Type | Default | Notes |
|---|---|---|---|
NODE_ENV | string | development | Common values: development, production, testing |
APP_NAME | string | ZinTrust | Used in responses and logs |
APP_KEY | string | "" | Required in production (>= 16 chars) |
APP_PORT | int | 3000 | Exposed as Env.PORT |
PORT | int | 3000 | Used by the standard boot entrypoint, including a thin src/boot/bootstrap.ts that imports @zintrust/core/boot; keep in sync with APP_PORT |
HOST | string | localhost | Bind host |
DEBUG | bool | false | Debug behavior in some modules |
APP_TIMEZONE | string | UTC | Used by src/config/app.ts |
REQUEST_TIMEOUT | int | 30000 | Milliseconds |
MAX_BODY_SIZE | int/string | 10485760 / 10mb | Env.MAX_BODY_SIZE is bytes; appConfig.maxBodySize is a string |
Logging
| Variable | Type | Default | Notes |
|---|---|---|---|
LOG_LEVEL | string | depends on NODE_ENV | prod defaults to info, testing defaults to error, otherwise debug |
LOG_FORMAT | string | text | text or json |
DISABLE_LOGGING | bool | false | Disables log output |
LOG_HTTP_REQUEST | bool | true | Enables HTTP request logging middleware |
LOG_COLOR | string | true | ANSI color output policy: true/always, auto, or false/never |
LOG_COLOR_THEME | string | arctic | Request-log color palette for text logs |
NO_COLOR | string | unset | Disables ANSI colors regardless of LOG_COLOR |
LOG_TO_FILE | bool | false | Enables Node-only file logging |
LOG_ROTATION_SIZE | int | 10485760 | Max bytes before rotating (Node-only) |
LOG_ROTATION_DAYS | int | 7 | Retention window in days (Node-only) |
LOG_CLEANUP_ENABLED | bool | depends on LOG_TO_FILE | Enables scheduled cleanup; defaults to true when LOG_TO_FILE=true |
LOG_CLEANUP_INTERVAL_MS | int | 3600000 | Cleanup schedule interval in ms (Node/Fargate only) |
LOG_MAX_TOTAL_SIZE | int | unset | Optional max total bytes for logs/ before deleting old files |
LOG_KEEP_FILES | int | 0 | Minimum number of recent log files to keep |
SCHEDULE_SHUTDOWN_TIMEOUT_MS | int | 30000 | Max time to wait for schedules to stop during shutdown |
Database
Core DB variables (from Env):
| Variable | Type | Default |
|---|---|---|
DB_CONNECTION | string | sqlite |
DB_HOST | string | localhost |
DB_PORT | int | 5432 |
DB_DATABASE | string | zintrust |
DB_USERNAME | string | postgres |
DB_PASSWORD | string | "" |
DB_READ_HOSTS | string | "" |
Notes:
- For SQLite in development/testing, if
DB_DATABASE/DB_PATHare not set, ZinTrust stores the database file under.zintrust/dbs/zintrust.sqliteby default.
Additional database tuning (from src/config/database.ts):
DB_SSL(bool, defaultfalse)DB_POOLING(bool, defaulttrue)DB_POOL_MIN(int, default5)DB_POOL_MAX(int, default20)DB_IDLE_TIMEOUT(int ms, default30000)DB_CONNECTION_TIMEOUT(int ms, default10000)DB_LOG_LEVEL(string, defaultdebug)DB_MIGRATION_EXT(string, default.ts)
Cache
| Variable | Type | Default | Notes |
|---|---|---|---|
CACHE_DRIVER | string | memory | memory, redis, mongodb, kv |
CACHE_DEFAULT_TTL | int | 3600 | Seconds |
CACHE_KEY_PREFIX | string | zintrust: | Prefix for namespacing |
Driver-specific keys (from src/config/cache.ts):
- Memory:
CACHE_MEMORY_TTL(seconds) - Redis:
REDIS_HOST,REDIS_PORT,CACHE_REDIS_TTL - MongoDB:
MONGO_URI,MONGO_DB,CACHE_MONGO_TTL - KV (Cloudflare Workers):
CACHE_KV_TTL(requires a KV binding namedCACHE)
Queue
From src/config/queue.ts:
QUEUE_DRIVER(defaultsync)QUEUE_TABLE(defaultjobs)QUEUE_DB_CONNECTION(defaultdefault)
Redis:
REDIS_QUEUE_DB(default1)
RabbitMQ:
RABBITMQ_HOST(defaultlocalhost)RABBITMQ_PORT(default5672)RABBITMQ_USER(defaultguest)RABBITMQ_PASSWORD(defaultguest)RABBITMQ_VHOST(default/)
AWS SQS:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SQS_QUEUE_URL
Failed jobs:
FAILED_JOBS_DB_CONNECTION(defaultdefault)FAILED_JOBS_TABLE(defaultfailed_jobs)
Worker controls:
QUEUE_JOB_TIMEOUT(default60)QUEUE_JOB_RETRIES(default3)QUEUE_JOB_BACKOFF(default0)QUEUE_WORKERS(default1)
Microservices
From Env and src/config/microservices.ts:
MICROSERVICES(bool-ish; enables microservices mode)ENABLE_MICROSERVICES(bool; used by some components)SERVICES(comma-separated service list)
Service discovery:
SERVICE_DISCOVERY_TYPE(defaultfilesystem;filesystem,consul,etcd)SERVICES_PATH(defaultservices)SERVICE_DISCOVERY_REFRESH_INTERVAL(default30000)
Registry:
SERVICE_REGISTRY_HOST(defaultlocalhost)SERVICE_REGISTRY_PORT(default8500)SERVICE_DEREGISTER_CRITICAL_AFTER(default30s)
Service auth:
SERVICE_AUTH_STRATEGY(defaultnone;api-key,jwt,none,custom)SERVICE_API_KEYSERVICE_JWT_SECRET
Tracing:
MICROSERVICES_TRACING(defaultfalse)MICROSERVICES_TRACING_RATE(default1.0)TRACING_EXPORT_INTERVAL(default10000)JAEGER_AGENT_HOST(defaultlocalhost)
Isolation:
DATABASE_ISOLATION(defaultshared;sharedorisolated)DATABASE_SCHEMA_PREFIX(defaultmicroservice)
Health checks:
SERVICE_HEALTH_CHECK_ENABLED(defaulttrue)SERVICE_HEALTH_CHECK_INTERVAL(default30000)SERVICE_HEALTH_CHECK_TIMEOUT(default5000)SERVICE_UNHEALTHY_THRESHOLD(default3)SERVICE_HEALTHY_THRESHOLD(default2)
Service calls:
SERVICE_CALL_TIMEOUT(default30000)SERVICE_CALL_RETRIES(default3)SERVICE_CALL_RETRY_DELAY(default1000)
Circuit breaker:
CIRCUIT_BREAKER_ENABLED(defaulttrue)CIRCUIT_BREAKER_THRESHOLD(default5)CIRCUIT_BREAKER_TIMEOUT(default60000)
Service mesh:
SERVICE_MESH_ENABLED(defaultfalse)SERVICE_MESH_TYPE(defaultistio;istioorlinkerd)SERVICE_MESH_NAMESPACE(defaultdefault)
Security
From src/config/security.ts:
JWT:
JWT_ENABLED(defaulttrue)JWT_SECRET(signing key). IfJWT_SECRETis not set the framework will fall back toAPP_KEYfor signing/verification; set an explicitJWT_SECRETin production.JWT_ALGORITHM(defaultHS256)JWT_EXPIRES_IN(default3600seconds)JWT_REFRESH_EXPIRES_IN(default7d)JWT_ISSUER(defaultzintrust)JWT_AUDIENCE(defaultzintrust-api)
JWT revocation (token invalidation):
JWT_REVOCATION_DRIVER(defaultdatabase;database,redis,kv,kv-remote,memory)JWT_REVOCATION_DB_CONNECTION(defaultdefault)JWT_REVOCATION_DB_TABLE(defaultzintrust_jwt_revocations)JWT_REVOCATION_REDIS_DB(default0)JWT_REVOCATION_REDIS_PREFIX(defaultzt:jwt:revoked:)JWT_REVOCATION_KV_BINDING(defaultCACHE)JWT_REVOCATION_KV_PREFIX(defaultzt:jwt:revoked:)
Notes:
- Revocation is checked by the built-in
jwtmiddleware. - Database revocation requires running the core migration that creates
zintrust_jwt_revocations. - The store is keyed by JWT
jtiwhen present; otherwise it falls back to the raw token string.
CSRF:
CSRF_ENABLED(defaulttrue)CSRF_HEADER_NAME(defaultx-csrf-token)CSRF_TOKEN_NAME(default_csrf)CSRF_COOKIE_NAME(defaultXSRF-TOKEN)CSRF_COOKIE_HTTP_ONLY(defaulttrue)CSRF_COOKIE_SECURE(defaulttrue)CSRF_COOKIE_SAME_SITE(defaultstrict;strict,lax,none)CSRF_STORE(default ``)CSRF_DRIVER(default ``)CSRF_REDIS_DB(default ``)
API key:
API_KEY_ENABLED(defaulttrue)API_KEY_HEADER(defaultx-api-key)API_KEY_SECRET
CORS:
CORS_ENABLED(defaulttrue)CORS_ORIGINS(default*)CORS_METHODS(defaultGET,POST,PUT,PATCH,DELETE)CORS_ALLOWED_HEADERS(defaultContent-Type,Authorization)CORS_EXPOSED_HEADERS(default empty)CORS_CREDENTIALS(defaultfalse)CORS_MAX_AGE(default86400)
Rate limiting:
RATE_LIMIT_ENABLED(defaulttrue)RATE_LIMIT_WINDOW_MS(default900000)RATE_LIMIT_MAX_REQUESTS(default100)RATE_LIMIT_MESSAGE(defaultToo many requests, please try again later)
XSS / headers:
XSS_ENABLED(defaulttrue)XSS_REPORT_URIHELMET_ENABLED(defaulttrue)CSP_ENABLED(defaulttrue)HSTS_ENABLED(defaulttrue)HSTS_MAX_AGE(default31536000)HSTS_INCLUDE_SUBDOMAINS(defaulttrue)
Session:
SESSION_NAME(defaultzintrust_session)SESSION_SECRET(defaultyour-session-secret)SESSION_EXPIRES_IN(default1800000)SESSION_SECURE(defaulttrue)SESSION_HTTP_ONLY(defaulttrue)SESSION_SAME_SITE(defaultstrict)
Password policy:
PASSWORD_MIN_LENGTH(default8)PASSWORD_REQUIRE_UPPERCASE(defaulttrue)PASSWORD_REQUIRE_NUMBERS(defaulttrue)PASSWORD_REQUIRE_SPECIAL_CHARS(defaulttrue)BCRYPT_ROUNDS(default10)
Storage
From src/config/storage.ts:
STORAGE_DRIVER(defaultlocal)
Local:
STORAGE_PATH(defaultstorage)STORAGE_URL(default/storage)STORAGE_VISIBILITY(defaultprivate)
AWS S3:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_S3_BUCKETAWS_S3_URLAWS_S3_ENDPOINTAWS_S3_USE_PATH_STYLE_URL(defaultfalse)
GCS:
GCS_PROJECT_IDGCS_KEY_FILEGCS_BUCKETGCS_URL
Temp files / uploads / backups:
TEMP_PATH(defaultstorage/temp)TEMP_FILE_MAX_AGE(default86400)MAX_UPLOAD_SIZE(default100mb)ALLOWED_UPLOAD_MIMES(defaultjpg,jpeg,png,pdf,doc,docx)UPLOADS_PATH(defaultstorage/uploads)BACKUPS_PATH(defaultstorage/backups)BACKUP_DRIVER(defaults3)
Cloudflare
ZinTrust’s Cloudflare support is configured primarily via your Workers bindings (Wrangler binding names) plus a small set of runtime env flags.
Runtime flags:
DB_CONNECTION=d1(use the D1 adapter)DB_CONNECTION=d1-remote(use D1 via the HTTPS proxy service)CACHE_DRIVER=kv(use the KV cache driver)CACHE_DRIVER=kv-remote(use KV via the HTTPS proxy service)
Remote driver configuration:
D1_REMOTE_URLD1_REMOTE_KEY_IDD1_REMOTE_SECRETD1_REMOTE_MODE(defaultregistry;registryorsql)KV_REMOTE_URLKV_REMOTE_KEY_IDKV_REMOTE_SECRETKV_REMOTE_NAMESPACE
Workers binding names (expected defaults):
- D1 binding name:
DB - KV binding name:
CACHE
Legacy/optional env keys:
D1_DATABASE_IDKV_NAMESPACE_ID
These are not required for runtime access in Workers; ZinTrust resolves D1/KV via bindings.
See docs/cloudflare.md for the full setup.
Remote proxy docs:
docs/cloudflare-d1-remote.mddocs/cloudflare-kv-remote.md
Security note:
docs/cloudflare-d1-remote.mdincludes a threat model table explaining what registry mode protects against (and what it does not).
AWS (Runtime)
From Env:
AWS_REGION(defaultus-east-1)AWS_LAMBDA_FUNCTION_NAMEAWS_LAMBDA_FUNCTION_VERSIONAWS_EXECUTION_ENVLAMBDA_TASK_ROOT
Runtime Selection
Some runtime adapters can be selected explicitly:
RUNTIME(used by runtime detection logic)
Examples
Development
NODE_ENV=development
APP_NAME=ZinTrust
APP_PORT=3000
HOST=localhost
LOG_LEVEL=debug
LOG_FORMAT=text
LOG_HTTP_REQUEST=trueProduction
NODE_ENV=production
APP_NAME=ZinTrust
APP_PORT=3000
HOST=0.0.0.0
# Required in production
APP_KEY=your-very-long-secret-key-here
LOG_LEVEL=info
LOG_FORMAT=json
LOG_TO_FILE=true
LOG_ROTATION_SIZE=10485760
LOG_ROTATION_DAYS=7Testing
NODE_ENV=testing
LOG_LEVEL=error
LOG_FORMAT=text
LOG_TO_FILE=false