diff --git a/minimal-linux-installer.skill b/minimal-linux-installer.skill new file mode 100644 index 0000000..78208ad Binary files /dev/null and b/minimal-linux-installer.skill differ diff --git a/minimal-linux-installer/SKILL.md b/minimal-linux-installer/SKILL.md new file mode 100644 index 0000000..59ec020 --- /dev/null +++ b/minimal-linux-installer/SKILL.md @@ -0,0 +1,120 @@ +--- +name: minimal-linux-installer +description: 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. + +```python +# 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. + +```python +# 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`. + +```python +# 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 +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`. + +```python +# 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. + +```python +run_command(["sync"]) +``` \ No newline at end of file