From 5b0cc80d0a8e8cfa5b602951047cb5d70ebafd3b Mon Sep 17 00:00:00 2001 From: Aaron Date: Sat, 3 Jan 2026 17:51:11 -0500 Subject: [PATCH] Fix firstboot tls bundle script and prep checks --- pikit-prep.sh | 45 +++++++++++++++++++++++++++++--------- pikit-smoke-test.sh | 19 +++++++++++++++- systemd/pikit-firstboot.sh | 16 +++++++------- 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/pikit-prep.sh b/pikit-prep.sh index 9e089ac..69821d8 100755 --- a/pikit-prep.sh +++ b/pikit-prep.sh @@ -23,6 +23,7 @@ DID_PREP=0 ERRORS=0 WARNINGS=0 +STOPPED_PIHOLE_FTL=0 usage() { cat <<'USAGE' @@ -211,14 +212,14 @@ reset_iface_to_dhcp() { local tmp tmp="$(mktemp)" awk -v target="$iface" ' - BEGIN{in=0} + BEGIN{in_iface=0} /^[[:space:]]*iface[[:space:]]+/ { split($0, parts, /[[:space:]]+/); - if (parts[2]==target) { in=1; print "iface " target " inet dhcp"; next; } - else { in=0; } + if (parts[2]==target) { in_iface=1; print "iface " target " inet dhcp"; next; } + else { in_iface=0; } } { - if (in==1) { + if (in_iface==1) { if ($1=="address"||$1=="netmask"||$1=="gateway"||$1=="dns-nameservers") next; } print; @@ -321,7 +322,14 @@ prep_image() { fi if command -v pihole >/dev/null 2>&1; then - pihole -f >/dev/null 2>&1 && status CLEANED "pihole logs via pihole -f" || status FAIL "pihole -f" + if command -v systemctl >/dev/null 2>&1; then + if systemctl stop pihole-FTL >/dev/null 2>&1; then + status CLEANED "stopped pihole-FTL" + STOPPED_PIHOLE_FTL=1 + else + status WARN "unable to stop pihole-FTL" + fi + fi clean_logs_dir /var/log/pihole '*' clean_file /etc/pihole/pihole-FTL.db clean_file /etc/pihole/pihole-FTL.db-wal @@ -609,12 +617,22 @@ check_image() { section "Logs" if [ -d /var/log ]; then - local nonempty - nonempty="$(find /var/log -type f -size +0c 2>/dev/null | wc -l | tr -d ' ')" - if [ "$nonempty" -gt 0 ]; then - status WARN "/var/log has non-empty files: $nonempty" + local nonempty filtered + nonempty="$(find /var/log -type f -size +0c 2>/dev/null)" + filtered="$(printf "%s\n" "$nonempty" | grep -Ev '/(lastlog|faillog|btmp|wtmp)$' || true)" + if [ -n "$filtered" ]; then + local count + count="$(printf "%s\n" "$filtered" | wc -l | tr -d ' ')" + status WARN "/var/log has non-empty files: $count" + printf "%s\n" "$filtered" | head -n 5 | sed 's/^/[WARN] /' else - status OK "/var/log empty" + if [ -n "$nonempty" ]; then + local count + count="$(printf "%s\n" "$nonempty" | wc -l | tr -d ' ')" + status WARN "/var/log has only login tracking files: $count" + else + status OK "/var/log empty" + fi fi else status WARN "/var/log missing" @@ -713,6 +731,13 @@ maybe_shutdown() { status OK "Shutting down" shutdown -f now || status FAIL "shutdown" else + if [ "$STOPPED_PIHOLE_FTL" -eq 1 ] && command -v systemctl >/dev/null 2>&1; then + if systemctl start pihole-FTL >/dev/null 2>&1; then + status OK "restarted pihole-FTL (shutdown skipped)" + else + status WARN "failed to restart pihole-FTL after prep" + fi + fi status OK "Shutdown skipped" fi } diff --git a/pikit-smoke-test.sh b/pikit-smoke-test.sh index 519f8ff..e45b246 100755 --- a/pikit-smoke-test.sh +++ b/pikit-smoke-test.sh @@ -169,6 +169,7 @@ sys.exit(1) check_firstboot() { local url="$1" local body state error_present + local done_present error_file_present log_present state_present if ! body="$(remote_cmd "curl -fsS --max-time 5 $url")"; then status FAIL "firstboot API not reachable" return @@ -186,10 +187,26 @@ check_firstboot() { status FAIL "firstboot status invalid or missing" return fi + done_present="$(remote_sudo_cmd "test -f /var/lib/pikit/firstboot/firstboot.done && echo yes || echo no" 2>/dev/null || true)" + error_file_present="$(remote_sudo_cmd "test -f /var/lib/pikit/firstboot/firstboot.error && echo yes || echo no" 2>/dev/null || true)" + log_present="$(remote_sudo_cmd "test -f /var/lib/pikit/firstboot/firstboot.log && echo yes || echo no" 2>/dev/null || true)" + state_present="$(remote_sudo_cmd "test -f /var/lib/pikit/firstboot/state.json && echo yes || echo no" 2>/dev/null || true)" if [ "$state" = "done" ] && [ "$error_present" != "true" ]; then status OK "firstboot completed" + return + fi + if [ "$state" = "error" ] || [ "$error_present" = "true" ] || [ "$error_file_present" = "yes" ]; then + status FAIL "firstboot failed (state=$state error=$error_present)" + return + fi + if [ "$done_present" = "yes" ]; then + status FAIL "firstboot state mismatch (done file present but state=$state)" + return + fi + if [ "$log_present" != "yes" ] && [ "$state_present" != "yes" ]; then + status WARN "firstboot not started yet (image prepped?)" else - status FAIL "firstboot not complete (state=$state error=$error_present)" + status WARN "firstboot in progress (state=$state)" fi } diff --git a/systemd/pikit-firstboot.sh b/systemd/pikit-firstboot.sh index f001072..6a32ef1 100755 --- a/systemd/pikit-firstboot.sh +++ b/systemd/pikit-firstboot.sh @@ -215,11 +215,11 @@ if isinstance(actions, list) and actions: log(f"TLS bundle skipped (missing cert/key): {dest}") continue dest.parent.mkdir(parents=True, exist_ok=True) - content = src_cert.read_bytes() + b\"\\n\" + src_key.read_bytes() + b\"\\n\" + content = src_cert.read_bytes() + b"\n" + src_key.read_bytes() + b"\n" dest.write_bytes(content) owner = action.get("owner") if owner: - user, _, group = str(owner).partition(\":\") + user, _, group = str(owner).partition(":") try: uid = pwd.getpwnam(user).pw_uid if user else -1 except Exception: @@ -238,8 +238,8 @@ if isinstance(actions, list) and actions: pass restart = action.get("restart") if restart: - subprocess.run([\"systemctl\", \"restart\", str(restart)], check=False) - log(f\"TLS bundle written: {dest}\") + subprocess.run(["systemctl", "restart", str(restart)], check=False) + log(f"TLS bundle written: {dest}") continue if action_type == "replace_text": @@ -247,17 +247,17 @@ if isinstance(actions, list) and actions: match = str(action.get("match", "")) replacement = str(action.get("replace", "")) if not file_path.exists(): - log(f\"Replace skipped (missing file): {file_path}\") + log(f"Replace skipped (missing file): {file_path}") continue content = file_path.read_text() if match not in content: - log(f\"Replace skipped (pattern not found): {file_path}\") + log(f"Replace skipped (pattern not found): {file_path}") continue file_path.write_text(content.replace(match, replacement, 1)) restart = action.get("restart") if restart: - subprocess.run([\"systemctl\", \"restart\", str(restart)], check=False) - log(f\"Replaced text in: {file_path}\") + subprocess.run(["systemctl", "restart", str(restart)], check=False) + log(f"Replaced text in: {file_path}") continue else: log("Profile actions step skipped (none).")