max / alloy
4 files changed,
+46 insertions,
-9 deletions
| @@ -466,6 +466,41 @@ | |||
| 466 | 466 | done; \ | |
| 467 | 467 | echo "polkit: granted $(echo "$granted" | wc -l) actions, all defined" | |
| 468 | 468 | ||
| 469 | + | # ===================================================================== | |
| 470 | + | # run0 — assert the way to root that Alloy documents is in the image. | |
| 471 | + | # | |
| 472 | + | # Alloy names `run0` and not `sudo` (docs/CONTINUITY.md, | |
| 473 | + | # docs/HARDWARE-FW12.md, the installer's account pane; rationale in wiki | |
| 474 | + | # note `alloy-privilege`). run0 is systemd's, arrived in 256, and is a | |
| 475 | + | # symlink to systemd-run: it asks PID 1 for a transient unit running as | |
| 476 | + | # root, and PID 1 asks polkit. So becoming root goes through the same | |
| 477 | + | # authority the console's writing views already go through, and a | |
| 478 | + | # fingerprint or FIDO2 factor configured once at polkit's PAM stack | |
| 479 | + | # covers both. | |
| 480 | + | # | |
| 481 | + | # sudo is still in the base and still works. Nothing here removes it; | |
| 482 | + | # what is asserted is only that the path the docs name is present, since | |
| 483 | + | # a manual telling a user to type run0 on an image without it is worse | |
| 484 | + | # than no manual. Three ways that can be wrong, all silent on a built | |
| 485 | + | # image: | |
| 486 | + | # | |
| 487 | + | # - the base dropped run0, so every doc naming it is a lie | |
| 488 | + | # - systemd is older than 256, so run0 predates its own existence | |
| 489 | + | # - the action a transient-unit request authenticates against is not | |
| 490 | + | # defined, so run0 has no admin to resolve and cannot authorize | |
| 491 | + | # ===================================================================== | |
| 492 | + | RUN set -eux; \ | |
| 493 | + | command -v run0 >/dev/null \ | |
| 494 | + | || { echo "no run0 in the base image; the docs name it as the way to root" >&2; exit 1; }; \ | |
| 495 | + | version=$(systemctl --version | sed -n '1s/^systemd \([0-9]*\).*/\1/p'); \ | |
| 496 | + | [ -n "$version" ] || { echo "could not read a systemd version" >&2; exit 1; }; \ | |
| 497 | + | [ "$version" -ge 256 ] \ | |
| 498 | + | || { echo "systemd $version predates run0, which arrived in 256" >&2; exit 1; }; \ | |
| 499 | + | action=org.freedesktop.systemd1.manage-units; \ | |
| 500 | + | grep -qr "action id=\"$action\"" /usr/share/polkit-1/actions/ \ | |
| 501 | + | || { echo "$action is not defined; run0 cannot ask polkit for an admin" >&2; exit 1; }; \ | |
| 502 | + | echo "run0: present, systemd $version, $action defined" | |
| 503 | + | ||
| 469 | 504 | # ===================================================================== | |
| 470 | 505 | # Systemd presets — shipped via etc/systemd/{system,user}-preset/ | |
| 471 | 506 | # in the config tree above. Split across system-preset (greetd, |
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | - The client (`tailscaled` + `tailscale`) is open-source and works with either the tailscale.com control plane or a self-hosted Headscale server. | |
| 18 | 18 | - The control plane choice is exposed at enrollment time as a "Server" field, defaulting to tailscale.com. Users pointing at Headscale set `--login-server=<url>`, which Alloy handles as a first-class field in `alloy mesh` rather than a footnote. The console reads the control plane back and names it in the view title when it is self-hosted, so "which control plane am I on" is answerable without dropping to a shell. | |
| 19 | - | - Enabled via `alloy mesh` (see below) or plain `sudo tailscale up`. Not enrolled by default. An OS that phones home before the user says yes is out of character for Alloy. | |
| 19 | + | - Enabled via `alloy mesh` (see below) or plain `run0 tailscale up`. Not enrolled by default. An OS that phones home before the user says yes is out of character for Alloy. | |
| 20 | 20 | ||
| 21 | 21 | **Not shipping the Headscale server itself.** That is fleet-admin work, not client-OS work. Users self-hosting Headscale run it on their infrastructure of choice; Alloy points at it. | |
| 22 | 22 |
| @@ -68,7 +68,7 @@ | |||
| 68 | 68 | ||
| 69 | 69 | Framework 12 ships a fingerprint reader on the power button. Upstream Linux support is via `libfprint`; enrollment through `fprintd`. Fedora Silverblue includes the stack. | |
| 70 | 70 | ||
| 71 | - | - Alloy configures PAM to allow fingerprint at sudo and at the lockscreen. | |
| 71 | + | - Alloy configures PAM to allow fingerprint wherever the system asks who you are: at the lockscreen, and at the polkit prompt, which is the one `run0` and the console's writing views both raise. The file that matters for the second is `/etc/pam.d/polkit-1`, not `/etc/pam.d/sudo` — Alloy documents `run0` rather than `sudo` (wiki note `alloy-privilege`), so a fingerprint stack that only covered sudo would cover nothing a user is told to type. | |
| 72 | 72 | - Fingerprint unlock wires through swaylock's PAM stack (the authored egui lockscreen was dropped in the pivot). No Alloy code beyond PAM config. | |
| 73 | 73 | ||
| 74 | 74 | ## Firmware (fwupd / LVFS) | |
| @@ -98,7 +98,7 @@ | |||
| 98 | 98 | ||
| 99 | 99 | ## Open questions | |
| 100 | 100 | ||
| 101 | - | - [ ] fprintd unlock through swaylock's PAM stack on the FW12: enroll, then verify unlock at swaylock and at sudo. | |
| 101 | + | - [ ] fprintd unlock through swaylock's PAM stack on the FW12: enroll, then verify unlock at swaylock and at a `run0` prompt (polkit's PAM stack, via `pkttyagent`). | |
| 102 | 102 | - [ ] Fractional-scale validation at 1.25x on this panel under sway: do terminal glyph metrics stay crisp? | |
| 103 | 103 | - [ ] s2idle drain measurement on FW12 running the Alloy image, baseline vs. tuned. If drain is bad enough to matter, revisit whether Alloy ships any power tweaks or leaves it to Fedora defaults. | |
| 104 | 104 | - [ ] (shelved) The `alloy-hinged` fold-to-notes questions (keyboard/trackpad suppression on `SW_TABLET_MODE`, Rnote fullscreen behavior) revive only if the tablet flow comes back. |
| @@ -782,9 +782,10 @@ | |||
| 782 | 782 | .arg("--force"), | |
| 783 | 783 | ), | |
| 784 | 784 | // useradd rather than a sysusers entry because this account needs a home | |
| 785 | - | // and a supplementary group. wheel is what sudo grants on Fedora, and an | |
| 786 | - | // install whose only account cannot escalate is one with no way to | |
| 787 | - | // administer itself. | |
| 785 | + | // and a supplementary group. wheel is the group Fedora's polkit resolves | |
| 786 | + | // an administrator to, which is what `run0` and every writing console | |
| 787 | + | // view ask for, and an install whose only account cannot escalate is one | |
| 788 | + | // with no way to administer itself. See wiki note `alloy-privilege`. | |
| 788 | 789 | // | |
| 789 | 790 | // --no-create-home despite the account needing one: --create-home | |
| 790 | 791 | // resolves the path inside the target, which puts the directory in the | |
| @@ -1622,7 +1623,7 @@ | |||
| 1622 | 1623 | let lines = vec![ | |
| 1623 | 1624 | Line::from(text::muted( | |
| 1624 | 1625 | theme, | |
| 1625 | - | "The account you will log in with. It can use sudo.", | |
| 1626 | + | "The account you will log in with. It can become root with run0.", | |
| 1626 | 1627 | )), | |
| 1627 | 1628 | Line::default(), | |
| 1628 | 1629 | self.field_line(theme, "username", &self.username, FIELD_USERNAME, false), | |
| @@ -2877,9 +2878,10 @@ | |||
| 2877 | 2878 | } | |
| 2878 | 2879 | ||
| 2879 | 2880 | // An account that cannot escalate leaves an install with no way to | |
| 2880 | - | // administer itself. | |
| 2881 | + | // administer itself. wheel is the group polkit resolves an administrator | |
| 2882 | + | // to, so it is what `run0` and the console's writing views both ask for. | |
| 2881 | 2883 | #[test] | |
| 2882 | - | fn the_account_can_sudo() { | |
| 2884 | + | fn the_account_can_administer_the_machine() { | |
| 2883 | 2885 | let useradd = command_starting("useradd"); | |
| 2884 | 2886 | ||
| 2885 | 2887 | assert!(useradd.contains("wheel"), "{useradd}"); |