Phase 3 of the fresh-install spec: the parts of a run that depend on what the machine actually is. NVIDIA, Secure Boot, Fedora's preinstalled extras, firmware. Two of these looked like they would force a compromise, and neither did. sunhat opened an editor in the middle of its run so grub could be hand-corrected, and that single step is why walking away from an install did not work. The step existed to delete duplicated kernel arguments -- and grubby replaces an argument that already exists rather than appending a second copy, so the duplicates cannot accumulate and there is nothing to correct. The editor was load-bearing for a problem that a different tool does not have. MOK enrolment needs a password now and the same password at the next boot's blue screen, which reads like a prompt that has to happen mid-run. mokutil has --generate-hash and --hash-file for exactly this: the interview asks, hashes it on the spot, and records only the hash. The plaintext never reaches the answers file, the environment, or a command line, and the stage runs without asking. The stage runs last rather than fourth as the spec's table had it. The constraint was always "late" and fourth of eight is not late: enrolment arms a prompt for the next boot and firmware may want a reboot, so a machine that reboots out of this stage should already be completely configured. Every question names what was found -- the card, the packages actually installed -- and is not asked at all on a machine it would do nothing to. sunhat's debloat list no longer describes Fedora 44: totem became showtime and LibreOffice is not preinstalled, so the list is curated and a package that is not installed is never passed to dnf, which is what lets it outlive a release. This stage cannot be verified by running it. It installs a proprietary driver and queues a Secure Boot enrolment, and this machine is an AMD desktop. So every privileged command is stood in on PATH and the contract asserts which answer led to which call: that no answers means no commands, that a failed driver install is not followed by arguments and services for a driver that is not there, that the hash reaches mokutil through a file and never a command line, and that removal is offered only for packages that are installed. The contract was checked by breaking the stage three ways and confirming it caught each. It does not verify that akmod-nvidia builds, and says so where a reader would otherwise assume it did. The README's stage table listed three of seven stages; the interview and identity work never reached it. Corrected rather than extended, since a table that lists three of seven is worse than one that lists none. The Desktops section still describes a GNOME session nothing installs -- that is phase 5. Claude-Session: https://claude.ai/code/session_01NvgBuSWB5sE43yWmg21ozj
137 lines
6.3 KiB
Bash
Executable File
137 lines
6.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# The parts of an install that depend on what the machine actually is: the
|
|
# NVIDIA driver, the machine owner key that lets it load under Secure Boot,
|
|
# Fedora's preinstalled extras, and firmware.
|
|
#
|
|
# Runs last. MOK enrolment arms a prompt consumed at the next boot and firmware
|
|
# updates can ask for a reboot, so neither belongs in front of the package work
|
|
# or the dotfiles -- a machine that reboots out of this stage has already been
|
|
# fully configured.
|
|
#
|
|
# Nothing here decides anything. Every branch is an answer the interview
|
|
# collected before the run began, and an absent answer means no, which is what
|
|
# makes this safe to re-run by hand while repairing one piece of a machine.
|
|
#
|
|
# sunhat's version of this opened an editor in the middle of the run so grub
|
|
# could be hand-corrected. That is the exact failure this repository exists to
|
|
# avoid, and it is unnecessary: grubby replaces an argument that already exists
|
|
# rather than appending a second copy, so the duplicates that had to be cleaned
|
|
# up by hand cannot accumulate in the first place.
|
|
|
|
set -uo pipefail
|
|
|
|
log() { echo -e "\033[1;34m[INFO]\033[0m $*"; }
|
|
warn() { echo -e "\033[1;33m[WARN]\033[0m $*" >&2; }
|
|
|
|
# Fedora ships these and Panama uses none of them. Named here rather than in the
|
|
# interview so there is one list: the interview asks for it with --debloat-list
|
|
# to name what it is about to remove, and this stage removes it. A package that
|
|
# is not installed is skipped rather than passed to dnf, so the list can outlive
|
|
# a Fedora release -- totem left in Fedora 43 and the list should not start
|
|
# failing because of it.
|
|
DEBLOAT=(gnome-contacts gnome-tour gnome-maps showtime)
|
|
|
|
if [[ "${1:-}" == "--debloat-list" ]]; then
|
|
printf '%s\n' "${DEBLOAT[@]}"
|
|
exit 0
|
|
fi
|
|
|
|
# ── NVIDIA ───────────────────────────────────────────────────────────────────
|
|
|
|
if [[ "${PANAMA_NVIDIA:-no}" == yes ]]; then
|
|
log "Installing the NVIDIA driver"
|
|
if sudo dnf install -y akmod-nvidia xorg-x11-drv-nvidia-cuda; then
|
|
# nouveau has to be out of the way before the kernel would otherwise
|
|
# bind it, which is why these are kernel arguments and not a modprobe
|
|
# drop-in. modeset=1 is what makes the Wayland session work at all.
|
|
if command -v grubby >/dev/null 2>&1; then
|
|
sudo grubby --update-kernel=ALL \
|
|
--args="rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1"
|
|
log "Kernel arguments set for every installed kernel"
|
|
else
|
|
warn "grubby is not installed; nouveau was not blacklisted"
|
|
fi
|
|
|
|
# Suspend and resume are where a proprietary driver most visibly fails.
|
|
# These units save and restore VRAM across it.
|
|
sudo systemctl enable nvidia-hibernate.service nvidia-suspend.service \
|
|
nvidia-resume.service nvidia-powerd.service
|
|
log "NVIDIA power management services enabled"
|
|
else
|
|
warn "The NVIDIA driver did not install; skipping its kernel arguments and services"
|
|
fi
|
|
fi
|
|
|
|
# ── Secure Boot ──────────────────────────────────────────────────────────────
|
|
#
|
|
# akmods signs the modules it builds with a key it generates on installation.
|
|
# Under Secure Boot that key means nothing until it is enrolled, and enrolment
|
|
# is deliberately a thing only somebody at the physical machine can complete:
|
|
# the request is queued here, and the next boot shows a blue screen asking for
|
|
# the password before it will trust the key.
|
|
#
|
|
# The password itself never reaches this stage. The interview hashed it and
|
|
# recorded the hash, so nothing readable is passed on a command line or left in
|
|
# this process's environment -- which is the whole reason mokutil has
|
|
# --generate-hash and --hash-file.
|
|
|
|
mok_hash="${PANAMA_MOK_HASH:-}"
|
|
if [[ -n "$mok_hash" ]]; then
|
|
# Overridable so the contract can exercise this against a certificate it is
|
|
# allowed to create. Nothing else sets it.
|
|
cert="${PANAMA_MOK_CERT:-/etc/pki/akmods/certs/public_key.der}"
|
|
|
|
if [[ ! -r "$cert" ]]; then
|
|
warn "No akmods certificate at $cert, so there is no key to enrol"
|
|
elif mokutil --test-key "$cert" 2>/dev/null | grep -q 'already enrolled'; then
|
|
log "The akmods key is already enrolled"
|
|
else
|
|
hash_file="$(mktemp -t panama-mok.XXXXXX)"
|
|
chmod 600 "$hash_file"
|
|
printf '%s\n' "$mok_hash" >"$hash_file"
|
|
if sudo mokutil --import "$cert" --hash-file "$hash_file"; then
|
|
log "Key enrolment requested"
|
|
log "At the next boot, choose 'Enrol MOK' and enter the password you gave the installer"
|
|
else
|
|
warn "Key enrolment failed; the NVIDIA module will not load until it is enrolled"
|
|
fi
|
|
rm -f "$hash_file"
|
|
fi
|
|
fi
|
|
|
|
# ── Fedora's preinstalled extras ─────────────────────────────────────────────
|
|
|
|
if [[ "${PANAMA_DEBLOAT:-no}" == yes ]]; then
|
|
present=()
|
|
for package in "${DEBLOAT[@]}"; do
|
|
rpm -q "$package" >/dev/null 2>&1 && present+=("$package")
|
|
done
|
|
|
|
if (( ${#present[@]} > 0 )); then
|
|
log "Removing ${present[*]}"
|
|
sudo dnf remove -y "${present[@]}" >/dev/null \
|
|
|| warn "Some packages could not be removed"
|
|
else
|
|
log "None of Fedora's extras are installed"
|
|
fi
|
|
fi
|
|
|
|
# ── Firmware ─────────────────────────────────────────────────────────────────
|
|
#
|
|
# Panama's Updates page covers this from then on; the installer covers the
|
|
# first run. --no-reboot-check because deciding to reboot is not this stage's
|
|
# call to make in the middle of an unattended install.
|
|
|
|
if [[ "${PANAMA_FIRMWARE:-no}" == yes ]]; then
|
|
if command -v fwupdmgr >/dev/null 2>&1; then
|
|
log "Refreshing firmware metadata"
|
|
sudo fwupdmgr refresh --force >/dev/null 2>&1
|
|
log "Applying firmware updates"
|
|
sudo fwupdmgr update -y --no-reboot-check \
|
|
|| log "No firmware updates were applied"
|
|
else
|
|
warn "fwupdmgr is not installed; skipping firmware"
|
|
fi
|
|
fi
|