Skip to content

fix: no silent gap between first boot screens; keep a root password set at creation - #35

Merged
marcos-mendez merged 4 commits into
masterfrom
fix/firstboot-wait-and-keep-password
Oct 2, 2026
Merged

marcos-mendez merged 4 commits into
masterfrom
fix/firstboot-wait-and-keep-password

Conversation

@marcos-mendez

@marcos-mendez marcos-mendez commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

What the maintainer saw

Proxmox VE 9.2.11, an LXC container from the step8 Web image, root password set in pct create. On the console he chose Generate and pressed . The console then stayed on "Did you save the password?" for a while and came back by itself.

What runs in that gap

I reproduced it on LXC (freeze-test on the test VM, root password set with chpasswd in the rootfs before first boot, tty1 driven with lxc-console -t 1 in tmux). Nothing hangs and no dialog goes to a pipe: ps -ef --forest at the gap shows run > 80keel-cloud > keelfirstboot.py cloud > dialog, with dialog's fds 0 and 1 on /dev/lxc/tty1. The gap is time in which nothing draws:

step after full CPU 0.25 CPU
boot wait before 30turnkey-init-fence, 75keel-role, 80keel-cloud (11 systemctl is-system-running each, up to 10 s of sleep each while the system is still starting) ~0.1 s ~3.5 s
75keel-role: keel inspect to find a database engine the Web image does not have 2 s 7.7 s
80keel-cloud up to its screen <1 s ~3 s
total, to Keel Cloud 2 s 15 s

On a host where the system is still starting when the wizard runs (slow units, DHCP), the boot wait adds 10 s before every hook from 30 on, 30 s before the Keel Cloud screen.

Changes

  • run: waits for a starting system once per run and stops as soon as it is up. Each first boot hook is named on the terminal while it runs, in an infobox with the first boot backtitle ("Configuring keel-role... please wait"), and so is the wait. Nothing is drawn off a terminal or with REDIRECT_OUTPUT; a notice that cannot be drawn is not an error.
  • setpass.py / Dialog.get_password(keep=...): when root can already log in with a password at first boot (passwd -S says P), the menu offers Keep first, as the default and recommendation ("Password set when the container was created (recommended)"), with Generate and Manual below. Keep is offered only for a password the image did not ship (review finding): passwd -S says P, the image carries /etc/keel/build-date (fix: images ship root locked, or the build fails; stamp the build date common#31, whose seal-root fails any build that does not ship root locked) and the shadow last-change day is on or after it, and the shadow field is neither empty nor U6aMy0wojraho. The field is compared, never printed or logged (asserted in every setpass test); an image without the date, such as every image built before common#31, gets no Keep. The same day counts because shadow keeps whole days and a container is often created on its image's build day. No prior password, preseeded ROOT_PASS, secrets.root_password and keel-init are unchanged. The image already ships root as * (checked in the step8 Web tar.zst).
  • Menus are drawn wide enough for their longest entry, up to 76 columns (measured on an 80 column tty1).
  • 30rootpass reads INITHOOKS_DEFAULT like the other hooks.

With the fix and confconsole's companion PR, at 0.25 CPU the gap from to Keel Cloud is 7.7 s (was 15 s), and the screen reads "Configuring ... please wait" throughout.

Tests (written first, RED on master)

  • tests/test-firstboot-pty.bats (new): run, the real 30rootpass, setpass.py and dialog on a pty under script; keys are typed when their screen reaches the pty, with a timeout on the whole run. Generate then Saved, New, Manual, Keep, Generate below Keep and a preseeded password each reach the next hook's screen. It fails on a hang and on a screen drawn into a pipe (both guards have their own test). On master, the Keep test and the notice check fail. CI installs dialog python3-dialog for it.
  • tests/test-run.bats: the boot wait happens once and ends when the system is up; notices on a terminal only, not for everyboot hooks, not with REDIRECT_OUTPUT, and a failing notice does not stop the run.
  • tests/test_setpass.py, tests/test_dialog_wrapper.py: Keep offered only for status P, first and the only recommendation, None returned, chpasswd not run, passwd failures mean no Keep, no file read, keel-init and preseed unchanged, text fits the menu.

Run: Python 405 passed locally; bats 260 locally (pty file skipped without dialog) and the pty file 8/8 inside the container.

Test plan

  • CI green (shell coverage with the pty test, Python coverage, changelog)
  • Build an image with this and confconsole keel12; first boot with pct create --password: Keep is first, Enter goes to Keel Cloud with "please wait" in between
  • Same image without a password: Generate then Saved, and Manual, unchanged and no frozen screen

navigator added 3 commits October 2, 2026 13:49
…et at creation

On a Proxmox VE container of the step8 Web image the console stayed on
"Did you save the password?" after <Saved> until the Keel Cloud screen
came. Nothing hung. Measured on LXC: 2 s, 15 s with a quarter of a CPU,
spent in the boot wait (before every hook from 30 on, eleven systemctl
calls and up to 10 s of sleep each while the system is starting) and in
75keel-role's keel inspect, with nothing new on the screen.

run waits for a starting system once per run and stops as soon as it is
up; each first boot hook, and the wait, is named on the terminal in a
box with the first boot backtitle ("Configuring keel-role... please
wait"). Nothing is drawn off a terminal or with REDIRECT_OUTPUT.

The password screen offers Keep first when root can already log in with
a password at first boot (pct create --password, LXC writing
/etc/shadow): passwd -S is the only question, the hash is never read.
No prior password, a preseeded ROOT_PASS, secrets.root_password and
keel-init behave as before.

tests/test-firstboot-pty.bats runs run, 30rootpass, setpass.py and the
real dialog on a pty under script, with a timeout, and fails on a hang
or on a screen drawn into a pipe.
dialog_wrapper logged to /var/log/dialog.log unconditionally, so setpass.py
failed for the CI runner's user and every password screen of the pty test
was missing. DIALOG_LOG names another file; the test points it into its
scratch directory and lets PYTHONPATH carry what the caller set. The Keep
assertion reads the recommendation, which a runner outside a container
shows too.
Review of #35: passwd -S says P for a password a build with ROOT_PASS
left, and for U6aMy0wojraho, which five older WordPress images ship, so
Keep was offered as recommended for a password every copy shares.

Keep now also needs the image's build date (/etc/keel/build-date, from
common's seal-root, which fails a build whose root is not locked) and a
last change on or after it, and a shadow field that is neither empty nor
a known placeholder. The field is compared, never printed or logged; an
image without the date gets no Keep.
@marcos-mendez
marcos-mendez merged commit c4dcd84 into master Oct 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant