| 1 |
# Creates the `installer` account, on the installer medium only. |
| 2 |
# |
| 3 |
# This unit is the gate for the whole ssh-in half of the headless flow. The |
| 4 |
# sshd policy that turns that account into an installer session ships in every |
| 5 |
# image (etc/ssh/sshd_config.d/20-alloy-installer.conf) and is inert without |
| 6 |
# it: `Match User installer` matches nothing when there is no such user. So the |
| 7 |
# condition below is the single thing standing between a running Alloy machine |
| 8 |
# and a remotely reachable disk-partitioning wizard. |
| 9 |
# |
| 10 |
# Same flag and same reasoning as alloy-installer.service, which gates the tty1 |
| 11 |
# installer. `alloy.installer` is set only by the GRUB entries the ISO build |
| 12 |
# writes (build/make-iso.sh), so this is inert on an installed system — which |
| 13 |
# is the same image. |
| 14 |
# |
| 15 |
# Fails safe. If the condition does not hold, or the unit fails, or it simply |
| 16 |
# has not run yet, the account does not exist and nobody logs in. The bad |
| 17 |
# direction would be a gate whose absence leaves the door open, which is what |
| 18 |
# writing the sshd drop-in at runtime would have been. |
| 19 |
[Unit] |
| 20 |
Description=Alloy installer ssh account |
| 21 |
Documentation=https://git.sr.ht/~maxmj/alloy |
| 22 |
ConditionKernelCommandLine=alloy.installer |
| 23 |
|
| 24 |
# Ordered ahead of sshd so the account exists before anything can ask for it. |
| 25 |
# Both are pulled by multi-user.target, so they land in one transaction and |
| 26 |
# this ordering is honoured. sshd does not need restarting afterwards: the user |
| 27 |
# is resolved per connection, not read at start. |
| 28 |
Before=sshd.service |
| 29 |
|
| 30 |
[Service] |
| 31 |
Type=oneshot |
| 32 |
RemainAfterExit=yes |
| 33 |
|
| 34 |
# Idempotent, because a `useradd` that has already run exits 9 and would put |
| 35 |
# the unit in failed. The `id` test is the check rather than a `-` prefix on |
| 36 |
# the command, which would also swallow the failures worth seeing. |
| 37 |
# |
| 38 |
# The shell is /bin/sh and that is not cosmetic: sshd runs a ForceCommand |
| 39 |
# through the account's login shell with `-c`, so /sbin/nologin would refuse |
| 40 |
# every session. Nothing is reachable through it — ForceCommand replaces |
| 41 |
# whatever the client asked for — so this grants no shell. |
| 42 |
# |
| 43 |
# No home directory, and `--home-dir /` so sshd has somewhere to chdir rather |
| 44 |
# than logging a failure on every connection. The authorized_keys it reads is |
| 45 |
# an absolute path in /usr/lib, baked at build time and owned by root. |
| 46 |
# |
| 47 |
# One physical line, not a continuation. The Containerfile checks that this |
| 48 |
# unit and the sshd drop-in name the same account, and it can only do that by |
| 49 |
# reading the line the account name is on. |
| 50 |
ExecStart=/bin/sh -c 'id -u installer >/dev/null 2>&1 || useradd --system --no-create-home --home-dir / --shell /bin/sh --comment "Alloy installer over ssh" installer' |
| 51 |
|
| 52 |
[Install] |
| 53 |
WantedBy=multi-user.target |
| 54 |
|