From 1538ecacdd0b0ec3df8656a264aa54f7e3c2ae07 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 6 Sep 2026 21:45:28 +0200 Subject: [PATCH] Record how secrets reach a workload The first launch with a full environment failed EACCES on /srv/heimdall/keys/signing-key.pem: the workload runs under DynamicUser and cannot open a heimdall:heimdall 0600 file. The wrong fix is a supplementary group -- widening access to resolve a permissions error. Idunn already has the right one. A [workload.secret_files] entry is loaded as a systemd credential, and the driver sets an env var named after the entry whose value is the credential path. Naming the entry after the variable the service already reads wires it up with no code change, and setting that name in [workload.environment] too is refused as a collision. Co-Authored-By: Claude Opus 5 --- docs/migration.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/migration.md b/docs/migration.md index bc23545..5c545a8 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -395,6 +395,17 @@ binding cannot widen access, and each one cost a failed deployment to discover: | runner network | must exist | the binding names a docker network; the operator provisions it | | runtime presence identity | `root:root`, mode `0400`, `nlink` 1 | passed to the workload as a parent-only descriptor, so it must be unwritable and unaliased -- a second hard link would be a second path to the signing key | +**Secrets reach the workload as systemd credentials, not as readable files.** +The workload runs under `DynamicUser`, so it cannot open a `heimdall:heimdall +0600` key no matter where it sits, and giving it a supplementary group to make +that work would be widening access to fix a permissions error. Put the secret in +`[workload.secret_files]` instead: Idunn loads it as a credential and sets an +environment variable **named after the entry**, whose value is the credential +path. Naming the entry after the variable the service already reads -- +`GC_ACCESS_SIGNING_PRIVATE_KEY_PATH` for Heimdall -- wires it up with no code +change at all. Setting the same name in `[workload.environment]` as well is +refused as a collision, which is the mechanism telling you there is one owner. + **The Idunn unit also needs the target.s roots.** `ProtectSystem=full` makes `/etc` read-only, so a target whose `runtime_root` is not in `ReadWritePaths` fails at "creating runtime bundle". Every migration adds exactly three paths --