Ubuntu 24.04, Debian 12, Arch and Fedora 41. OS and package-manager detection
correct on all four; --help works unprivileged; and the install report is written
end to end in a container that had never seen this code — task 1's mechanism
confirmed off the machine it was written on.
Three real findings.
--only does not isolate a step. Running --only "Core utils" still created a user
account, because ask_username and the account creation sit in the preamble above
the step framework, so everything before the first `step` runs every time. It is
defensible and it is not what the flag appears to promise.
.setup-answers travels with a copy of the tree. Correctly gitignored and 0600,
but it lives inside the repository directory, so `cp -r` carries it — a container
that had never run setup came up already knowing the username and created that
account. Nothing secret in it; it is a surprise, which in an installer is the
expensive kind.
adduser leaks its own interactive prompt ("Try again? [y/N]") on the
account-creation path. Harmless here because the run had already stopped, but a
hang on a real unattended install.
Also records what containers cannot reach: no init means systemd, netplan, ufw
and the sshd drop-ins are only verifiable as "wrote the right file"; Docker and
Postgres are untested; macOS is unreachable entirely and everything about it is
reasoned rather than executed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
75 lines
3.1 KiB
Markdown
75 lines
3.1 KiB
Markdown
# Testing the installer in containers
|
|
|
|
**2026-08-13.** First pass. Ubuntu 24.04, Debian 12, Arch, Fedora 41.
|
|
|
|
## What passed
|
|
|
|
**OS and package-manager detection is correct on all four.**
|
|
|
|
| image | `OS` | `PM` |
|
|
| --- | --- | --- |
|
|
| ubuntu:24.04 | `ubuntu` | `apt` |
|
|
| debian:12 | `debian` | `apt` |
|
|
| archlinux | `arch` | `pacman` |
|
|
| fedora:41 | `fedora` | `dnf` |
|
|
|
|
**`--help` and argument handling work unprivileged** in a clean container, before any escalation.
|
|
|
|
**The install report is written**, end to end, in a container that had never seen this code. That is
|
|
task 1's mechanism confirmed outside the machine it was written on.
|
|
|
|
**Refusing beats hanging.** With no answer available the run stopped with
|
|
`FAIL: No answer. Set ASSUME_YES=1 to run without prompts.` rather than blocking forever on a prompt
|
|
nobody could see. That is the behaviour an unattended run needs, and it already exists.
|
|
|
|
---
|
|
|
|
## What it found
|
|
|
|
### 1. `--only` does not isolate a step
|
|
|
|
Running `--only "Core utils"` still **created a user account**, because `ask_username` and the
|
|
account creation happen in the preamble, above the step framework. Everything before the first
|
|
`step` call runs on every invocation.
|
|
|
|
Defensible — every step needs to know who it is installing for — but it means `--only` is not the
|
|
surgical tool it appears to be, and a first-time reader will assume it is. Either the preamble
|
|
becomes lazy, or `--only` says plainly what it will still do.
|
|
|
|
### 2. `.setup-answers` travels with a copy of the tree
|
|
|
|
It lives at `scripts/setup/machine-setup/.setup-answers`, is correctly gitignored, and is `0600`
|
|
root-owned. But it is **inside the repository directory**, so `cp -r` or a tarball of the tree
|
|
carries it — which is exactly what happened here: a container that had never run setup came up
|
|
already knowing the username `pastilhas` and created that account.
|
|
|
|
Not a leak (username and install path, nothing secret). It is a surprise, and surprises in an
|
|
installer are the expensive kind. Worth moving outside the repo, next to the progress file.
|
|
|
|
### 3. `adduser` leaks its own prompts
|
|
|
|
```
|
|
Use of uninitialized value $answer in pattern match (m//) at /usr/sbin/adduser line 848.
|
|
Try again? [y/N]
|
|
```
|
|
|
|
The account-creation path reaches an interactive `adduser` question the script does not answer.
|
|
Harmless here because the run stopped anyway, but on a real unattended install this is a hang.
|
|
|
|
---
|
|
|
|
## Coverage this cannot reach
|
|
|
|
Containers have no init by default, so **`systemctl`, netplan, ufw and the sshd drop-ins were not
|
|
exercised**. Those sections can only be verified as "wrote the right file", not "the service came
|
|
up". Running privileged containers with systemd would close most of that gap and is the obvious next
|
|
step.
|
|
|
|
**Docker-in-Docker** was not attempted, so the Docker section and Postgres provisioning are
|
|
untested. Mounting the host socket would test the section's logic while telling us nothing about the
|
|
install path.
|
|
|
|
**macOS is untestable here entirely.** The 17 skipped sections, the Homebrew paths, the Xcode
|
|
command line tools step and the refusal-to-run-as-root are all reasoned from documentation and
|
|
unverified by execution.
|