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
|
fi
|
||||||
bootstrap_ssh
|
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."
|
log "Installed system is up. Saving base image."
|
||||||
stop_vm
|
stop_vm
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ def run(ctx: InstallContext, phases: list[tuple[str, PhaseFn]]) -> None:
|
|||||||
state["finished_at"] = time.time()
|
state["finished_at"] = time.time()
|
||||||
_write_state(state_path, state)
|
_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:
|
def _write_state(path: Path, state: dict) -> None:
|
||||||
# Dashboard polls this file while phases update it. Write atomically so the
|
# 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:
|
def prepare_live(ctx: InstallContext) -> None:
|
||||||
info("› initializing pacman keyrings")
|
# archiso's pacman-init.service initializes and populates every installed
|
||||||
subprocess.run(["pacman-key", "--init"], check=True)
|
# keyring before the live environment reaches multi-user.target. Pacstrap
|
||||||
subprocess.run(["pacman-key", "--populate", "archlinux"], check=True)
|
# then initializes the target's independent keyring, and archinstall does
|
||||||
subprocess.run(["pacman-key", "--populate", "omarchy"], check=True)
|
# its own repository sync before the first package transaction. Repeating
|
||||||
subprocess.run(["pacman", "-Sy", "--noconfirm"], check=True)
|
# 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:
|
if ctx.is_protected:
|
||||||
info("› protected mode: skipping whole-disk cleanup")
|
info("› protected mode: skipping whole-disk cleanup")
|
||||||
@@ -239,6 +241,7 @@ def arch_install_system(ctx: InstallContext) -> None:
|
|||||||
if config.mirror_config:
|
if config.mirror_config:
|
||||||
installer.set_mirrors(mirror_handler, config.mirror_config, on_target=False)
|
installer.set_mirrors(mirror_handler, config.mirror_config, on_target=False)
|
||||||
|
|
||||||
|
_mount_offline_package_cache(ctx)
|
||||||
_mask_mkinitcpio_pacman_hooks(ctx)
|
_mask_mkinitcpio_pacman_hooks(ctx)
|
||||||
try:
|
try:
|
||||||
info("› installing base system (mkinitcpio deferred to final Limine UKI build)")
|
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))
|
installer.add_additional_packages(_runtime_package_list(ctx))
|
||||||
finally:
|
finally:
|
||||||
_unmask_mkinitcpio_pacman_hooks(ctx)
|
_unmask_mkinitcpio_pacman_hooks(ctx)
|
||||||
|
_unmount_offline_package_cache(ctx)
|
||||||
|
|
||||||
# Standard arch finishers.
|
# Standard arch finishers.
|
||||||
if config.timezone:
|
if config.timezone:
|
||||||
@@ -575,6 +579,35 @@ def _install_early_packages(installer) -> None:
|
|||||||
installer.add_additional_packages(user_seed_packages)
|
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:
|
def _is_devnull_symlink(path: Path) -> bool:
|
||||||
try:
|
try:
|
||||||
return path.is_symlink() and path.readlink() == Path("/dev/null")
|
return path.is_symlink() and path.readlink() == Path("/dev/null")
|
||||||
|
|||||||
+10
-1
@@ -12,7 +12,16 @@ bootmodes=('bios.syslinux' 'uefi.grub')
|
|||||||
arch="x86_64"
|
arch="x86_64"
|
||||||
pacman_conf="pacman-offline.conf"
|
pacman_conf="pacman-offline.conf"
|
||||||
airootfs_image_type="squashfs"
|
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')
|
bootstrap_tarball_compression=('zstd' '-c' '-T0' '--auto-threads=logical' '--long' '-19')
|
||||||
file_permissions=(
|
file_permissions=(
|
||||||
["/etc/shadow"]="0:0:400"
|
["/etc/shadow"]="0:0:400"
|
||||||
|
|||||||
Reference in new issue
Block a user