Skip to content

Environment variables

All env vars are prefixed Z4J_ (brain-side) or read from the Z4J dict in framework settings (agent-side). Brain settings map onto fields in z4j_brain.settings.Settings; the prefix is dropped and the name lowercased (e.g. Z4J_EVENT_RETENTION_DAYS -> settings.event_retention_days).

This page lists every Z4J_* variable the brain reads. Most operators set only the required four plus a handful from the Database, Retention, and Metrics sections; the rest are exposed for fine-tuning under sustained load or unusual deployments.

Variable Description
Z4J_DATABASE_URL PostgreSQL connection string (postgresql+asyncpg://user:pw@host/db).
Z4J_SECRET Master HMAC signing key. Drives the per-project frame HMAC, the audit-log row HMAC, and the session-cookie signer’s master derivation. 64 hex chars recommended.
Z4J_SESSION_SECRET Independent secret for user-session cookies. Rotating it invalidates active sessions.
Z4J_PUBLIC_URL Full externally reachable base URL with scheme (https://z4j.example.com). Validated: no whitespace, no userinfo, http(s) only.
Variable Default Description
Z4J_PREVIOUS_SECRETS - Comma-separated previous Z4J_SECRET values still accepted while verifying older audit rows / frames during rotation. Writes always use the new Z4J_SECRET. Empty = no rotation in progress.
Z4J_PREVIOUS_SESSION_SECRETS - Comma-separated previous session secrets still accepted while verifying older cookies during rotation.
Variable Default Description
Z4J_DATABASE_STATEMENT_CACHE_SIZE 50 Per-connection asyncpg prepared-statement cache cap. 0 disables. See Brain memory tuning.
Z4J_DATABASE_MAX_INACTIVE_CONNECTION_LIFETIME_SECONDS 60 Seconds before an idle asyncpg connection is closed and reopened. Maps to SQLAlchemy’s pool_recycle.
Z4J_AUTO_MIGRATE true Run Alembic head migrations on brain boot. Set to false for orchestrators that run migrations as a separate step.
Z4J_REQUIRE_DB_SSL true Refuse Postgres URLs that disable SSL (auto-relaxed when the URL points at a loopback host).
Z4J_DB_STATEMENT_TIMEOUT_MS 10000 Postgres statement_timeout (milliseconds). Caps any single query.
Z4J_DB_LOCK_TIMEOUT_MS 3000 Postgres lock_timeout (milliseconds). Caps how long a transaction waits for a row lock.
Z4J_DB_IDLE_IN_TX_TIMEOUT_MS 30000 Postgres idle_in_transaction_session_timeout (milliseconds).
Z4J_ASYNCPG_CONNECT_TIMEOUT 10.0 Seconds before an asyncpg connect attempt times out.
Z4J_ASYNCPG_CLOSE_TIMEOUT 5.0 Seconds before an asyncpg close call times out.
Z4J_WAL_CHECKPOINT_INTERVAL_SECONDS 300 SQLite-only PRAGMA wal_checkpoint(TRUNCATE) cadence. Ignored on Postgres.
Variable Default Description
Z4J_PASSWORD_MIN_LENGTH 8 Minimum password length.
Z4J_ARGON2_TIME_COST 3 argon2id time cost.
Z4J_ARGON2_MEMORY_COST 65536 argon2id memory (KiB, 64 MiB default).
Z4J_ARGON2_PARALLELISM 4 argon2id threads.
Variable Default Description
Z4J_SESSION_ABSOLUTE_LIFETIME_SECONDS 604800 Hard cap on a session’s age (default 7 days). Sessions are rejected past this regardless of activity.
Z4J_SESSION_IDLE_TIMEOUT_SECONDS 1800 Sliding idle timeout (default 30 minutes). Sessions whose last_seen_at is older than this are rejected.
Z4J_SESSION_COOKIE_SAMESITE lax SameSite attribute on the session cookie. lax or strict.
Z4J_SESSION_PIN_USER_AGENT false If true, the resolved client User-Agent at session issue time is enforced on every subsequent request. Off by default; too many false positives on mobile networks.
Z4J_LOGIN_LOCKOUT_THRESHOLD 10 Failed login attempts on a single account before lockout.
Z4J_LOGIN_LOCKOUT_DURATION_SECONDS 900 Lockout duration after threshold exceeded.
Z4J_LOGIN_BACKOFF_BASE_SECONDS 0.5 Base per-failure backoff applied to the login response.
Z4J_LOGIN_BACKOFF_MAX_SECONDS 5.0 Cap on the per-failure backoff.
Z4J_LOGIN_MIN_DURATION_MS 300 Minimum total response time for /auth/login (success or failure). Held by asyncio.sleep so timing variance cannot leak whether the account exists.
Z4J_LOG_LOGIN_EMAIL false Log the attempted email on failed logins. Off by default (PII consideration).
Variable Default Description
Z4J_RECONCILIATION_SWEEP_SECONDS 300 Seconds between reconciliation passes that compare in-flight tasks against engine result backends.
Z4J_RECONCILIATION_STALE_THRESHOLD_SECONDS 900 Minimum age before a task in started state becomes eligible for reconciliation.
Variable Default Description
Z4J_EVENT_RETENTION_DAYS 30 Days raw events rows live before the retention worker drops their partition.
Z4J_AUDIT_RETENTION_DAYS 90 Days audit_log rows live before the retention worker prunes them.
Z4J_AUDIT_RETENTION_SWEEP_INTERVAL_SECONDS 3600 Seconds between audit retention sweeps (default 1 hour).
Z4J_AUDIT_RETENTION_SWEEP_BATCH_SIZE 5000 Rows pruned per database round-trip inside one sweep pass.
Z4J_AUDIT_RETENTION_SWEEP_MAX_PER_PASS 200000 Hard cap on rows deleted in a single sweep pass. Sweeps stop and resume on the next interval if the cap is hit.
Variable Default Description
Z4J_METRICS_AUTH_TOKEN - (auto-minted) Bearer token required by /metrics. Operators may provide one explicitly via env or ~/.z4j/secret.env; if absent and Z4J_METRICS_PUBLIC is unset, z4j serve auto-mints one and writes it to ~/.z4j/secret.env. Run z4j metrics-token to print or rotate.
Z4J_METRICS_PUBLIC false Set to 1 to leave /metrics open. Use only when the endpoint is firewalled or behind an authenticated proxy.
Z4J_METRICS_ENABLED true Set to false to skip mounting the /metrics route entirely (very rare; use the auth-token instead).
Variable Default Description
Z4J_BOOTSTRAP_ADMIN_EMAIL - Skip the first-boot setup URL and auto-provision an admin with this email. Read once at boot.
Z4J_BOOTSTRAP_ADMIN_PASSWORD - Required when Z4J_BOOTSTRAP_ADMIN_EMAIL is set. Eagerly popped from os.environ after use.
Z4J_FIRST_BOOT_TOKEN_TTL_SECONDS 900 Validity window for the one-time setup token (default 15 minutes).
Z4J_FIRST_BOOT_ATTEMPTS_PER_IP 30 Sliding-window cap on setup-token verification attempts per IP per 15 minutes.
Variable Default Description
Z4J_MFA_ENFORCE_FOR_ADMINS false Require MFA enrollment for every user with the global is_admin bit. Past the grace window their sessions are restricted to the enrollment flow.
Z4J_MFA_ENFORCE_FOR_ALL false Same for every user. Stricter superset of the admins-only flag.
Z4J_MFA_ENROLLMENT_GRACE_DAYS 7 Days an enforcement-targeted user has to enroll once their grace clock starts. Range 0..90; 0 restricts from the first post-policy login.
Z4J_MFA_RECOVERY_CODE_COUNT 10 Single-use recovery codes minted at enrollment. Range 5..50.
Z4J_MFA_VERIFICATION_TTL_SECONDS 3600 How long a successful MFA verify counts as fresh for the sensitive-action gate (default 60 min).
Z4J_MFA_REMEMBER_DEVICE_DAYS 30 Lifetime of the z4j_mfa_trust “remember this device” cookie. Hard upper bound 90.
Z4J_MFA_VERIFICATION_RATE_PER_MIN 10 Per-IP cap on /auth/mfa/verify attempts per minute. Tighter than login because the endpoint is a TOTP brute-force target.
Z4J_MFA_TRUSTED_DEVICES_MAX_PER_USER 20 Cap on active trusted-device rows per user. At the cap, the oldest active row is revoked to make room.

See Multi-factor authentication for the full design + threat model, and MFA enforcement for the enforcement policy semantics.

Variable Default Description
Z4J_NOTIFICATIONS_WEBHOOK_ALLOW_HTTP false Allow http:// webhook URLs. Default refuses plaintext at both config-validation and dispatch time.
Variable Default Description
Z4J_AGENT_OFFLINE_TIMEOUT_SECONDS 30 Heartbeats older than this mark the agent offline in the dashboard.
Z4J_AGENT_OFFLINE_ALERT_GRACE_SECONDS 60 Extra silence past the offline timeout before the outage is confirmed and alerted (audit row + worker.offline rules + agent.offline subscriptions). See agent offline alerts.
Z4J_AGENT_HEALTH_SWEEP_SECONDS 10 Cadence for the agent health-check sweep.
Z4J_AGENT_STALE_PRUNE_DAYS 30 Agents offline for longer than this are pruned from the dashboard listings. The agent row is soft-removed; audit references keep their FK.
Variable Default Description
Z4J_WS_IDLE_TIMEOUT_SECONDS 90 Per-connection idle timeout for /ws (agent) and /ws/dashboard.
Z4J_WS_INGEST_QUEUE_MAXSIZE 2000 Bounded per-connection ingest queue. Decouples app-level frame dispatch from the WS recv loop so PING/PONG keeps flowing.
Z4J_WS_MAX_FRAME_BYTES 1048576 Maximum inbound WebSocket frame size (1 MiB).
Z4J_WS_PER_AGENT_CONCURRENCY_CAP 64 Maximum concurrent worker connections per agent_id (worker-first protocol).

The brain’s BrainRegistry routes commands to agent connections across replicas. The default postgres_notify backend uses Postgres LISTEN/NOTIFY; SQLite forces local automatically.

Variable Default Description
Z4J_REGISTRY_BACKEND postgres_notify postgres_notify or local. SQLite forces local.
Z4J_REGISTRY_LISTENER_HEARTBEAT_SECONDS 10 Self-NOTIFY heartbeat for the watchdog on the LISTEN connection.
Z4J_REGISTRY_LISTENER_HEARTBEAT_TIMEOUT_SECONDS 25 Timeout before the watchdog reconnects the LISTEN connection.
Z4J_REGISTRY_LISTENER_MAX_AGE_SECONDS 900 Hard-recycle interval for the LISTEN connection.
Z4J_REGISTRY_RECONCILE_INTERVAL_SECONDS 30 Poll cadence for pending commands targeting an agent this replica owns.

These are app-level caps; the per-endpoint per-IP buckets in authentication and rate-limits layer on top.

Variable Default Description
Z4J_MAX_PAYLOAD_SIZE_BYTES 8192 Maximum REST request body size. Larger requests return 413.
Z4J_TASKS_EXPORT_MAX_ROWS 50000 Upper bound on rows fetched by task / audit export endpoints. Beyond this, the call returns a validation error pointing operators at narrower filters.
Z4J_RATELIMIT_COMMANDS_PER_MINUTE 100 Per-project upper bound on command issuance.
Z4J_RATELIMIT_EVENTS_PER_SECOND 10000 Per-project upper bound on event ingestion.
Z4J_ADMIN_PROJECT_LIST_CAP 500 Upper bound on admin project-listing endpoints.
Z4J_REQUEST_TIMEOUT_SECONDS 30 Per-request handler wall-clock budget.
Z4J_REST_DEFAULT_PAGE_SIZE 50 Default page size on REST list endpoints.
Z4J_REST_MAX_PAGE_SIZE 500 Maximum page size on REST list endpoints.
Variable Default Description
Z4J_ALLOWED_HOSTS [] Host-header allow-list. Production deployments must populate this. Use z4j allowed-hosts add for live management. See allowed hosts.
Z4J_CORS_ORIGINS [] Allowed CORS origins for the dashboard. JSON array of full origins.
Z4J_CORS_ALLOW_CREDENTIALS true Allow credentials on CORS requests.
Z4J_TRUSTED_PROXIES [] CIDR list of reverse-proxy IPs whose X-Forwarded-For the brain should trust. Empty list means trust no proxy.
Z4J_HSTS_MAX_AGE_SECONDS 31536000 HSTS max-age (default 1 year). Emitted only in production over HTTPS.
Z4J_HSTS_INCLUDE_SUBDOMAINS true Append includeSubDomains to the HSTS header.
Z4J_ALLOW_HTTP_PUBLIC_URL false Test/dev escape hatch: permit a plaintext http:// Z4J_PUBLIC_URL. Never set in production.
Variable Default Description
Z4J_BIND_HOST 0.0.0.0 ASGI bind host.
Z4J_BIND_PORT 7700 ASGI bind port.
Z4J_ENVIRONMENT production Free-form environment label surfaced in logs and on the dashboard. Affects nothing else.
Z4J_LOG_JSON true Emit logs as JSON (true) or human-readable console output (false).
Z4J_LOG_LEVEL INFO Stdlib logging level.
Z4J_VERSION_CHECK_URL (canonical GitHub raw URL) Source URL for the dashboard “Check for updates” button. Override to point at a private mirror in restricted environments.
Variable Default Description
Z4J_COMMAND_TIMEOUT_SECONDS 60 Age threshold past which a dispatched command is marked timed-out. Surfaces as 504 command_timeout to API callers.
Z4J_COMMAND_TIMEOUT_SWEEP_SECONDS 5 Cadence for the command-timeout sweeper worker.

The brain accepts mTLS gRPC connections from z4j-scheduler instances. Disabled by default.

Variable Default Description
Z4J_SCHEDULER_GRPC_ENABLED false Accept mTLS gRPC connections from z4j-scheduler.
Z4J_SCHEDULER_GRPC_BIND_HOST 0.0.0.0 Bind interface for the scheduler gRPC server.
Z4J_SCHEDULER_GRPC_BIND_PORT 7701 Bind port for the scheduler gRPC server.
Z4J_SCHEDULER_GRPC_ALLOWED_CNS [] JSON array of allow-listed scheduler client CNs.
Z4J_SCHEDULER_GRPC_REQUIRE_ALLOWLIST false Fail closed if _ALLOWED_CNS is missing instead of falling back to trust-the-CA.
Z4J_SCHEDULER_GRPC_CN_PROJECT_BINDINGS {} JSON object mapping scheduler CN to allowed project list.
Z4J_SCHEDULER_GRPC_TLS_CERT - Brain’s gRPC server certificate (PEM path).
Z4J_SCHEDULER_GRPC_TLS_KEY - Brain’s gRPC server private key (PEM path).
Z4J_SCHEDULER_GRPC_TLS_CA - CA bundle for validating incoming scheduler client certs.
Z4J_SCHEDULER_GRPC_INSECURE false Dev/test only: bind the scheduler gRPC port without TLS. Refuses to start in production.
Z4J_SCHEDULER_GRPC_GRACE_SECONDS 5.0 Graceful drain window on shutdown for in-flight RPCs.
Z4J_SCHEDULER_GRPC_FIRE_RATE_LIMIT_ENABLED true Enable the per-cert rate limit on FireSchedule.
Z4J_SCHEDULER_GRPC_FIRE_RATE_PER_SECOND 10.0 Sustained refill rate (tokens / sec) for the per-cert fire-rate limit.
Z4J_SCHEDULER_GRPC_FIRE_RATE_CAPACITY 600.0 Maximum burst size for the per-cert fire-rate limit.
Z4J_SCHEDULER_GRPC_WATCH_MAX_CONCURRENT 64 Hard cap on concurrent WatchSchedules streams per brain process.
Z4J_SCHEDULER_GRPC_WATCH_MAX_PER_CERT 4 Per-CN cap on concurrent WatchSchedules streams.
Z4J_SCHEDULER_GRPC_WATCH_POLL_SECONDS 2.0 Poll cadence for the watch-stream backend.
Z4J_SCHEDULER_INFO_URLS [] HTTP URLs of scheduler instances for the dashboard’s fleet-status page.

When the brain needs to push a schedule trigger to z4j-scheduler, it dials an outbound gRPC channel. Without Z4J_SCHEDULER_TRIGGER_URL set, the brain falls back to its in-process scheduler path and the TLS variables are ignored.

Variable Default Description
Z4J_SCHEDULER_TRIGGER_URL - host:port of the scheduler’s TriggerSchedule listener.
Z4J_SCHEDULER_TRIGGER_TLS_CERT - Path to the brain’s client certificate.
Z4J_SCHEDULER_TRIGGER_TLS_KEY - Path to the brain’s client key.
Z4J_SCHEDULER_TRIGGER_TLS_CA - Path to the CA bundle the brain uses to verify the scheduler’s server cert.

For homelab / single-instance deployments the brain can spawn z4j-scheduler as a supervised subprocess. See z4j-scheduler.

Variable Default Description
Z4J_EMBEDDED_SCHEDULER false Spawn z4j-scheduler as a supervised subprocess inside the brain lifespan.
Z4J_EMBEDDED_SCHEDULER_ARGV ["serve"] Subprocess argv after the implicit [sys.executable, "-m", "z4j_scheduler"] prefix.
Z4J_EMBEDDED_SCHEDULER_PKI_DIR ~/.z4j/embedded-pki/ Directory for auto-minted loopback mTLS PKI.
Z4J_EMBEDDED_SCHEDULER_RESTART_MAX_ATTEMPTS 10 Maximum auto-restart attempts before the supervisor gives up.
Z4J_EMBEDDED_SCHEDULER_RESTART_BACKOFF_SECONDS 2.0 Initial backoff between restart attempts (doubles up to a 60s cap).
Z4J_EMBEDDED_SCHEDULER_SHUTDOWN_GRACE_SECONDS 10.0 Grace window for SIGTERM before the supervisor sends SIGKILL.

Schedule fires, misfires, and circuit breaker

Section titled “Schedule fires, misfires, and circuit breaker”
Variable Default Description
Z4J_SCHEDULE_FIRES_RETENTION_DAYS 30 Days schedule_fires rows live. Postgres reclaims expired days by partition drop; SQLite by DELETE. See schedule fire history.
Z4J_PENDING_FIRES_RETENTION_DAYS 7 Days buffered fires can stay pending before being dropped.
Z4J_PENDING_FIRES_REPLAY_INTERVAL_SECONDS 10 Cadence for the buffered-fire replay worker.
Z4J_SCHEDULE_CIRCUIT_BREAKER_THRESHOLD 5 Consecutive failed fires before the schedule is auto-disabled. 0 disables the breaker.
Z4J_SCHEDULE_CIRCUIT_BREAKER_INTERVAL_SECONDS 60 Sweep cadence for the schedule circuit-breaker worker.
Z4J_SCHEDULER_MISFIRE_GRACE_SECONDS 60 Lateness past a schedule’s expected fire before it counts as misfired. See misfire detection.
Z4J_SCHEDULER_MISFIRE_SWEEP_SECONDS 60 Cadence for the brain-side misfire detector. 0 disables misfire detection.
Variable Default Description
Z4J_AUTOMATION_NOTIFY_COALESCE_SECONDS 0 When > 0, a rule that already emitted a notify within the window suppresses further notifies, so an event flood cannot fan out one notification per event per member. The first alert in each window always goes out. 0 notifies on every matching event.
Z4J_AUTOMATION_OUTBOX_DRAIN_INTERVAL_SECONDS 30 Cadence for the firing-outbox drain worker that replays automation firings deferred under backpressure.
Z4J_AUTOMATION_OUTBOX_MAX_ROWS_PER_PROJECT 10000 Per-project ceiling on deferred firings; above it, further firings are dropped (counted on a metric) rather than growing the outbox without bound.

The following fields exist on Settings but are infrastructure or test-only and should not be set by operators:

  • Z4J_DASHBOARD_DIST – filesystem path to built dashboard assets (set by the container image).
  • Z4J_DISABLE_SPA_FALLBACK – unit-test fixture flag.

Set in your framework’s config dict (e.g. Django settings.Z4J) or as the matching Z4J_* env var:

Key Required Default Description
brain_url yes - WebSocket URL of z4j
token yes - Agent bearer token
hmac_secret yes - Per-project HMAC secret returned at agent-mint time
project_id no "default" Project slug
agent_name no $HOSTNAME Display name
buffer_size no 1000 Event buffer cap
heartbeat_interval no 10 Seconds between heartbeats
reconnect_backoff_max no 60 Max backoff on reconnect

Env vars override everything. File-based settings (~/.z4j/config.env) can supplement env vars but not replace them. Explicit keyword arguments to the framework adapter win over both.