Skip to main content

Environment Variables

Complete reference for the .env file consumed by the production docker-compose.yml.

Required In The Generated .env​

VariableDescriptionExample
BETTER_AUTH_SECRETSession signing secret (at least 32 chars)openssl rand -hex 32
BETTER_AUTH_URLPublic URL of DaoFlow instancehttps://deploy.example.com
ENCRYPTION_KEYGlobal DaoFlow secret-encryption key; keep it unchanged during destination-key rotation (at least 32 chars)openssl rand -hex 32
DAOFLOW_RECOVERY_ENCRYPTION_KEYDedicated key for encrypted control-plane recovery bundles; store it outside DaoFlow (at least 32 chars)openssl rand -hex 32
DAOFLOW_DATABASE_NAMEDatabase selected by the production DATABASE_URL; defaults to daoflowdaoflow
POSTGRES_PASSWORDDaoFlow application database passwordopenssl rand -hex 16

DATABASE_URL, REDIS_URL, and most container-local defaults are constructed inside the compose stack and are not normally hand-authored in this .env file. On a new Postgres volume, the service creates DAOFLOW_DATABASE_NAME (default daoflow). Changing this value after the volume has already been initialized selects a different application database but does not create or rename that database by itself.

Migration Recovery Controls​

VariableDefaultDescription
DAOFLOW_ALLOW_START_WITH_MIGRATION_FAILUREfalseEmergency degraded-start bypass for ordinary execution failures. It never bypasses migration-lineage mismatches or a recorded failed migration.
DAOFLOW_RETRY_FAILED_MIGRATIONfalseExplicitly clears the matching failed-migration marker and retries once. Use only in migration-only mode after repairing the underlying problem, then remove it immediately.

DaoFlow records only the failed migration timestamp, hash, stable reason, and failure time. It does not store the database URL, raw SQL, or the original error text in this recovery marker.

For an offline clean-install restore, use a separate external secrets file with mode 600. It must contain BETTER_AUTH_SECRET, ENCRYPTION_KEY, DAOFLOW_RECOVERY_ENCRYPTION_KEY, any manifest-required optional key, DAOFLOW_RECOVERY_VERIFY_EMAIL, and DAOFLOW_RECOVERY_VERIFY_PASSWORD. See Control-plane Recovery Bundles for the dry-run, plan-hash confirmation, and failed-target cleanup contract.

Backup-Destination Encryption Keys​

Backup-destination credentials use DAOFLOW_BACKUP_DESTINATION_ENCRYPTION_KEY when it is set, and otherwise use the global ENCRYPTION_KEY.

VariableDefaultDescription
DAOFLOW_BACKUP_DESTINATION_ENCRYPTION_KEYENCRYPTION_KEYCurrent key for backup-destination credential envelopes.
DAOFLOW_PREVIOUS_BACKUP_DESTINATION_ENCRYPTION_KEYunsetOld destination key supplied temporarily while startup rotates existing envelopes.

To rotate destination credentials, keep ENCRYPTION_KEY unchanged, set the new destination key and the temporary previous key, then run migration-only mode or restart the service. Startup verifies every envelope, re-encrypts all rows in a transaction, and clears legacy plaintext destination secrets. Any mixed or undecryptable state blocks production startup, and a failed rotation leaves the old ciphertext usable because no partial transaction is committed.

After /ready is healthy, test every destination with daoflow backup destination test --id <destination-id>. Only then remove DAOFLOW_PREVIOUS_BACKUP_DESTINATION_ENCRYPTION_KEY and restart. If the rotation fails before commit, restore the old destination key as DAOFLOW_BACKUP_DESTINATION_ENCRYPTION_KEY (or unset it to fall back to ENCRYPTION_KEY) and remove the temporary previous key. Do not replace the global ENCRYPTION_KEY.

Control-plane recovery uses DAOFLOW_RECOVERY_ENCRYPTION_KEY, not the global or destination key. DaoFlow stores only its fingerprint and rotation metadata. During a controlled rotation, supply the former value through DAOFLOW_PREVIOUS_RECOVERY_ENCRYPTION_KEY until a new recovery plan succeeds, then remove it. Losing the external recovery key makes encrypted bundles unreadable.

Large recovery bundles can tune transfer and isolated-restore limits:

VariableDefaultAllowed rangeDescription
DAOFLOW_RCLONE_COMMAND_TIMEOUT_MS180000060000–3600000Maximum time for one recovery-object upload or download.
DAOFLOW_CONTROL_PLANE_RECOVERY_VERIFIER_STORAGE_MB4096512–65536Storage and memory ceiling for each isolated PostgreSQL verifier.

Size the verifier above the restored database footprint. Recovery fails closed when a transfer exceeds its timeout or the isolated verifier exceeds its limit.

