- any distro from any distro (debian, ubuntu, arch, artix, void, alpine, fedora) - YAML config for distro, arch, init, packages, users, services, bootloader - each distro backend knows how to bootstrap itself - squashfs + xorriso for ISO generation - sexy CLI with banner and colored output - examples for Artix+Euri and Project Horizon
74 lines
2.9 KiB
Python
74 lines
2.9 KiB
Python
"""Void Linux backend — uses xbps-install with a rootfs tarball or chroot."""
|
|
|
|
from pathlib import Path
|
|
|
|
from .base import Distro
|
|
|
|
|
|
class Void(Distro):
|
|
name = "void"
|
|
host_deps = ["xbps-install", "squashfs-tools", "xorriso", "mtools", "dosfstools"]
|
|
|
|
REPOS = {
|
|
"glibc": "https://repo-default.voidlinux.org/current",
|
|
"musl": "https://repo-default.voidlinux.org/current",
|
|
}
|
|
|
|
def bootstrap(self, rootfs: Path, config: dict) -> None:
|
|
libc = config.get("libc", "musl")
|
|
arch = config.get("arch", "x86_64")
|
|
repo = config.get("mirror", self.REPOS[libc])
|
|
init = config.get("init", "dinit")
|
|
|
|
# base packages — swap runit for dinit if requested
|
|
base = ["base-system"]
|
|
if init == "dinit":
|
|
# Void ships runit in base-system; we'll replace later
|
|
base.append("dinit")
|
|
|
|
cmd = [
|
|
"xbps-install",
|
|
"-S",
|
|
"-r", str(rootfs),
|
|
"-R", repo,
|
|
*base,
|
|
]
|
|
env = {**config.get("env", {}), "XBPS_ARCH": f"{arch}-{libc}"}
|
|
self._run(cmd, env=env)
|
|
|
|
# swap runit for dinit
|
|
if init == "dinit":
|
|
self._run_chroot(rootfs, ["xbps-remove", "-y", "runit"])
|
|
self._run_chroot(rootfs, ["ln", "-s", "/etc/dinit.d/boot.d", "/etc/runit/runsvdir/default"])
|
|
|
|
def install_packages(self, rootfs: Path, packages: list[str]) -> None:
|
|
if not packages:
|
|
return
|
|
self._run_chroot(rootfs, ["xbps-install", "-Sy", *packages])
|
|
|
|
def configure_base(self, rootfs: Path, config: dict) -> None:
|
|
hostname = config.get("hostname", "euri")
|
|
(rootfs / "etc/hostname").write_text(f"{hostname}\n")
|
|
|
|
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:
|
|
self._run_chroot(rootfs, ["bash", "-c", f"echo '{name}:{user[\"password\"]}' | chpasswd"])
|
|
for group in user.get("groups", []):
|
|
self._run_chroot(rootfs, ["usermod", "-aG", group, name])
|
|
|
|
init = config.get("init", "dinit")
|
|
for svc in config.get("services", []):
|
|
if init == "dinit":
|
|
self._run_chroot(rootfs, ["ln", "-s", f"/etc/dinit.d/{svc}", "/etc/dinit.d/boot.d/"])
|
|
else:
|
|
self._run_chroot(rootfs, ["ln", "-s", f"/etc/runit/sv/{svc}", "/etc/runit/runsvdir/default"])
|
|
|
|
def install_bootloader(self, rootfs: Path, config: dict) -> None:
|
|
self._run_chroot(rootfs, ["xbps-install", "-Sy", "grub", "grub-x86_64-efi", "efibootmgr"])
|
|
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=Void"])
|
|
self._run_chroot(rootfs, ["grub-mkconfig", "-o", "/boot/grub/grub.cfg"])
|