--- title: "Fleet Secrets" description: "Centralized, encrypted, versioned env-var bundles you can push to labeled nodes' stacks." --- Fleet Secrets gives you one place to author the environment variables a stack needs, and one action to push them to every node that runs that stack. Bundles are encrypted at rest, every save bumps a version, and every push is recorded in the audit log with a per-node diff. Fleet Secrets is available on **Skipper** and **Admiral** licenses. The tab is hidden on Community. ## What's in scope | Today | Not yet | |-------|---------| | Bundles of `KEY=value` env pairs | Certificates, key files, credential JSON blobs | | Push to nodes by label selector | Pin a bundle to specific node IDs | | Versioning on every save with a change note | Scheduled or auto-rotation | | Diff preview before each push | Multi-region or per-environment overlays | If a feature is not in the table above, it's deferred to a later release. Fleet Secrets in 1.0 is intentionally focused on env-var drift across copies of the same stack. ## Create a bundle 1. Open **Fleet → Secrets**. 2. Click **New bundle**. 3. Give it a name (letters, digits, dot, dash, underscore; 2–64 chars) and an optional description. 4. Add `KEY=value` rows. Keys must match the env-var convention (`A-Z`, digits, underscore; cannot start with a digit). The eye icon toggles value visibility; the copy icon copies a single value to the clipboard. 5. Add a **Change note** (optional but recommended) explaining why this version exists. 6. Click **Save**. The bundle is now version `v1`. Saving the bundle encrypts the payload with the instance's data key (AES-256-GCM via the same key that protects MFA secrets and registry credentials). The plaintext only ever exists in memory while you're editing. ## Edit and version Editing a bundle creates a new version. Each version is immutable once saved. Open a bundle and switch to the **Versions** tab to see who saved each version and any change notes attached. Saves are last-write-wins. There's no row-level lock; if two operators edit the same bundle concurrently, the later save creates the higher version number and the earlier save remains visible in history. ## Push to nodes A push reads the bundle's current version, computes the diff against each target's existing env file, and writes the merged result. 1. From the bundle row, click the **Send** action to open the push wizard. 2. **Target tab:** - Pick one or more node labels. - Choose **any** (a node matches if it has any of the selected labels) or **all** (a node must have all selected labels). - Enter the **Stack name** that the bundle should be applied to. The stack must exist on each target node by that name. - Pick the **Env file** to write. The dropdown lists every file declared by the stack's compose on a representative target node — the canonical `.env` plus any files referenced via `env_file:` directives. Per-node compose files can differ; nodes that do not declare the chosen file are reported as failed for that push. 3. Click **Preview**. 4. **Preview tab:** the table shows one row per matched node. Each row reports a quick header (`+added · ~changed · ·unchanged`) and an expander with the per-key diff. Drift — keys present on the target that are absent from the bundle — is shown as informational `removed` rows. The push will not delete those keys. 5. Click **Push to N nodes**. 6. **Results tab:** per-node status pills (`ok`, `failed`, `skipped`). Hover a failure to see the error. Pushes are sequential per bundle to make audit ordering predictable. Only one push for a given bundle can run at a time; a second concurrent push attempt returns `409 Conflict` until the first finishes. ## Merge semantics: overlay Fleet Secrets uses **overlay** merge: - A key in the bundle that is missing from the target is **added**. - A key in both with a different value is **changed** to the bundle's value. - A key in both with the same value is **unchanged**. - A key on the target that is **not in the bundle** is preserved on the target. The diff shows it under `removed (drift)` so you can see the divergence, but the push leaves it alone. This is deliberately conservative for a v1 push action. If a key truly needs to be removed from a target's env file, do it in the stack editor on that node, then push the bundle to bring the rest of the keys in line. ## Audit trail Every mutating action shows up in **Audit Log**: | Action | Audit summary | |--------|---------------| | Create bundle | `Created secret` | | Update bundle (new version) | `Updated secret: ` | | Delete bundle | `Deleted secret: ` | | Import env from a stack | `Imported env into secret: ` | | Preview a push | `Previewed secret push: ` | | Execute a push | `Pushed secret: ` | The execute-push action also writes one row per target node in `secret_pushes`, capturing the bundle id, version, push id (a UUID grouping all rows from the same push), node id, stack name, env file, status, error message, and per-node `added` / `changed` / `unchanged` counts. ## Troubleshooting ### "env file '' not found on node " The node's compose file for that stack does not declare the env file you asked Fleet Secrets to write to. Either pick a different env file in the wizard's **Env file** dropdown, or update that node's compose to reference the file via `env_file:`. ### "stack not found" The named stack does not exist on that node. Fleet Secrets pushes to existing stacks only — it does not create stack directories. ### A push partially succeeded Per-node failures are independent. The bundle and other targets are unaffected; only the failing node missed the push. Fix the underlying cause (file declared in compose, stack created, node reachable) and re-run the push. Idempotent overlay means re-pushing is safe. ### "A push for this secret is already running" Only one push per bundle runs at a time. Wait for the previous push to finish, then retry. ### Values look wrong on the target Open the bundle and switch to **Versions** — confirm the version you intended to push is the current one. Open the wizard, run **Preview** without pushing, and read the diff. The preview is a faithful representation of what the next push will write.