"""Arch/Artix backend — uses pacstrap (Arch) or basestrap (Artix).""" from pathlib import Path from .base import Distro class Arch(Distro): name = "arch" host_deps = ["squashfs-tools", "xorriso", "mtools", "dosfstools"] INITS = {"openrc", "runit", "s6", "dinit"} def __init__(self, family: str = "arch"): self.family = family def bootstrap(self, rootfs: Path, config: dict) -> None: init = config.get("init", "dinit") base_pkgs = ["base", "base-devel", f"{init}", *config.get("base_packages", [])] if self.family == "artix": # basestrap for Artix elogind_pkg = f"elogind-{init}" cmd = ["basestrap", "-i", str(rootfs), *base_pkgs, elogind_pkg] else: # pacstrap for Arch cmd = ["pacstrap", "-K", str(rootfs), *base_pkgs] self._run(cmd) def install_packages(self, rootfs: Path, packages: list[str]) -> None: # always include the package manager itself pkgs = ["pacman", *packages] self._run_chroot(rootfs, ["pacman", "-Syu", "--noconfirm", *pkgs]) def configure_base(self, rootfs: Path, config: dict) -> None: hostname = config.get("hostname", "euri") (rootfs / "etc/hostname").write_text(f"{hostname}\n") # hosts file hosts = ( "127.0.0.1\tlocalhost\n" "::1\t\tlocalhost\n" f"127.0.1.1\t{hostname}.localdomain\t{hostname}\n" ) (rootfs / "etc/hosts").write_text(hosts) for user in config.get("users", []): name = user["name"] shell = user.get("shell", "/bin/bash") self._run_chroot(rootfs, ["useradd", "-m", "-s", shell, name]) if "password" in user: pw = user["password"] self._run_chroot(rootfs, ["bash", "-c", f"echo '{name}:{pw}' | chpasswd"]) for group in user.get("groups", []): self._run_chroot(rootfs, ["usermod", "-aG", group, name]) init = config.get("init", "dinit") # enable services per init system for svc in config.get("services", []): if self.family == "artix": if init == "openrc": self._run_chroot(rootfs, ["rc-update", "add", svc]) elif init == "runit": self._run_chroot(rootfs, ["ln", "-s", f"/etc/runit/sv/{svc}", "/etc/runit/runsvdir/default"]) elif init == "s6": self._run_chroot(rootfs, ["touch", f"/etc/s6/adminsv/default/contents.d/{svc}"]) elif init == "dinit": self._run_chroot(rootfs, ["ln", "-s", f"../{svc}", "/etc/dinit.d/boot.d/"]) else: self._run_chroot(rootfs, ["systemctl", "enable", svc]) def install_bootloader(self, rootfs: Path, config: dict) -> None: init = config.get("init", "dinit") self._run_chroot(rootfs, ["pacman", "-S", "--noconfirm", "grub", "efibootmgr", "os-prober"]) self._run_chroot(rootfs, ["grub-install", "--target=i386-pc", "/dev/sda"]) self._run_chroot(rootfs, ["grub-install", "--target=x86_64-efi", "--efi-directory=/boot/efi", "--bootloader-id=grub"]) self._run_chroot(rootfs, ["grub-mkconfig", "-o", "/boot/grub/grub.cfg"])