iso 1.27.1: the FIRST boot is Felhom's — postinst masks pvebanner and writes /etc/issue
gates / gates (push) Successful in 18s

The 1.27.0 proof install (VM 331, screen s20) still showed Proxmox's
":8006" block on the first boot: pvebanner.service ran before
felhom-bootstrap could mask it, and the Felhom text lost its o/u double
acutes (painted before the Latin-2 font loads).
- postinst: mask pvebanner by symlink (a file act, valid in the chroot) and
  write /etc/issue; both guarded, still exit 0 (G8 self-checks unchanged).
- bootstrap: same text, byte-identical, no o/u double acutes (second line).
- harness: PI scenario (postinst in a container) + no-accent checks, red
  first against the 1.27.0 code; 55/55 green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-14 17:55:08 +02:00
parent 63f29c6ad8
commit 27e8ec860c
4 changed files with 44 additions and 2 deletions
+1 -1
View File
@@ -48,7 +48,7 @@ set -euo pipefail
# does not exist: the ISO is a frozen artifact, while felhom-host-install.sh is fetched at RUN TIME
# from the website's git-sync of `main` (R-94/R-110), so whatever version an ISO carries, the script a
# box runs is always current. Coupling them would invent a constraint. The claim is corrected instead.
ISO_VERSION="1.27.0" # the ISO's own version. INDEPENDENT of felhom-host-install.sh's SCRIPT_VERSION,
ISO_VERSION="1.27.1" # the ISO's own version. INDEPENDENT of felhom-host-install.sh's SCRIPT_VERSION,
# which is fetched at run time from main and is not frozen into the image.
IMAGE="${FELHOM_ISO_ASSISTANT_IMAGE:-felhom-iso-assistant:trixie}"
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+5 -1
View File
@@ -83,6 +83,10 @@ print_pairing_banner() {
# in English. pvebanner.service REWRITES /etc/issue on every boot (/usr/bin/pvebanner opens it '>'), so
# overwriting the file alone would last one boot: the unit is MASKED, then the file is written.
# Best-effort in every step — a banner must never block the boot or the pairing.
# v1.27.1: the package postinst now does the same two acts at INSTALL time (the 1.27.0 proof install showed
# pvebanner running at the first boot before this function), so this is the second line of defence. The text
# must stay BYTE-IDENTICAL to the postinst's (harness PI pins it) and must avoid ő/ű: the login screen is
# painted before the Latin-2 console font loads, and 1.27.0 rendered „képernyőn" as „képernyon".
ISSUE_FILE="${FELHOM_ISSUE_FILE:-/etc/issue}"
install_felhom_issue() {
if command -v systemctl >/dev/null 2>&1; then
@@ -95,7 +99,7 @@ install_felhom_issue() {
local tmp="${ISSUE_FILE}.felhom-tmp"
if { printf '\n'
printf ' Felhom otthoni szerver\n\n'
printf ' Ezen a képernyőn nincs teendőd, bejelentkezni sem kell.\n'
printf ' Ezen a gépen most nincs dolgod, és bejelentkezni sem kell.\n'
printf ' A beállításhoz kövesd a Felhomtól kapott útmutatót.\n\n'
} > "$tmp" 2>/dev/null && mv -f "$tmp" "$ISSUE_FILE" 2>/dev/null; then
log "console: $ISSUE_FILE is the Felhom text (no admin URL)"
+20
View File
@@ -28,6 +28,26 @@ LOG=/var/log/felhom-bootstrap-postinst.log
chmod 0644 "$LOG" 2>/dev/null || true
if [ "${1:-}" = "configure" ]; then
# R-496 (v1.27.1): the console's login text is Felhom's from the FIRST boot. pvebanner.service rewrites
# /etc/issue with the Proxmox admin URL on every boot; on 1.27.0 it ran before felhom-bootstrap could
# mask it (proof install screen 331-s20). Masking is a SYMLINK to /dev/null — a file act, valid in this
# systemd-less chroot, like the wants-symlink fallback below. Both acts guarded; neither can fail the install.
mkdir -p /etc/systemd/system 2>/dev/null || true
if ln -sf /dev/null /etc/systemd/system/pvebanner.service 2>/dev/null; then
echo "felhom-bootstrap postinst: pvebanner.service masked (symlink)" >> "$LOG" 2>&1 || true
fi
# Byte-identical to felhom-bootstrap.sh install_felhom_issue (harness PI pins it). No ő/ű: the login
# screen is painted before the Latin-2 font loads.
if { printf '\n'
printf ' Felhom otthoni szerver\n\n'
printf ' Ezen a gépen most nincs dolgod, és bejelentkezni sem kell.\n'
printf ' A beállításhoz kövesd a Felhomtól kapott útmutatót.\n\n'
} > /etc/issue.felhom-tmp 2>/dev/null && mv -f /etc/issue.felhom-tmp /etc/issue 2>/dev/null; then
echo "felhom-bootstrap postinst: /etc/issue is the Felhom text" >> "$LOG" 2>&1 || true
else
rm -f /etc/issue.felhom-tmp 2>/dev/null || true
fi
# `enable` only. Guarded, and its outcome recorded either way.
if systemctl enable "$UNIT" >> "$LOG" 2>&1; then
echo "felhom-bootstrap postinst: enabled $UNIT via systemctl" >> "$LOG" 2>&1 || true
+18
View File
@@ -188,6 +188,9 @@ check "R-496: /etc/issue is the Felhom text" "grep -q 'Felhom otthoni s
check "R-496: /etc/issue carries no admin URL (:8006)" "! grep -q '8006' /work/issue"
check "R-496: /etc/issue does not say Proxmox" "! grep -qi 'proxmox' /work/issue"
check "R-496: pvebanner.service masked" "grep -q 'mask pvebanner.service' /work/systemctl.log"
# v1.27.1: the login screen is painted BEFORE the Latin-2 console font loads, so ő/ű in /etc/issue
# rendered as dropped letters on the 1.27.0 proof install („képernyon", „teendod", screen 331-s20).
check "R-496: /etc/issue carries no ő/ű (the boot font lacks them)" "! grep -q '[őűŐŰ]' /work/issue"
# ============ P: pairing loop (v1.21.0) — register, wait unbound INSIDE one invocation, deliver =====
say "P: pairing env -> register + in-script 204 wait -> 200 delivery -> host-install, ONE invocation"
@@ -282,6 +285,21 @@ check "interfaces untouched" "[ \"$PRE_SHA\" = \"$POST_SHA\"
check "console screen still painted" "grep -q 'Nincs hálózati kapcsolat' /work/console.out"
check "no-sweep branch logged" "grep -q 'no sweep, interfaces untouched' /work/run.log"
# ============ PI: the package postinst (v1.27.1) — the FIRST boot must already be Felhom's ===========
# Measured on the 1.27.0 proof install (screen 331-s20): pvebanner.service ran at the first boot BEFORE
# felhom-bootstrap could mask it, so the household's first screen still carried the Proxmox admin URL.
# The postinst runs in the installer chroot (no systemd): it may only write files. It masks by symlink.
say "PI: postinst configure -> pvebanner masked by symlink, /etc/issue is Felhom's, exit 0"
rm -f /etc/systemd/system/pvebanner.service /etc/issue /work/systemctl.log
printf '\nWelcome to the Proxmox Virtual Environment ... https://10.0.0.1:8006/\n' > /etc/issue
sh /work/postinst configure; rc=$?
check "PI: postinst exits 0" "[ $rc -eq 0 ]"
check "PI: pvebanner.service -> /dev/null (masked by file)" "[ \"\$(readlink /etc/systemd/system/pvebanner.service)\" = /dev/null ]"
check "PI: /etc/issue is the Felhom text" "grep -q 'Felhom otthoni szerver' /etc/issue"
check "PI: /etc/issue carries no admin URL" "! grep -q '8006' /etc/issue"
check "PI: /etc/issue carries no ő/ű" "! grep -q '[őűŐŰ]' /etc/issue"
check "PI: postinst and bootstrap write the SAME issue text" "cmp -s /etc/issue /work/issue"
echo "=================================================="
if [ $fail -eq 0 ]; then echo "ALL BOOTSTRAP-MODE TESTS PASSED"; else echo "SOME TESTS FAILED"; fi
exit $fail