max / alloy
1 file changed,
+26 insertions,
-8 deletions
| @@ -18,6 +18,12 @@ | |||
| 18 | 18 | # build/check-host.sh # this machine | |
| 19 | 19 | # ssh fw12 'bash -s' < build/check-host.sh | |
| 20 | 20 | # sudo build/check-host.sh # adds the rows that need root | |
| 21 | + | # ssh -t fw12.local 'sudo bash -s' < build/check-host.sh # both, with a prompt | |
| 22 | + | # | |
| 23 | + | # Four rows need root and skip without it: the image identity (`bootc status` | |
| 24 | + | # refuses an unprivileged caller), the SELinux labels, the LUKS keyslot count, | |
| 25 | + | # and the firewall's trusted-zone membership. Alloy's sudo asks for a password, | |
| 26 | + | # so a BatchMode ssh run answers thirteen of seventeen rows and says so. | |
| 21 | 27 | # build/check-host.sh --self-test # checks the harness; touches nothing | |
| 22 | 28 | # | |
| 23 | 29 | # Exit codes, following build/check-installed.sh: | |
| @@ -75,13 +81,20 @@ | |||
| 75 | 81 | # below can answer, and saying so is the honest result. | |
| 76 | 82 | . /etc/os-release 2>/dev/null || true | |
| 77 | 83 | [ "${ID:-}" = "alloy" ] || { printf 'error: not an Alloy machine (ID=%s)\n' "${ID:-unknown}" >&2; exit 3; } | |
| 78 | - | row PASS os "alloy ${VERSION_ID:-?} build ${ALLOY_BUILD_STAMP:-unstamped}" | |
| 84 | + | row PASS os "alloy ${VERSION_ID:-?} build ${IMAGE_VERSION:-unstamped}" | |
| 79 | 85 | ||
| 80 | 86 | # ------------------------------------------------------------------- image --- | |
| 81 | 87 | # `bootc status` is the row; parsing its JSON for the image name is a | |
| 82 | 88 | # convenience, so an output shape this does not recognise degrades to a plainer | |
| 83 | 89 | # detail rather than to a verdict. | |
| 84 | - | if have bootc; then | |
| 90 | + | # `bootc status` needs root: it opens the deployment for write before it will | |
| 91 | + | # answer. Reported as SKIP without it rather than as a failure, which is what | |
| 92 | + | # the first real run of this script got wrong on fw12 2026-09-03. | |
| 93 | + | if ! have bootc; then | |
| 94 | + | row FAIL image "no bootc on an image-based system" | |
| 95 | + | elif ! is_root; then | |
| 96 | + | row SKIP image "needs root: bootc status refuses an unprivileged caller" | |
| 97 | + | else | |
| 85 | 98 | if bootc status >/dev/null 2>&1; then | |
| 86 | 99 | booted="$(bootc status --format=json 2>/dev/null \ | |
| 87 | 100 | | tr -d ' \n' | grep -o '"image":"[^"]*"' | head -1 | cut -d'"' -f4)" | |
| @@ -89,8 +102,6 @@ | |||
| 89 | 102 | else | |
| 90 | 103 | row FAIL image "bootc is present and \`bootc status\` fails" | |
| 91 | 104 | fi | |
| 92 | - | else | |
| 93 | - | row FAIL image "no bootc on an image-based system" | |
| 94 | 105 | fi | |
| 95 | 106 | ||
| 96 | 107 | # ------------------------------------------------- labels, and what it costs -- | |
| @@ -164,15 +175,22 @@ | |||
| 164 | 175 | # The combination is the risk, not the firewall: tailscaled writes its own | |
| 165 | 176 | # rules, and firewalld starting without tailscale0 in the trusted zone drops | |
| 166 | 177 | # every inbound tailnet connection, which on a headless box is the login. | |
| 178 | + | # systemctl answers unprivileged; `firewall-cmd --state` does not, and reading | |
| 179 | + | # its refusal as "not running" reported a stopped firewall on a machine where | |
| 180 | + | # firewalld was enabled and active (fw12, 2026-09-03). | |
| 167 | 181 | if have firewall-cmd; then | |
| 168 | - | if firewall-cmd --state >/dev/null 2>&1; then | |
| 169 | - | if firewall-cmd --zone=trusted --query-interface=tailscale0 >/dev/null 2>&1; then | |
| 182 | + | if systemctl is-active firewalld >/dev/null 2>&1; then | |
| 183 | + | if ! is_root; then | |
| 184 | + | row SKIP firewall "running; the trusted-zone check needs root" | |
| 185 | + | elif firewall-cmd --zone=trusted --query-interface=tailscale0 >/dev/null 2>&1; then | |
| 170 | 186 | row PASS firewall "running, tailscale0 in the trusted zone" | |
| 171 | 187 | else | |
| 172 | 188 | row FAIL firewall "running, and tailscale0 is NOT trusted; inbound tailnet traffic is being dropped" | |
| 173 | 189 | fi | |
| 190 | + | elif systemctl is-enabled firewalld >/dev/null 2>&1; then | |
| 191 | + | row FAIL firewall "firewalld is enabled and not running" | |
| 174 | 192 | else | |
| 175 | - | row FAIL firewall "firewalld is installed and not running" | |
| 193 | + | row FAIL firewall "firewalld is installed and neither enabled nor running" | |
| 176 | 194 | fi | |
| 177 | 195 | else | |
| 178 | 196 | row SKIP firewall "no firewall-cmd in this image" | |
| @@ -244,7 +262,7 @@ | |||
| 244 | 262 | # The label is polkit's own wording; an unrecognised one leaves impl empty | |
| 245 | 263 | # and the row skips, because guessing here would report a prompt that is not | |
| 246 | 264 | # there or miss one that is. | |
| 247 | - | impl="$(pkaction --action-id org.freedesktop.UDisks2.filesystem-mount --verbose 2>/dev/null \ | |
| 265 | + | impl="$(pkaction --action-id org.freedesktop.udisks2.filesystem-mount --verbose 2>/dev/null \ | |
| 248 | 266 | | awk -F: '/implicit active/{gsub(/[[:space:]]/,"",$2); print $2; exit}')" | |
| 249 | 267 | case "$impl" in | |
| 250 | 268 | yes) row PASS udisks "filesystem-mount is allowed for an active session" ;; |