max / alloy
1 file changed,
+47 insertions,
-3 deletions
| @@ -280,9 +280,53 @@ | |||
| 280 | 280 | Recipe values go in ahead of anything typed on the command line, so an explicit | |
| 281 | 281 | `--build-arg` overrides the recipe rather than racing it. | |
| 282 | 282 | ||
| 283 | - | What the three recipes say today: fw12 is a stock client mint and sets nothing; | |
| 284 | - | fw13 takes `LANGS=rust,js` and `DB=postgres16` for the build-host role; astra | |
| 285 | - | takes those plus `PROFILE=server` and `ARCH=aarch64`. | |
| 283 | + | What the three recipes say today: fw13 takes `LANGS=rust,js` and | |
| 284 | + | `DB=postgres16` for the build-host role; astra takes those plus | |
| 285 | + | `PROFILE=server` and `ARCH=aarch64`; fw12 sets no dials at all and carries only | |
| 286 | + | identity and answers, below. | |
| 287 | + | ||
| 288 | + | ## The answer sheet | |
| 289 | + | ||
| 290 | + | A recipe can also answer the questions `alloy install` would otherwise ask. The | |
| 291 | + | identity step writes them to `/usr/lib/alloy/answers.toml`, beside the baked | |
| 292 | + | `authorized_keys`, and `crates/alloy/src/preseed.rs` reads that file once when | |
| 293 | + | the wizard opens. A step the sheet answers in full is skipped. | |
| 294 | + | ||
| 295 | + | | Argument | Answers | Notes | | |
| 296 | + | |---|---|---| | |
| 297 | + | | `ALLOY_HOSTNAME` | the machine's name | also rewrites `DEFAULT_HOSTNAME`; the build asserts the two agree | | |
| 298 | + | | `ALLOY_USERNAME` | the account to create | the password is never here | | |
| 299 | + | | `ALLOY_DISK` | which disk | `single-internal` or `single-internal-nvme`; a device path is refused | | |
| 300 | + | | `ALLOY_ENCRYPT` | the encryption checkbox | `yes` leaves the passphrase to be typed; `no` answers the whole step | | |
| 301 | + | | `ALLOY_LOCATE_TIMEZONE` | the timezone lookup | both this and the hostname are needed to skip that step | | |
| 302 | + | ||
| 303 | + | Two rules govern what may go in, and neither is a preference. | |
| 304 | + | ||
| 305 | + | **No secrets, ever.** Not the account password, not the LUKS passphrase. The | |
| 306 | + | identity step's own comment states the invariant: the image "can be kept, copied | |
| 307 | + | or rebuilt without care and a leak of it costs nothing". A passphrase written | |
| 308 | + | into the sheet would be in every layer cache, in every `podman save`, and on | |
| 309 | + | every stick written from the medium. So the account and encryption steps are | |
| 310 | + | still shown, with everything except the secret already filled in. A fully | |
| 311 | + | unattended install is not what this buys, and saying otherwise would be a lie | |
| 312 | + | about where the secrets are. | |
| 313 | + | ||
| 314 | + | **The disk is a rule, not a path.** `single-internal-nvme` means "the one | |
| 315 | + | non-removable NVMe in this machine", and a rule that matches nothing, or matches | |
| 316 | + | two, falls back to asking and says why in the status line. A medium that erased | |
| 317 | + | `/dev/nvme0n1` on sight would be one wrong laptop away from erasing the wrong | |
| 318 | + | machine. | |
| 319 | + | ||
| 320 | + | What that leaves for fw12, whose recipe answers everything it can: the disk and | |
| 321 | + | hostname steps are skipped, the account step opens with the username and ssh key | |
| 322 | + | already in it and the password to type, and the encryption step opens with the | |
| 323 | + | box ticked and the passphrase to type. The review names every answer that came | |
| 324 | + | from the medium, because a screen whose job is to be checked has to say which | |
| 325 | + | lines nobody typed. | |
| 326 | + | ||
| 327 | + | `build/vmtest/install_preseeded.py` drives exactly that install in a VM, and | |
| 328 | + | `crates/alloy/tests/answer_sheet.rs` pins the Containerfile and the installer to | |
| 329 | + | the same keys and the same disk vocabulary, since neither can see the other. | |
| 286 | 330 | ||
| 287 | 331 | ## Version fields | |
| 288 | 332 |