Speed up offline ISO installs
This commit is contained in:
1 parent
3544261e8c
commit
463f862b6c
4 files changed
+57
-6
No files matched your search
@@ -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
@@ -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"
|
||||
|
||||
Reference in new issue
Block a user