Commit Graph
78 Commits
Author SHA1 Message Date
17532793fd [INSTALL SPEED] Configure target keyboard without temporary boot (#93)
* Configure target keyboard without temporary boot

* Slim the offline keyboard configuration to what Omarchy consumes

Drop the Xorg 00-keyboard.conf writer: the installed system only reads
the XKB* settings in vconsole.conf (via detect-keyboard-layout.sh, which
copies XKBLAYOUT/XKBVARIANT into Hyprland's kb_layout), and nothing on
an Omarchy system reads xorg.conf.d. systemd-firstboot already writes
those vconsole settings.

Drop the set_keyboard_language monkey-patch: passing an empty kb_layout
to minimal_installation takes archinstall's documented skip path (no
nspawn boot), and the keymap is configured offline right after instead.

Append the preserved FONT= line instead of reproducing localectl's exact
file layout, and slim the tests to the behavior that matters: XKB
settings present, font preserved, every configurator keymap valid, and
archinstall-compatible invalid/empty handling.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 20:00:56 -05:00
N1R4 0b4d74f6af Filter phantom entries when rewriting EFI BootOrder (#94)
The Limine registration helper rebuilds the UEFI BootOrder from the
pre-state read, but passes every entry through verbatim. Some firmware
(listed in the BootOrder but with no matching BootXXXX variable) causes
efibootmgr --bootorder to fail with exit status 8, aborting the whole
install at the bootloader step.

Only carry forward entries that still exist as boot variables.
2026-08-01 13:07:09 -05:00
b3cf0c6f29 Run the live CPUs at the performance governor during install (#89)
archiso boots on whatever governor the kernel defaults to, which on most
laptops ramps conservatively. Package extraction and the UKI build are both
CPU-bound, so pin performance for the whole install and put it back afterwards.

Reduced from #87 by @davydotcom, which also disabled every non-POLL cpuidle
state. That half is left out deliberately: C1 wake latency is 1us on current
hardware, and disabling it leaves POLL as the only idle state, so idle cores
busy-spin instead of halting. Package extraction is single-threaded, so on an
8-core laptop that is 7 cores burning power for no work — on a thermally
limited machine that costs the working core its turbo headroom, which is a
plausible way to make the install slower. #87 measured the two tweaks together
with a page-cache prefetch and an updatedb deferral, so the C-state
contribution was never isolated.

Scoped to the whole install rather than just the pacstrap window, which #87
used: finalize_limine_boot runs mkinitcpio and compresses a UKI, and is the
most purely CPU-bound phase there is.

Restoring only matters when an install fails and the user keeps using the live
environment; a successful one reboots out of it.

Co-authored-by: David Estes <davydotcom@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 08:24:13 -07:00
David Heinemeier HanssonandClaude Opus 5 4f60a18c87 Drive the install bar from packages, not from a stopwatch
install_progress() mapped each phase to a start%, an end% and a hard-coded
"expected seconds", then interpolated on elapsed time. Those seconds were
calibrated on one machine, so the bar was only ever honest on that machine.
Measured against a real 69s install on an XPS 13, the table expected 145s: 95s
for a phase that took 58.6s, 10s for one that took 2.6s. On slow media it is
wrong the other way — the bar reaches each phase's ceiling in a fraction of the
real time and then sits there. Today's clamp turns that into a 386-second freeze
at 85% on a USB2 install.

Phases do not even scale together: package installation is bound by media read
and disk write, the UKI rebuild is CPU and compression bound. No single seconds
table can be right for both.

So stop predicting durations. Position is now max(floor, work), both
non-decreasing:

  floor  an asymptote over the phase's band, on time since this process first
         saw the phase. tau is a shape constant, not a prediction — wrong by 3x
         it changes the pace of a crawl, never the correctness.
  work   only for "Installing Arch + Omarchy", which is ~85% of the install.
         libalpm creates one directory per package under
         <target>/var/lib/pacman/local, so counting them counts finished work.
         The denominator is resolved at ISO build time by pacman's own resolver
         against the offline mirror, so there is no second package list to
         drift. phases.py records expected and actual in the timing JSON on
         every install, so drift shows up in acceptance runs.

There is deliberately no give-up predicate: two discontinuous curves selected by
a toggle, behind a monotonic clamp, is a freeze generator. If the signal never
appears — no denominator, wrong target, implausible count — the floor alone
still walks the band to its end.

Position moves to per-mille. That is load-bearing, not precision theatre: these
are asymptotes, and in whole percent an asymptote over a 2-point band has two
reachable values and stops moving within seconds.

Time now comes from /proc/uptime. The live ISO runs tzupdate and
systemd-timesyncd, and the old code read EPOCHSECONDS, so a clock step
mid-install jumped every band straight to its ceiling.

Also fixes drift the old table had accumulated: it still weighted five phases
that no longer exist and had no entry at all for "Preparing install target",
which fell through to a 1->99 sweep. Unknown names now derive an even band from
the index the orchestrator already publishes.

bin/omarchy-iso-installer fakes a pacman database so the preview exercises the
package path instead of the fallback; PREVIEW_PACKAGES tunes the count.

Verified by simulation against the real logic: a 69s NVMe install, a 6-minute
USB2 install with a 70s pre-extraction stall, an implausible denominator, an
unknown phase name, and a target that already holds packages. All monotonic, all
reach 100%. Not yet run on real hardware.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 07:54:05 -07:00
David Heinemeier HanssonandClaude Opus 5 e47ce379ad Drop gum from the orchestrator's progress lines
The dashboard owns the visible UI: it captures the orchestrator's stdout into
the support log and strips CSI sequences on the way in, so the colouring was
never seen by anyone. gum charged a Go process start per line for it, on every
phase and every package group. Plain writes keep the same indented shape.

Flushing stays: pacstrap and arch-chroot inherit this fd, so buffering would
reorder our lines against theirs in the log.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 15:24:35 -07:00
David Heinemeier HanssonandClaude Opus 5 c2b93afe01 Defer the target's UKI rebuild until the final Limine build
The existing hook mask only covers pacstrap. pacman.conf(5) HookDir is
absolute, so it never applied to the pacman runs inside arch-chroot, and during
omarchy-setup-system the target's own hooks are live. limine-entry-tool's
90-mkinitcpio-install.hook triggers on usr/lib/firmware/*, usr/src/*/dkms.conf
and usr/lib/modules/*/pkgbase, and collect_pkgbase_files sets rebuild_all for
any trigger outside usr/lib/modules — so it rebuilds the initramfs and UKI for
every installed kernel. The hardware scripts hit that routinely: sof-firmware
on Intel audio, nvidia-open-dkms, linux-ptl on Panther Lake, linux-t2 on Macs.

Every one of those builds is discarded. finalize_limine_boot runs limine-update
immediately after, which pipes "rebuild" into the same script and rebuilds
unconditionally. They are stale as well as redundant: hardware/nvidia.sh writes
its mkinitcpio drop-in after installing the driver.

Mask that one hook inside the target for the duration of the phase. The
kernel-removal hooks stay live — they only prune Limine entries, which is what
ptl-kernel.sh's "pacman -Rdd linux" needs.

A mask that survived would be invisible until a later kernel update shipped a
UKI-less boot, so it is restored in a finally, again in main()'s finally, and
validate_boot repairs and then insists the real hook is back before reboot.
limine-mkinitcpio-hook is a hard dependency of the Omarchy runtime package, so
that file is always on disk before the mask goes up.

Worth several seconds per avoided build on real hardware. It is invisible in
the VM harness, which installs no hardware packages, so measure it on an Intel
laptop rather than in CI.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 15:24:26 -07:00
David Heinemeier HanssonandClaude Opus 5 436f37f926 Explain why archinstall's zram-generator.conf gets dropped
omarchy-settings now ships the tuning as a vendor drop-in that outranks the
main config file, so setup_swap's /etc copy decides nothing and is removed only
to keep /etc free for the local admin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjeyQZsNBxqyYy9z8KaKm7
2026-07-25 14:00:52 -07:00
David Heinemeier HanssonandClaude Opus 5 529001d566 Validate the UKI that was actually built
Hardware packages like omarchy-hw-intel-ptl swap the kernel mid-install,
so the UKI lands under a name the configurator never asked for and boot
validation halted a perfectly good install. Read the kernels back off
/usr/lib/modules/*/pkgbase instead of trusting the requested name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 13:05:22 -07:00
David Heinemeier HanssonandClaude Opus 4.8 78824fe084 Skip archinstall's pre-format countdown
archinstall's FilesystemHandler.perform_filesystem_operations defaults to
show_countdown=True, which runs a ~4.5s "5...4...3...2...1" warning
(_final_warning) before wiping the disk. That prompt is meant for
archinstall's interactive TUI; in our orchestrated/dashboard install it
renders nowhere and just sleeps silently on every full-disk install.

Pass show_countdown=False, guarded by an introspection check so it stays
safe on newer archinstall releases that dropped both the countdown and the
parameter. Generalize _method_accepts_users into _method_accepts for the
check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-25 09:41:45 -07:00
David Heinemeier HanssonandClaude Opus 4.8 8653d07e06 Drop archinstall's zram-generator.conf before pacstrap
archinstall's setup_swap writes /etc/systemd/zram-generator.conf directly
into the target, but omarchy-settings now ships that file as a packaged
config. pacstrap then aborts the transaction on a file conflict
("zram-generator.conf exists in filesystem"), failing the install.

Delete archinstall's copy after setup_swap so omarchy-settings' packaged
config lands cleanly. We still keep the zram-generator package and service
that setup_swap installs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-25 07:54:04 -07:00
David Heinemeier HanssonandClaude Fable 5 5e80c917ea Skip signature checks for the offline mirror
Fresh installs on real hardware failed pacstrap with "keyring is not
writable" and "required key missing from keyring". The offline repo's
SigLevel = Optional TrustAll was not the bypass it appeared to be:
Optional verifies whenever a .sig file exists — and every package in the
offline mirror ships one — while pacstrap's pacman -r relocates the
install root but not GpgDir, so verification runs against the LIVE
keyring. That silently made every install depend on archiso's boot-time
pacman-init.service having finished: fast in QEMU, minutes-or-never on
real hardware, where pacstrap then raced it and lost.

The mirror ships inside the ISO, whose integrity is already covered by
the airootfs sha512 and the ISO signature, so pacman-level signature
verification adds nothing. Set SigLevel = Never so installs never touch
the live keyring. The target still gets its own keyring via pacstrap -K
plus the archlinux-keyring/omarchy-keyring package hooks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 15:49:29 -07:00
David Heinemeier HanssonandClaude Fable 5 6ac95226af Stop blocking installs on the live pacman keyring
prepare_live waited on archiso's pacman-init.service, stalling real-hardware
installs at 5% for minutes: the boot-time keyring init (gpg key generation
plus populating every keyring) is slow when reading from USB, and as a
Type=oneshot unit with no start timeout it can block systemctl start
indefinitely.

Nothing in the install consults the live keyring. The offline repo is
SigLevel = Optional TrustAll and archinstall bootstraps with pacstrap -K,
which gives the target its own independently initialized keyring. Drop the
wait and let pacman-init finish in the background for anyone using the live
environment interactively.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 11:41:23 -07:00
David Heinemeier Hansson 338e687f32 Explain Super 2026-07-23 19:56:35 -07:00
David Heinemeier Hansson 4e8ee7da9b Switch to using tips 2026-07-23 19:39:54 -07:00
David Heinemeier Hansson 463f862b6c Speed up offline ISO installs 2026-07-23 17:21:13 -07:00
David Heinemeier Hansson a274a2c56e More whimsy 2026-07-23 16:15:29 -07:00
David Heinemeier Hansson 9d4b155e22 Language tweaks 2026-07-19 21:04:27 -07:00
David Heinemeier HanssonandClaude Fable 5 04aafcb781 Retry the partition commit when udev holds the disk
Full-disk installs flaked with "Partition(s) 1, 2 on /dev/vda have been
written, but we have been unable to inform the kernel of the change":
archinstall's disk wipe and parted's own partition registrations fire
udev probes, and when one is still holding the disk mid-commit, the
BLKPG sync fails and the install halts. The table is written correctly
when this happens — only the kernel's view is stale — so settle udev
before partitioning and redo the filesystem operations (wipe, partition,
format) when parted throws exactly this error. Recoveries are logged so
they show up in the support log.

Reproduced headlessly by booting the ISO on a serial console and driving
the real installer: stock failed 1 in 5 full-disk cycles at this exact
phase, with an audit watch confirming nothing else writes the disk. With
the fix, 13 of 13 cycles got cleanly through partitioning.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:58:39 -07:00
David Heinemeier Hansson c3f9743847 Don't like the first one 2026-07-18 18:27:10 -07:00
David Heinemeier Hansson 49dcd808aa Whimsy tweaks 2026-07-15 18:07:07 -07:00
David Heinemeier HanssonandClaude Fable 5 a5e605af4c Replace dashboard Python heredocs with jq + bash
The install dashboard shelled out to a full Python interpreter to read
four keys from the installer state JSON — including inside the render
loop, twice a second. jq is already on the ISO and does the same job
with plain bash arithmetic for the phase-weight interpolation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 17:52:47 -07:00
David Heinemeier Hansson 8c1e143686 Hand write the whimsy 2026-07-15 17:40:24 -07:00
David Heinemeier Hansson c167bf9c1d Cleanup the look 2026-07-14 18:09:48 -07:00
David Heinemeier Hansson c303a9f746 More aesthetic tweaks 2026-07-13 17:06:43 -07:00
David Heinemeier Hansson c8a0072403 Tweak the installer aesthetics 2026-07-13 15:55:08 -07:00
David Heinemeier Hansson d44bbc5e5f Fix archinstall 4.4 compatibility 2026-07-12 18:43:51 -07:00
Ryan Hughes 8c77631f68 Delegate Snapper setup to Omarchy packages 2026-06-21 02:29:09 -04:00
Ryan Hughes b1c09fa1a8 Use dev Omarchy packages in dev ISO builds 2026-06-08 12:53:01 -04:00
Ryan Hughes ce9e648ade Drop omarchy-limine package; settings now ships limine configs
Pairs with omarchy-pkgs' fold of omarchy-limine into omarchy-settings.

Changes:
- EARLY_BOOTSTRAP_PACKAGES in phases_impl.py drops omarchy-limine.
  The limine configs it shipped (mkinitcpio hooks, entry-tool drop-ins,
  snapper template, default/limine/, default/snapper/) now come with
  omarchy-settings, which is already in the early bootstrap.
- builder/build-iso.sh's offline-mirror seed list and post-mirror filter
  no longer reference omarchy-limine.
- builder/build-omarchy-packages.sh's build queue drops omarchy-limine.
- Test manifests (fresh-4.json, fresh-4-semantic.json) no longer expect
  omarchy-limine in the installed-packages list. The /etc/pacman.d/hooks/
  99-omarchy-limine.hook entry stays — that hook file is generated by the
  orchestrator regardless, and the filename is descriptive, not tied to
  the package name.
2026-05-27 19:09:05 -04:00
Ryan Hughes 239c8e7f64 Use omarchy-finalize-user in target chroot setup
Pairs with omarchy-installer's rename of bin/omarchy-setup-user to
bin/omarchy-finalize-user. The orchestrator now invokes
omarchy-finalize-user --force --first-install in the run_chroot_finalizer
phase, and the phase-ordering docstring is updated to match.
2026-05-27 19:05:38 -04:00
Ryan Hughes afa8293b2b Improve ISO installer flow and VM tooling 2026-05-25 19:54:12 -04:00
Ryan Hughes c50d0bc299 Unify ISO install orchestration
Drive installs through the common ISO pipeline, carry install intent in configurator JSON, and finalize Limine boot setup from the ISO.
2026-05-25 12:50:31 -04:00
Ryan Hughes 660edcb3af installer: defer boot hooks during pacstrap 2026-05-23 14:39:52 -04:00
Ryan Hughes 3a51e875b6 installer: move hibernation into orchestrator 2026-05-23 14:05:15 -04:00
Ryan Hughes 38f56103e1 builder: add debug install instrumentation 2026-05-23 12:45:12 -04:00
Ryan Hughes b16303f294 installer: always clean up finalizer log bind 2026-05-23 10:30:53 -04:00
Ryan Hughes 6232620806 installer: unify finalizer logging 2026-05-23 10:21:38 -04:00
Ryan Hughes 8d1d3c906d installer: harden dashboard finish transition 2026-05-23 10:02:36 -04:00
Ryan Hughes fd12ace8bc installer: tolerate missing duration on finish 2026-05-23 05:29:53 -04:00
Ryan Hughes 1d656af51d installer: make dashboard own install flow 2026-05-23 04:50:32 -04:00
Ryan Hughes c43bad26b5 installer: stop dashboard before finish prompt 2026-05-23 03:35:55 -04:00
Ryan Hughes 7d7f6451a3 installer: track real dashboard pid 2026-05-23 02:55:44 -04:00
Ryan Hughes 0890472c9b installer: pass dashboard tty explicitly 2026-05-23 02:14:13 -04:00
Ryan Hughes 1162d111bd installer: force dashboard shutdown before finish 2026-05-22 23:10:44 -04:00
Ryan Hughes ca55321621 installer: animate dashboard and finish screens 2026-05-22 19:20:03 -04:00
Ryan Hughes 0734e982ca installer: harden dashboard handoff 2026-05-22 19:15:06 -04:00
Ryan Hughes 61f84a95cf installer: smooth dashboard progress 2026-05-22 18:09:00 -04:00
Ryan Hughes 337ba2e590 installer: show dashboard during ISO install 2026-05-22 17:34:01 -04:00
Ryan Hughes de0f013b5e orchestrator: converge free-space boot on finalizer 2026-05-22 16:33:11 -04:00
Ryan Hughes 948a53cc0a orchestrator: recover missing ESP mount in free-space installs 2026-05-22 15:00:19 -04:00