Skip to main content

max / alloy

ssh: require a key, for every account fedora-bootc:43 leaves PasswordAuthentication yes. Root was already key-only there, so nothing covered the account the installer creates: it was reachable by password from anywhere that could route to the machine, on every Alloy install, since sshd has always been enabled. Policy is now a key or nothing, stated in one file rather than left to whatever default the base happens to ship. KbdInteractiveAuthentication is repeated here despite 50-redhat.conf already setting it, because PAM can authenticate a password through that path with PasswordAuthentication off, and a rule split across a file Alloy does not own is a rule that can silently half-apply. The number is load-bearing. sshd_config includes this directory at line 15, ahead of every keyword it sets, and sshd takes the first value it obtains rather than the last, so 10- wins over Fedora's 40- and 50-. Cost: nothing on a desktop install, where greetd is on the console and a user with no key logs in locally and adds one. A headless install is a lockout until alloy install learns to collect a public key, which is GoingsOn alloy 02979700. The out-of-band workaround is written into the file for whoever hits it first. Verified against a real sshd in the base image: sshd -t passes and sshd -T reports passwordauthentication no.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-25 17:32 UTC
Signed with PGP, not checked
Commit: 6ff9a458dbafd727c2b16338537b5f2e4e4fc87f
Parent: e9767ba
1 file changed, +40 insertions, -0 deletions
@@ -1,0 +1,40 @@
1 + # Alloy sshd policy: a key, for every account, always.
2 + #
3 + # sshd is enabled on every Alloy install (see
4 + # etc/systemd/system-preset/50-alloy.preset). fedora-bootc:43 leaves
5 + # `PasswordAuthentication yes`, which means the account the installer creates is
6 + # reachable by password from anywhere that can route to the machine. Root was
7 + # already key-only there; nothing covered uid 1000. This file closes that, and
8 + # states the rule rather than leaving it to a built-in default: a valid public
9 + # key is required for any account, root included.
10 + #
11 + # Read before Fedora's own drop-ins. `/etc/ssh/sshd_config` puts its
12 + # `Include /etc/ssh/sshd_config.d/*.conf` at line 15, ahead of every keyword it
13 + # sets, and sshd takes the FIRST value it obtains for a keyword rather than the
14 + # last. So the number is what makes this authoritative, and lowering it is the
15 + # way to override, not raising it. Neither 40-redhat-crypto-policies.conf nor
16 + # 50-redhat.conf sets these three today, so this wins on merit as well as on
17 + # order, but the ordering is the part that keeps being true when they change.
18 +
19 + # The rule. `no` rather than relying on a default, because the default is
20 + # whatever the base ships and the base shipped `yes`.
21 + PasswordAuthentication no
22 +
23 + # The other password door. PAM's keyboard-interactive stack can authenticate a
24 + # password even with PasswordAuthentication off, so turning off one without the
25 + # other leaves the rule half-applied. 50-redhat.conf already sets this; it is
26 + # repeated here so the policy is legible in one file instead of depending on a
27 + # neighbour that Alloy does not own.
28 + KbdInteractiveAuthentication no
29 +
30 + # Root: key or nothing. This matches what fedora-bootc already had in effect
31 + # (`without-password`, the older spelling of the same thing), written in the
32 + # current spelling and stated rather than inherited.
33 + PermitRootLogin prohibit-password
34 +
35 + # WHAT THIS COSTS, said plainly. On a desktop install nothing: greetd is on the
36 + # console, so a user who has not planted a key logs in locally and adds one.
37 + # On a HEADLESS install it is a lockout, because there is no console to recover
38 + # from and `alloy install` does not yet collect a public key. That gap is real
39 + # and tracked (GoingsOn alloy d1fed0d7 item 2); until it closes, a headless
40 + # install has to plant a key into the target's authorized_keys out of band.