Skip to content

Configuration

This page documents all environment variables and default settings for the Ironflow server and its SDKs.


Variable Description Default
IRONFLOW_SERVER_URL The URL SDKs and CLI use to connect. The Go agent SDK also honors IRONFLOW_URL as a fallback alias (checked first). http://localhost:9123
IRONFLOW_API_KEY The key used for authentication. (None)
IRONFLOW_DATABASE_URL Postgres connection string (triggers PG mode). (None, uses SQLite)
IRONFLOW_BLOB_URL Blob overflow backend for large run/step outputs. Empty uses local filesystem next to the SQLite DB; s3://bucket?endpoint=...&region=... selects an S3-compatible backend. Multi-node deployments require an s3:// value. See Artifact overflow to blob storage. (None, local filesystem)
IRONFLOW_ARTIFACT_THRESHOLD Size above which run/step outputs offload to the blob backend (1MB, 512KiB, etc.). Empty or 0 disables new offloads; reads still inflate existing blobs. (None, off)
AWS_ACCESS_KEY_ID Access key used by the S3-compatible blob backend when IRONFLOW_BLOB_URL is set. (None)
AWS_SECRET_ACCESS_KEY Secret key used by the S3-compatible blob backend when IRONFLOW_BLOB_URL is set. (None)
AWS_SESSION_TOKEN Optional session token for temporary S3 credentials. (None)
IRONFLOW_MASTER_KEY 32-byte hex key for secrets encryption. (None, Dev Mode)
IRONFLOW_JWT_SECRET 32-byte hex key for dashboard JWT signing. Auto-generated and persisted to .ironflow_jwt_secret if not set. (Auto-generated)
IRONFLOW_SIGNING_KEY Key for verifying push-mode webhooks. (None)
IRONFLOW_ENV Default environment for CLI and SDK operations. default
IRONFLOW_CONFIG_DIR Directory for storing platform credentials (credentials.json). Used by ironflow platform login. ~/.config/ironflow
NATS_STORE_DIR Disk path for embedded NATS JetStream storage. (Auto-derived from --db path: {db_dir}/ironflow-nats. See Embedded NATS storage below.)
LOG_LEVEL trace, debug, info, warn, error. Overrides per-command defaults. warn (CLI), info (serve)
LOG_FORMAT text for human-readable output. Only affects serve command (JSON by default). CLI commands always use text. text (CLI), JSON (serve)

Ironflow uses S3-compatible storage in a few different places. These settings are intentionally separate because they protect different data.

Surface What goes to S3 Dev / single-node default Production setting Configure with
Runtime blob overflow Large run and step outputs after they exceed the configured threshold. Reads inflate the payload transparently. Local filesystem next to the SQLite DB; offload is disabled until a threshold is set. Multi-node deployments require a shared s3:// backend, even when new offloads are disabled. IRONFLOW_ARTIFACT_THRESHOLD, IRONFLOW_BLOB_URL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, optional AWS_SESSION_TOKEN; YAML: spec.blobs.artifactThreshold, spec.blobs.url. See Artifact overflow to blob storage.
Kubernetes PostgreSQL backups CNPG/Barman WAL archives and database backups. Disabled unless the Helm object store settings are enabled. Enable postgresql.objectStore and point it at an S3-compatible bucket. Helm values: postgresql.objectStore.enabled, destinationPath, endpointURL, retentionPolicy, s3Credentials. See Kubernetes deployment.
Cloud operator break-glass and snapshots Encrypted break-glass payloads and deprovision snapshot exports for managed-cloud workflows. Not used by normal ironflow serve; only used by ironflow-cloud workflows. Set the cloud operator S3 endpoint, bucket, credentials, region, and TLS flag. IRONFLOW_CLOUD_BREAK_GLASS_ENDPOINT, IRONFLOW_CLOUD_BREAK_GLASS_REGION, IRONFLOW_CLOUD_BREAK_GLASS_BUCKET, IRONFLOW_CLOUD_BREAK_GLASS_ACCESS_KEY, IRONFLOW_CLOUD_BREAK_GLASS_SECRET_KEY, IRONFLOW_CLOUD_BREAK_GLASS_SECURE.

The broader object/file storage API described in ADR-0035 is separate design work and is not configured by IRONFLOW_STORAGE_* variables in the shipped server path.

