Rehearse the headless installer in a lab
Use this exercise to understand how msip-drive answers an installerd
conversation. It simulates an installation against an invented disk. For an
actual installation, use Installing to disk.
1. Prepare a private, disposable lab #
Use a disposable lab instance with the matching installerd and msip-drive
binaries and an account allowed to use its lab socket. Create a new private
directory, restrict access using the lab system's access controls, and verify
that protection before starting. In each terminal, set LAB to that directory's
absolute path. The examples do not create or protect the directory for you.
Keep any saved output there and use only synthetic, nonsensitive data.
These are daemon startup effects, including warning-only socket security. Dry-run does not partition, format, or copy to the target disk; it is not a side-effect-free or fully isolated mode.
Save this JSON as inventory.json in that directory:
The device is deliberately invented, not a real target to substitute later. Omitted fields have schema defaults. Always supply the inventory: without it, dry-run still probes this machine's block devices and controllers. With it, the executor uses the supplied synthetic inventory.
2. Start only the lab daemon #
In the first terminal, with LAB set and verified:
Before starting a client, check that daemon output explicitly says
installerd (dry run) listening on followed by the exact private socket path.
Stop if the mode, path, or security checks are wrong. Leave the daemon running;
do not connect any other surface to it. Use a fresh directory and daemon for
each attempt rather than reusing an uncertain conversation.
3. Drive the synthetic conversation #
In the second terminal, with LAB set to the same verified directory:
The last action is intentional: successful job execution produces a finish
page, not an ended conversation. The dry-run executor's restart
returns success without rebooting the machine. Do not remove --dry-run
or aim this sequence at a real service.
The expected sequence below is inferred from the flow and client, not captured test output:
bound:reports a conversation ID andattached=false.- Turns advance through
mode,disk.choose,confirm,install.progress, andinstall.done. The client waits on the progress turn. act.rebootproduces== end: Complete Restarting the machine.and the client exits with status0for that completed conversation.
install.done means the executor reported job success. End Complete means
the restart request was accepted or simulated; neither proves a restart or
successful disk boot. A real restart request is accepted when
svctl shutdown reboot returns success.
In this lab, no disk installation or reboot takes place. Simulated percentages
do not verify partitioning, copying, image integrity, cleanup, or bootability.
If it stalls or reconnects #
Do not blindly replay the command. The client's Start implicitly joins
the daemon's one live, in-memory conversation and replays its current turn.
It has no conversation-ID guard and can consume a queued action immediately;
checking printed attached=true is not a barrier before an action runs.
If that appears in this fresh-lab exercise, stop the attempt and investigate
the unexpected state. The new private daemon and exclusive socket are the
precondition, not a check performed by the client.
Disconnecting the client does not cancel the daemon's job. A daemon restart
loses the in-memory conversation; a failed or completed conversation is also
cleared, so a later Start opens a new one. This is not durable recovery.
See job lifetime
and disconnect and Start handling.
The driver consumes actions only on NewTurn, not same-turn Updated events.
A rescan or rejected input/reboot can therefore leave it waiting indefinitely,
even with more presses queued. It has no built-in timeout. An external watchdog
that stops the client neither cancels the job nor undoes changes. A client with
no presses is not a persistent observer: it exits with status 1 when an
actionable turn arrives. These limits follow from the
client loop
and same-turn rejection/patch handling.
Keep the evidence in scope #
- Protect inventory, console output, and logs. Do not add credentials or
first-boot account setup to this exercise.
--setvalues are command-line arguments; only daemon-marked secret elements are masked in the client trace. The client also prints only the last three stored log lines per update, so its output is not a unique, exhaustive audit journal. See trace handling and log rendering. - The checked-in VM queue-inspection script
omits
act.rebootand logs, rather than asserts, the client's exit status. At this revision, a successful job reaches the actionable done turn with no presses left, so the client exits1. That script is not proof of a completed headless conversation; do not copy its real-device or mounting commands here. - When finished, stop only the dedicated lab daemon. A real unattended-install guide still needs runtime validation of the shipped binaries, failure and reconnect handling, and independent checks of the installed disk and boot.