Skip to content

Secrets Management

Ironflow provides environment-scoped secrets management with AES-256-GCM encryption backed by NATS KV. Secrets are write-only—values can be set but never retrieved through the API, CLI, or Dashboard.

Event-Driven by Design

Every secret operation (create, update, delete) is a JetStream message. This ensures that secret state inherits the same durability and replication guarantees as your workflows.

  • Atomic: Secret updates use native JetStream revision tracking.
  • Observable: Every rotation emits a system event (e.g., system.secret.STRIPE_KEY.updated).
  • Declarative: Functions declare exactly which secrets they need; the engine resolves and injects them only at runtime.

Secure by Default

The architecture enforces a strict “Management vs. Runtime” separation:

  • Write-Only API: The CLI and Dashboard only expose metadata (revision, name). Plaintext values are never returned.
  • Runtime Injection: Values are only decrypted when a worker receives a job.
  • Master Key: Encryption is controlled by the IRONFLOW_MASTER_KEY environment variable. The value must be a hex-encoded 32 bytes (generate with openssl rand -hex 32).

Dev mode — no encryption. If IRONFLOW_MASTER_KEY is unset or empty, Ironflow runs in development mode and stores secrets in plaintext on disk. The engine logs a warning at startup. Always set a master key in production.


Quick Start (Node.js)

1. Set a secret via CLI:

Terminal window
ironflow secret set STRIPE_KEY sk_live_123 --env default --description "Stripe live key"

The --env / -e flag targets a specific environment (defaults to default). All ironflow secret subcommands (set, get, list, delete) accept --env. set also accepts --description / -d.

2. Declare and use in a function:

import { ironflow } from "@ironflow/node";
export const payout = ironflow.createFunction(
{
id: "payout",
triggers: [{ event: "payout.requested" }],
secrets: ["STRIPE_KEY"], // Declare dependency
},
async ({ event, secrets, step }) => {
// Access the decrypted value
const apiKey = secrets.get("STRIPE_KEY");
await step.run("charge", () => stripe(apiKey).charge(...));
}
);

When to Use Secrets

FeatureUse For
SecretsAPI Keys, DB Passwords, Certificates.
ConfigRollout percentages, Theme settings, Timeouts.
KV StoreSessions, Caching, Counters.

Subscribing to Rotations

You can subscribe to secret lifecycle events to audit rotations or trigger security workflows.

import { ironflow } from "@ironflow/browser";
await ironflow.subscribe("system.secret.*.updated", {
onEvent: (e) => console.log(`Secret ${e.data.name} was rotated!`),
});