ironflow serve runs an embedded NATS JetStream server when NATS_URL is not set. JetStream needs a storage directory for streams and consumer state.

Default behavior (since #614): the store directory is auto-derived from the SQLite database path. For the default .ironflow/ironflow.db it becomes .ironflow/ironflow-nats/; for /data/ironflow.db it becomes /data/ironflow-nats/. The directory is created at startup with 0700 permissions (owner read/write/exec only) because JetStream stream files contain workflow event payloads that may include PII or secrets. Existing directories are left as-is so operators can pre-create with their preferred ownership and permissions.

Memory-mode opt-out: pass an explicit empty value for testing, demos, or ephemeral CI:

Terminal window
ironflow serve --nats-store-dir=""

The explicit empty CLI flag wins over a NATS_STORE_DIR environment variable inherited from the shell or systemd unit.

YAML-only opt-out is not currently supported. YAML round-trip cannot distinguish nats.storeDir: "" from an omitted field, so a YAML config alone cannot request memory mode. YAML operators who want ephemeral embedded NATS have two options today: (1) point at an external NATS server via nats.url, or (2) override at startup with --nats-store-dir="" on the command line. A discoverable :memory: sentinel for --nats-store-dir and NATS_STORE_DIR is tracked in TODOS.md as a follow-up.

Postgres mode: when IRONFLOW_DATABASE_URL is set and NATS_URL is NOT set (embedded NATS), ironflow serve and ironflow validate refuse to start without an explicit --nats-store-dir or NATS_STORE_DIR. Auto-deriving from the SQLite path is not safe — there is no SQLite path in Postgres mode, and silently creating a directory in the current working directory is dangerous under systemd units, container WorkingDirectory: /, and read-only cwd. Set the directory explicitly when you want embedded NATS with Postgres, or use --nats-url for an external NATS server.

:memory: SQLite: same fail-fast as Postgres mode. --db :memory: plus embedded NATS without an explicit store dir is rejected at startup.

Security note — secrets KV plaintext on disk. The secrets KV bucket is backed by JetStream file storage. When IRONFLOW_MASTER_KEY is unset, secret values are stored without encryption (passthrough). Before #614 this was masked by memory-mode embedded NATS; with persistent NATS as the default, secrets without a master key persist plaintext to {store_dir}/secrets/.... The server emits a startup WARN when this configuration is detected and a stronger WARN with the count of plaintext secrets when any exist. Set IRONFLOW_MASTER_KEY to a 32-byte hex value (e.g. openssl rand -hex 32) for AES-256-GCM encryption, then re-set existing secrets via ironflow secret set so they get re-encrypted.

Storage profile. File-storage streams retain about 1.3 GB total (internal/nats/streams.go), versus about 75 MB total in memory mode. Operators on size-constrained disks can override per-stream limits via YAML or roll back to memory mode with --nats-store-dir="".

Operator discipline. The embedded NATS server does not lock its store directory, so two ironflow serve processes against the same DB directory will silently corrupt JetStream state. Run a single process per directory.

Variable Description Default
IRONFLOW_OTEL_ENDPOINT OTLP gRPC endpoint for OpenTelemetry tracing. (None, disabled)
IRONFLOW_OTEL_SAMPLE_RATE Trace sampling rate (0.0 to 1.0). 1.0
IRONFLOW_OTEL_SERVICE_NAME OTel service name. ironflow
IRONFLOW_OTEL_INSECURE Use plaintext gRPC for OTLP export. true
IRONFLOW_METRICS_ENABLED Enable Prometheus metrics at /metrics. false

The --pprof CLI flag on ironflow serve starts a separate listener on :6060 with Go’s net/http/pprof handlers for CPU, heap, and goroutine profiling. Not configured via environment variable — CLI flag only. See Benchmarks for the load testing workflow.

Variable Description Default
NATS_URL External NATS server URL. When set, connects to external NATS instead of embedded. Requires PostgreSQL. (None, embedded)
NATS_CREDS_FILE NATS credentials file for NKey/JWT auth. (None)
IRONFLOW_NODE_ID Unique node identifier for distributed coordination. Must be stable per node. Random UUID v4
IRONFLOW_STALE_CLAIM_THRESHOLD Duration before stale scheduler claims are reclaimed. 2m
IRONFLOW_STALE_CLAIM_RECOVERY_INTERVAL How often the scheduler scans for orphaned claims. Lower values detect crashes faster at the cost of more frequent SQL sweeps. The --dev flag drops it to 5s. 60s
NATS_FILE_STORAGE Set to true to use file-backed JetStream streams instead of memory. false
NATS_STREAM_REPLICAS JetStream stream replica count for clustered NATS. 1
Variable Description Default
IRONFLOW_WS_ALLOWED_ORIGINS Comma-separated allowed origins for WebSocket connections. When empty, all origins are allowed. (None, all origins)
IRONFLOW_AGENT_TOOLS_ALLOW_PRIVATE When true, agent tool callback URLs may target RFC1918/loopback addresses. The --dev flag forces this on regardless. false
IRONFLOW_AGENT_TOOLS_URL_ALLOWLIST Comma-separated host allowlist for agent tool callback URLs. When set, only listed hosts are accepted. (None, no allowlist)
IRONFLOW_REQUIRE_ENCRYPTION When true/1/yes, the engine verifies the SQLite data path lives on a dm-crypt block device and fails fast at startup otherwise. Postgres backends skip the check. Belt-and-suspenders against misconfigured systemd BindsTo units. false (off)
Variable Description Default
IRONFLOW_CANCEL_ON_REPLAY_WINDOW_SECONDS Lookback window (seconds) for the cancel-on-replay buffer. Recent events newer than this are kept for cancellation matching. 30
IRONFLOW_CANCEL_ON_REPLAY_BUFFER_SIZE Maximum entries retained in the cancel-on-replay buffer. Bounds memory under high event rates. 10000
IRONFLOW_SQLITE_MAX_BYTES Caps total SQLite footprint (main + WAL + SHM). Writes that would exceed it return 507 Insufficient Storage. SQLite backends only. 10737418240 (10 GiB)
IRONFLOW_WRITE_QPS_MAX Caps REST write requests per second per node. Excess writes are throttled. Single-node SQLite sustained-write budget. 500
Variable Description Default
IRONFLOW_CAP_TOKEN_PRIVATE_KEY_B64 Base64-encoded PKCS8 DER Ed25519 private key for minting deprovision capability tokens (ironflow cloud cap-token mint). (None, required for mint)
IRONFLOW_MASTER_KEY_B64 Base64-encoded 32-byte meta-cluster KEK for decrypting break-glass bearer blobs and snapshot exports (ironflow cloud break-glass, ironflow cloud snapshot decrypt). (None, required for decrypt)
Variable Description Default
IRONFLOW_AUDIT_BATCH_SIZE Maximum rows per batch insert into the policy_decisions audit table. 100
IRONFLOW_AUDIT_BATCH_FLUSH_MS Milliseconds between batch flushes. Set lower for tighter audit latency; set higher for write throughput. 1000
Variable Description Default
IRONFLOW_REBUILD_BATCH_SIZE_SQLITE Events per batch when rebuilding a projection against a SQLite-backed event store. 500
IRONFLOW_REBUILD_BATCH_SIZE_POSTGRES Events per batch when rebuilding a projection against a PostgreSQL-backed event store. 1000
IRONFLOW_REBUILD_BATCH_PAUSE_MS Milliseconds to pause between FULL rebuild batches (PG only). Useful for throttling large rebuilds. 0

On the very first boot of a fresh database, Ironflow creates a default admin user with the email admin@ironflow.local and a randomly generated password. Both the admin API key and password are printed to the console and must be saved immediately – they will not be shown again.


import { ironflow } from "@ironflow/browser";
ironflow.configure({
serverUrl: "http://localhost:9123",
auth: { apiKey: "ifkey_..." },
environment: "default",
});

Additional options: transport (“connectrpc” | “websocket”), reconnect, visibility, logger, timeout.

import { createClient } from "@ironflow/node";
const client = createClient({
serverUrl: process.env.IRONFLOW_SERVER_URL || "http://localhost:9123",
apiKey: process.env.IRONFLOW_API_KEY,
});

Additional options: timeout (ms, default 30000), onError (global error handler).


Limit Value Applies To
Max Event Data 512 KB Payload of an emitted event.
Max Step Output 1 MB Data returned by a step.run.
Max Batch Size 100 Max events in a TriggerBatch call.
Wait Timeout 30s Default timeout for emit --wait.