Speed up offline ISO installs

This commit is contained in:
David Heinemeier Hansson committed 2026-07-23 17:21:13 -07:00
1 parent 3544261e8c
commit 463f862b6c
4 files changed
+57 -6

No files matched your search

+5
View File
@@ -840,6 +840,11 @@ install_phase() {
fi
bootstrap_ssh
ssh_guest "echo $GUEST_PASSWORD | sudo -S cat /var/log/omarchy-install-timing.json 2>/dev/null" \
>"$RUN_DIR/omarchy-install-timing.json" 2>/dev/null || true
ssh_guest "echo $GUEST_PASSWORD | sudo -S cat /var/log/pacman.log 2>/dev/null" \
>"$RUN_DIR/pacman.log" 2>/dev/null || true
log "Installed system is up. Saving base image."
stop_vm
}
@@ -65,6 +65,10 @@ def run(ctx: InstallContext, phases: list[tuple[str, PhaseFn]]) -> None:
state["finished_at"] = time.time()
_write_state(state_path, state)
timing_path = ctx.target / "var" / "log" / "omarchy-install-timing.json"
timing_path.parent.mkdir(parents=True, exist_ok=True)
_write_state(timing_path, state)
def _write_state(path: Path, state: dict) -> None:
# Dashboard polls this file while phases update it. Write atomically so the
@@ -162,11 +162,13 @@ def _early_packages() -> list[str]:
# ─────────────────────────────────────────────────────────────────────────────
def prepare_live(ctx: InstallContext) -> None:
info("› initializing pacman keyrings")
subprocess.run(["pacman-key", "--init"], check=True)
subprocess.run(["pacman-key", "--populate", "archlinux"], check=True)
subprocess.run(["pacman-key", "--populate", "omarchy"], check=True)
subprocess.run(["pacman", "-Sy", "--noconfirm"], check=True)
# archiso's pacman-init.service initializes and populates every installed
# keyring before the live environment reaches multi-user.target. Pacstrap
# then initializes the target's independent keyring, and archinstall does
# its own repository sync before the first package transaction. Repeating
# both operations here only rebuilds trust databases and syncs twice.
info("› verifying live pacman initialization")
subprocess.run(["systemctl", "start", "pacman-init.service"], check=True)
if ctx.is_protected:
info("› protected mode: skipping whole-disk cleanup")
@@ -239,6 +241,7 @@ def arch_install_system(ctx: InstallContext) -> None:
if config.mirror_config:
installer.set_mirrors(mirror_handler, config.mirror_config, on_target=False)
_mount_offline_package_cache(ctx)
_mask_mkinitcpio_pacman_hooks(ctx)
try:
info("› installing base system (mkinitcpio deferred to final Limine UKI build)")
@@ -274,6 +277,7 @@ def arch_install_system(ctx: InstallContext) -> None:
installer.add_additional_packages(_runtime_package_list(ctx))
finally:
_unmask_mkinitcpio_pacman_hooks(ctx)
_unmount_offline_package_cache(ctx)
# Standard arch finishers.
if config.timezone:
@@ -575,6 +579,35 @@ def _install_early_packages(installer) -> None:
installer.add_additional_packages(user_seed_packages)
def _mount_offline_package_cache(ctx: InstallContext) -> None:
"""Let pacstrap consume bundled packages without copying them first.
Pacstrap always points pacman's CacheDir inside the target. Without this
bind mount, pacman copies every package from the ISO's file:// repository
into that cache and then extracts it, duplicating several GiB of I/O.
Mount the already-populated offline repository at the target cache for the
duration of package installation. It is unmounted before genfstab so the
live-only bind can never leak into the installed system's fstab.
"""
source = Path("/var/cache/omarchy/mirror/offline")
target = ctx.target / "var" / "cache" / "pacman" / "pkg"
if not source.is_dir():
raise RuntimeError(f"offline package cache missing: {source}")
target.mkdir(parents=True, exist_ok=True)
subprocess.run(["mount", "--bind", str(source), str(target)], check=True)
ctx.state.setdefault("bind_mounts", []).append(str(target))
def _unmount_offline_package_cache(ctx: InstallContext) -> None:
target = str(ctx.target / "var" / "cache" / "pacman" / "pkg")
subprocess.run(["umount", target], check=True)
try:
ctx.state.get("bind_mounts", []).remove(target)
except ValueError:
pass
def _is_devnull_symlink(path: Path) -> bool:
try:
return path.is_symlink() and path.readlink() == Path("/dev/null")
+10 -1
View File
@@ -12,7 +12,16 @@ bootmodes=('bios.syslinux' 'uefi.grub')
arch="x86_64"
pacman_conf="pacman-offline.conf"
airootfs_image_type="squashfs"
airootfs_image_tool_options=('-comp' 'xz' '-Xbcj' 'x86' '-b' '1M' '-Xdict-size' '1M')
# Package archives in the offline mirror are already zstd-compressed. Storing
# them in an outer XZ stream saves little space but makes pacman decompress XZ
# while hashing and extracting every package during installation.
airootfs_image_tool_options=(
'-comp' 'xz'
'-Xbcj' 'x86'
'-b' '1M'
'-Xdict-size' '1M'
'-action' 'uncompressed@subpathname(var/cache/omarchy/mirror/offline)'
)
bootstrap_tarball_compression=('zstd' '-c' '-T0' '--auto-threads=logical' '--long' '-19')
file_permissions=(
["/etc/shadow"]="0:0:400"