fix: SetCredential with an empty value is dropped by systemd

`swarm-controller.service` carried `SetCredential=queue-client.secret:` — an
empty value, which systemd's parser refuses:

    /etc/systemd/system/swarm-controller.service:38:
    Invalid syntax, ignoring: queue-client.secret:

So the line was dropped on every daemon-reload, and `LoadCredential=` was
fatal again — precisely the failure that default was added to prevent. On a
hive where authelia has not yet minted the secret, the controller refuses to
start rather than coming up with the queue unconfigured.

It looked correct for days because the credential file happened to exist, so
the fail-soft was never exercised.

Measured with `systemd-analyze verify`: an empty value is rejected, any
non-empty one is accepted. The placeholder is a real word rather than filler —
it reaches the token request as the client secret, so authelia refuses it and
the journal names something an operator can act on.

Gate: state/eval-setcredential.sh, with the parent commit as its mutation.
This commit is contained in:
atlas 2026-08-16 22:53:50 +02:00
commit fbb20a56e8

View file

@ -464,17 +464,28 @@ in
]
++ lib.optional (cfg.forgeTokenFile != null) "forge-token:${cfg.forgeTokenFile}";
# The empty default that makes the above non-fatal. `LoadCredential=`
# takes priority over `SetCredential=`, so this is only ever seen
# when the file is missing — and in that case systemd starts the unit
# instead of refusing to. The controller then serves its HTTP surface
# with the queue unconfigured, which is a supported shape it already
# knows how to report.
# The placeholder default that makes the above non-fatal.
# `LoadCredential=` takes priority over `SetCredential=`, so this is
# only ever seen when the file is missing — and in that case systemd
# starts the unit instead of refusing to. The controller then serves
# its HTTP surface with the queue unconfigured, which is a supported
# shape it already knows how to report.
#
# Safe to put in a unit file precisely because it carries nothing:
# ⚠️ THE VALUE MUST BE NON-EMPTY. `SetCredential=<id>:` with an empty
# value is rejected by systemd's parser — *"Invalid syntax, ignoring"*
# — so the whole line is dropped and the fail-soft above silently does
# not exist. Measured with `systemd-analyze verify`: empty is refused,
# any non-empty value is accepted. This shipped broken and only looked
# fine because the credential file happened to be present.
#
# The word is deliberate rather than arbitrary: it reaches the token
# request as the client secret, so authelia refuses it and the journal
# says so in terms an operator can act on.
#
# Safe in a unit file precisely because it is not a secret:
# `SetCredential=` values are readable by unprivileged processes over
# IPC, so a real secret must never appear here.
SetCredential = [ "queue-client.secret:" ];
# IPC, so real key material must never appear here.
SetCredential = [ "queue-client.secret:placeholder-no-secret-file" ];
User = "swarm-controller";
Group = "swarm-controller";
Restart = "on-failure";