Version, Workflow Profile, And Ports​

VariableLean valueTemporal valueDescription
DAOFLOW_VERSION0.11.00.11.0DaoFlow image tag used by the repository production Compose file
DAOFLOW_WORKFLOW_PROFILEleantemporalInstaller-selected workflow profile; lean is the default
COMPOSE_PROFILESemptytemporalActive Compose profiles; the temporal profile adds the Temporal services
DAOFLOW_ENABLE_TEMPORALfalsetrueSelects legacy or Temporal-backed workflow execution
DAOFLOW_BIND127.0.0.1127.0.0.1Host interface bound to the control plane. Set explicitly, for example to 0.0.0.0, only when direct public binding is intentional.
DAOFLOW_PORT30003000Host port bound to the control plane
TEMPORAL_UI_PORT82338233Host port for Temporal UI when its separate Compose profile is enabled

The installer persists the three profile values together. Do not enable Temporal by changing only DAOFLOW_ENABLE_TEMPORAL; use daoflow install --workflow-profile temporal or set the matching profile values in .env.

HTTP Origin Controls​

VariableDefaultDescription
CORS_ORIGINunsetOptional allowed browser origin for API requests when the app is accessed from a separate trusted origin.

Initial Owner Bootstrap​

VariableDescription
DAOFLOW_INITIAL_ADMIN_EMAILOptional first owner email
DAOFLOW_INITIAL_ADMIN_PASSWORDOptional first owner password

Execution And Temporal​

VariableDefaultDescription
DEPLOY_TIMEOUT_MS86400000Max queue-wait and execution time; expiry aborts active work
TEMPORAL_POSTGRES_PASSWORDunset in lean; required in temporalTemporal database password
TEMPORAL_ADDRESStemporal:7233 in generated installsTemporal connection target
TEMPORAL_NAMESPACEdaoflowTemporal namespace
TEMPORAL_TASK_QUEUEdaoflow-deploymentsTemporal task queue
APPROVAL_ACTION_DISPATCH_POLL_INTERVAL_MS5000Durable approved-operation poll interval; values below 1000 use the default
DAOFLOW_APPROVAL_DISPATCH_MAX_ATTEMPTS12Positive attempt limit before submission reaches terminal failure
DAOFLOW_APPROVAL_DISPATCH_RETRY_BASE_MS1000Positive initial full-jitter retry window in milliseconds
DAOFLOW_APPROVAL_DISPATCH_RETRY_MAX_MS300000Positive maximum full-jitter retry window in milliseconds
PROVIDER_FEEDBACK_POLL_INTERVAL_MS5000Provider-feedback poll interval; values below 1000 use the default
DAOFLOW_PROVIDER_FEEDBACK_MAX_ATTEMPTS12Positive delivery-attempt limit before feedback is dead-lettered
DAOFLOW_PROVIDER_FEEDBACK_RETRY_BASE_MS1000Positive initial bounded exponential retry delay in milliseconds
DAOFLOW_PROVIDER_FEEDBACK_RETRY_MAX_MS300000Positive maximum provider-feedback retry delay in milliseconds

On an existing install, rerunning the installer without --workflow-profile preserves the current choice and infers older installs from their existing Temporal settings. Switching from temporal to lean stops and removes the Temporal containers after explaining the plan, while preserving the temporal-pgdata named volume. Temporal UI remains separately opt-in through temporal-ui.

Lean can omit TEMPORAL_POSTGRES_PASSWORD; the temporal profile requires a non-empty value.

Email (SMTP)​

VariableDescription
SMTP_HOSTSMTP server hostname
SMTP_PORTSMTP port
SMTP_USERSMTP username
SMTP_PASSWORDSMTP password
SMTP_FROMFrom address for emails

Optional Backup Storage (S3)​

VariableDescription
S3_ENDPOINTS3-compatible endpoint URL
S3_BUCKETBucket name for backups
S3_ACCESS_KEYS3 access key
S3_SECRET_KEYS3 secret key
S3_REGIONAWS region (optional)

Advanced Runtime Overrides​

These are usually set inside the compose file rather than in your .env, but they are part of the runtime contract:

VariableDefaultDescription
PORT3000Internal HTTP port inside the DaoFlow container
NODE_ENVproduction in composeRuntime mode
GIT_WORK_DIR/app/stagingFrozen deploy artifact workspace
SSH_KEY_DIR/app/.sshSSH key storage for managed targets
SERVER_READINESS_POLL_INTERVAL_MS60000Interval for recurring persisted server readiness checks
SERVER_METRICS_MONITOR_POLL_INTERVAL_MS15000Poll interval for selecting servers whose metric policy is due
SERVER_METRICS_MONITOR_CONCURRENCY4Maximum concurrent read-only server metric collections, from 1 to 16