Files
installer/minimal-linux-installer/SKILL.md

3.9 KiB

name, description
name description
minimal-linux-installer Guide for creating robust, minimal Linux installers (Fedora-based) with systemd-boot, offline dnf support, and reliable user configuration. Use when building or debugging custom OS installers.

Minimal Linux Installer Guide

This skill provides proven patterns for building minimal, robust Linux installers, specifically targeting Fedora-based systems. It covers critical areas like bootloader configuration (systemd-boot), offline package management, and user account setup.

Core Workflows

1. Partitioning & Mounting

Guideline: Always unmount partitions before modifying them. Mount pseudo-filesystems (including efivarfs) before chrooting.

# Unmount all partitions on target disk
ensure_unmounted(target_disk)

# ... Partitioning logic (EFI @ 512MB+, Root) ...

# Mount pseudo-filesystems
def mount_pseudo_fs(mount_root):
    mounts = ["dev", "proc", "sys"]
    for fs in mounts:
        run_command(["mount", "--bind", f"/{fs}", f"{mount_root}/{fs}"])
    
    # Critical for UEFI variable updates
    if os.path.exists("/sys/firmware/efi/efivars"):
        run_command(["mount", "-t", "efivarfs", "efivarfs", f"{mount_root}/sys/firmware/efi/efivars"])

2. Offline Package Installation (DNF)

Guideline: Prioritize local ISO repositories to allow offline installation. Fallback to network only if necessary.

# Search for ISO repo in common live media locations
possible_repos = [
    "/run/install/repo",
    "/run/install/source",
    "/mnt/install/repo",
    "/run/initramfs/live",
    "/run/initramfs/isoscan"
]
# Also check /run/media/$USER/$LABEL

iso_repo = find_repo(possible_repos)

if iso_repo:
    # Strict offline mode
    dnf_args = [
        "--disablerepo=*",
        f"--repofrompath=local-iso,{iso_repo}",
        "--enablerepo=local-iso",
        "--cacheonly" # Critical for dnf5 to avoid metadata download
    ]
else:
    # Network fallback
    dnf_args = [] 

# Essential packages for a bootable minimal system
packages = [
    "basesystem", "bash", "coreutils", "kernel", "systemd",
    "systemd-boot-unsigned", # Required for bootctl
    "dnf", "shadow-utils", "util-linux", # User mgmt & utils
    "efibootmgr", "passwd", "rootfiles", "vim-minimal"
]

3. Bootloader Configuration (systemd-boot)

Guideline: Use bootctl and kernel-install for a robust, standardized boot process. Set layout to bls.

# 1. Configure kernel layout
with open(f"{mount_root}/etc/kernel/layout", "w") as f:
    f.write("bls\n")

# 2. Install bootloader
# Remove --force if not supported by target version
run_command(["chroot", mount_root, "bootctl", "install", "--path=/boot"])

# 3. Generate initramfs if missing
if not os.path.exists(f"{mount_root}/boot/initramfs-{kver}.img"):
    run_command(["chroot", mount_root, "dracut", "--force", f"/boot/initramfs-{kver}.img", kver])

# 4. Add kernel entry
# kernel-install add <kver> <image> <initrd>
run_command(["chroot", mount_root, "kernel-install", "add", kver, kernel_image, initrd_path])

4. Reliable User & Password Setup

Guideline: Avoid piping plaintext passwords to stdin of chpasswd inside chroot if possible. Pre-hash passwords on the host or use usermod -p.

# 1. Create User
run_command(["chroot", mount_root, "useradd", "-m", "-G", "wheel", username])

# 2. Hash Password (Host-side)
# openssl passwd -6 generates SHA512 hash
hash = subprocess.check_output(["openssl", "passwd", "-6", password], text=True).strip()

# 3. Set Password (Directly modify shadow via usermod)
run_command(["chroot", mount_root, "usermod", "-p", hash, username])
run_command(["chroot", mount_root, "usermod", "-p", hash, "root"])

# 4. Ensure Sudo Access
with open(f"{mount_root}/etc/sudoers.d/wheel", "w") as f:
    f.write("%wheel ALL=(ALL) ALL\n")

5. Finalization

Guideline: Always sync to flush write buffers to physical media.

run_command(["sync"])