alvinlollo f3bd10cf0f
Tests / tests (push) Successful in 2m19s
fix(iso): sweep ii-builder leftovers via NSpid before userdel
end-4's ./setup sudo keepalive orphans a `sleep 60` child as ii-builder;
userdel then exits 8 and aborts the ISO build (CI exit 8).

Sweep uid-matching processes inside the build chroot before userdel,
mirroring shadow's user_busy_processes() checks (real/effective/saved
uid + root device/inode). Because arch-chroot mounts proc before
`unshare --fork --pid`, /proc entry numbers are outer-namespace pids:
signal the last NSpid field instead, require matching NSpid depth, and
surface kill errors instead of swallowing them. userdel keeps its stderr
and, on final failure, dumps the leftover process list before aborting.
2026-09-27 14:03:47 +10:00
2026-09-15 17:16:31 +10:00

Complete Guide to Creating a Custom Arch Linux ISO

Scheduled ArchISO Build Tests

DistroTube: https://www.youtube.com/watch?v=tSGGBbJBgvk&t=1228s

Dotfiles install file structure:

AlvinArch/
├── airootfs/
│   ├── etc/skel/
│   │   ├── .config/bat/           # bat + catppuccin theme
│   │   ├── .config/fish/          # 20 files, quickshell guard
│   │   ├── .config/nvim/          # LazyVim (14 files)
│   │   ├── .config/hypr/custom/   # 8 files (kdeconnectd + cursor only)
│   │   ├── .config/starship.toml
│   │   ├── .zshrc                 # adapted (no hardcoded paths)
│   │   └── .fzf.zsh
│   └── root/customize_airootfs.sh # pre-installs oh-my-zsh, lazy.nvim, plugins
├── localrepo/
│   ├── build-end4-deps.sh         # non-interactive AUR build (all deps)
│   ├── end4-pkgbuilds/            # microtex-git, quickshell-git, bibata
│   ├── illogical-impulse-quickshell-git-*.pkg.tar.zst
│   ├── illogical-impulse-bibata-modern-classic-bin-*.pkg.tar.zst
│   └── update.sh                  # existing, regenerates repo db
└── packages.x86_64               # 420 packages (65+ end-4 deps added)

Table of Contents

  1. Overview
  2. Prerequisites
  3. Directory Structure
  4. Core Configuration Files
  5. User Configuration (skel/)
  6. System Services & Networking
  7. Local Repository (localrepo/)
  8. Boot Configuration
  9. Build & Test
  10. Planned Additions
  11. Troubleshooting

Overview

AlvinArch is a custom Arch Linux live ISO built on the archiso framework. It ships a Hyprland desktop with end-4 dots-hyprland, a curated set of ~400 packages, and a local repository of pre-built AUR packages for packages not available in official repos. The ISO targets both real hardware and VMs (VirtualBox/Hyper-V/VMware guest services are enabled out of the box).

Key Features

  • Hyprland + end-4 — Wayland compositor with illogical-impulse dotfiles (quickshell, bibata cursors, microtex)
  • LazyVim — Pre-configured Neovim with lazy.nvim and curated plugins
  • Fish + Zsh + Starship — Dual shell setup with oh-my-zsh and a cross-shell prompt
  • Local AUR repo — Pre-built packages (end-4 deps, wallust, grub-customizer, etc.) that aren't in official repos
  • Curated packages — ~400 packages across ccache, networking, dev tools, and desktop utilities
  • Guest VM support — VirtualBox, Hyper-V, and VMware tools auto-enabled

Prerequisites

Required Tools

# Install archiso and dependencies
sudo pacman -S archiso git base-devel

# Optional but recommended
sudo pacman -S arch-install-scripts squashfs-tools

Knowledge Requirements

  • Basic Linux system administration
  • Understanding of Arch Linux package management
  • Shell scripting basics
  • Git version control (for managing your project)

Directory Structure

Complete Project Layout

AlvinArch/
├── profiledef.sh                    # ISO metadata, compression, boot modes, file permissions
├── packages.x86_64                  # ~400 live-environment packages (Hyprland, end-4, dev tools)
├── bootstrap_packages               # Minimal build-time packages (base, arch-install-scripts)
├── pacman.conf                      # Repos: cachyos → core → extra → multilib → chaotic-aur → local-aur
├── airootfs/                        # Root filesystem overlay (copied into live ISO)
│   ├── etc/
│   │   ├── os-release               # NAME="Alvin Arch Linux", ID=arch
│   │   ├── hostname                 # Default hostname: archiso
│   │   ├── motd                     # Welcome text with install instructions and color bar
│   │   ├── locale.conf              # LANG=en_AU.UTF-8
│   │   ├── locale.gen               # Locale generation file
│   │   ├── localtime → ../usr/share/zoneinfo/...  # Timezone symlink
│   │   ├── resolv.conf              # DNS resolver config
│   │   ├── passwd                   # System user accounts
│   │   ├── shadow                   # Password hashes (mode 400)
│   │   ├── clamav/                  # ClamAV antivirus config (certs, clamd, freshclam, milter)
│   │   ├── skel/                    # Home directory template for new users
│   │   │   ├── .config/
│   │   │   │   ├── bat/             # bat + Catppuccin Macchiato theme
│   │   │   │   ├── fish/            # Fish shell config (~20 files, nvm, fisher, hyprland helper)
│   │   │   │   ├── nvim/            # LazyVim setup (init.lua, plugins/, config/)
│   │   │   │   ├── hypr/custom/     # Hyprland dotfiles (keybinds, rules, execs, env, general, scripts)
│   │   │   │   └── starship.toml    # Starship cross-shell prompt
│   │   │   ├── .zshrc               # Zsh config (oh-my-zsh compatible)
│   │   │   └── .fzf.zsh             # Fzf shell integration
│   │   ├── systemd/
│   │   │   ├── system/              # Service files and enablement symlinks
│   │   │   │   ├── choose-mirror.service          # Auto mirror selection
│   │   │   │   ├── pacman-init.service             # Keyring initialization
│   │   │   │   ├── livecd-alsa-unmuter.service     # Unmute ALSA on boot
│   │   │   │   ├── livecd-talk.service              # LiveCD talk helper
│   │   │   │   ├── multi-user.target.wants/        # Enabled services (iwd, NetworkManager, sshd, vboxservice,
│   │   │   │   │                                  #   hv_kvp/vss/fcopy, vmtoolsd, ModemManager, etc.)
│   │   │   │   ├── sysinit.target.wants/           # systemd-timesyncd, systemd-time-wait-sync
│   │   │   │   ├── sockets.target.wants/           # systemd-networkd, pcscd
│   │   │   │   ├── network-online.target.wants/    # systemd-networkd-wait-online
│   │   │   │   └── sound.target.wants/             # livecd-alsa-unmuter
│   │   │   ├── networkd.conf.d/     # IPv6 privacy extensions
│   │   │   ├── resolved.conf.d/     # systemd-resolved config
│   │   │   ├── journald.conf.d/     # Volatile journal storage
│   │   │   └── logind.conf.d/       # Do-not-suspend policy
│   │   ├── pacman.d/
│   │   │   ├── hooks/
│   │   │   │   ├── uncomment-mirrors.hook          # Enable mirrors after install
│   │   │   │   └── zzzz99-remove-custom-hooks-from-airootfs.hook
│   │   │   ├── chaotic-mirrorlist   # Chaotic AUR mirrors
│   │   │   └── cachyos-mirrorlist   # CachyOS mirrors
│   │   ├── ssh/sshd_config.d/       # SSH live-environment config (10-archiso.conf)
│   │   ├── modprobe.d/              # broadcom-wl.conf (Broadcom WiFi driver)
│   │   └── mkinitcpio.conf.d/       # archiso initramfs config
│   ├── usr/
│   │   ├── lib/os-release           # usr-merge os-release
│   │   ├── local/bin/               # choose-mirror, Installation_guide, livecd-sound
│   │   ├── local/share/livecd-sound/ # ALSA config (asound.conf.in)
│   │   └── share/pacman/keyrings/   # CachyOS GPG keyring + trust data
│   └── root/
│       ├── .automated_script.sh     # Automated install entry point
│       ├── .zlogin                  # Zsh login hook
│       ├── .gnupg/scdaemon.conf     # GPG smartcard config
│       ├── .live-pacman.conf        # Pacman config for live session
│       └── customize_airootfs.sh    # Build-time chroot script (oh-my-zsh, lazy.nvim, plugins)
├── localrepo/                       # Pre-built AUR packages (indexed as local-aur repo)
│   ├── build-end4-deps.sh           # Non-interactive AUR builder for end-4 dependencies
│   ├── update.sh                    # Regenerates repo DB + syncs names to packages.x86_64
│   ├── end4-pkgbuilds/             # PKGBUILDs: quickshell-git, microtex-git, bibata-modern-classic-bin
│   ├── *.pkg.tar.zst               # Pre-built packages (illogical-impulse-*, wallust, grub-customizer,
│   │                               #   snapd, upscayl, meshy-git, pacserve, etc.)
│   └── local-aur.db{,.tar.gz}      # Repo database files
├── efiboot/                         # UEFI boot (systemd-boot)
│   └── loader/
│       ├── loader.conf
│       └── entries/
│           ├── 01-archiso-linux.conf
│           ├── 02-archiso-speech-linux.conf
│           └── 03-archiso-memtest86+x64.conf
├── grub/                            # GRUB boot (BIOS + UEFI)
│   ├── grub.cfg
│   └── loopback.cfg
└── syslinux/                        # BIOS boot (syslinux)
    ├── syslinux.cfg
    ├── archiso_head.cfg
    ├── archiso_pxe-linux.cfg
    ├── archiso_sys.cfg
    ├── archiso_sys-linux.cfg
    ├── archiso_tail.cfg
    └── splash.png

Core Configuration Files

profiledef.sh

Defines the entire ISO build. Key settings: iso_label="AlvinArch_...", bootmodes (BIOS syslinux + UEFI systemd-boot), airootfs_image_type="squashfs" with xz compression. Edit first to change branding or compression.

packages.x86_64

The main package list (~400 packages). Packages from allowed repos (cachyos, extra, multilib, chaotic-aur) are installed directly. Packages in localrepo/*.pkg.tar.zst are pulled from the [local-aur] repo. Keep sorted alphabetically.

bootstrap_packages

Minimal packages for the mkarchiso bootstrap phase: base and arch-install-scripts.

pacman.conf

Defines the repo order: cachyos → core → extra → multilib → chaotic-aur → local-aur. The [local-aur] repo points to the local localrepo/ directory for pre-built AUR packages.


User Configuration (skel/)

Dotfiles in airootfs/etc/skel/ are copied into every new user's home directory on the live ISO.

.config/bat/

bat with a Catppuccin Macchiato color theme. Provides bat as a cat replacement.

.config/fish/

Fish shell configuration (~20 files). Includes nvm integration, fisher plugin manager, Hyprland auto-detection (auto-Hypr.fish), frozen theme/keybindings, and custom functions (edit, update, lzd).

.config/nvim/

Full LazyVim setup powered by lazy.nvim. Includes init.lua, plugin specs for Obsidian, Arduino, and Harper (grammar), plus standard LazyVim config/options/keymaps/autocmds.

.config/hypr/custom/

Hyprland dotfiles from end-4 dots-hyprland:

File Purpose
keybinds.lua Window manager keybindings
general.lua Appearance, gaps, border settings
rules.lua Window rules (floating, size, class matching)
execs.lua Autostart commands
env.lua Environment variables
variables.lua Shared variable definitions
scripts/ Helper scripts (video wallpaper restore, paste-as-type)

.config/starship.toml

Cross-shell prompt config for Starship. Works with both Fish and Zsh.

.zshrc / .fzf.zsh

Zsh configuration adapted for oh-my-zsh (installed by customize_airootfs.sh) and fzf shell integration.


System Services & Networking

Service Purpose
iwd WiFi management
NetworkManager Network connections
sshd SSH access to live environment
vboxservice VirtualBox guest additions
hv_kvp_daemon, hv_vss_daemon, hv_fcopy_daemon Hyper-V integration
vmtoolsd, vmware-vmblock-fuse VMware guest tools
ModemManager Mobile broadband
pacman-init Initializes GPG keyring before package operations
choose-mirror Auto mirror selection (triggered by mirror kernel param)
livecd-alsa-unmuter Unmutes audio on live boot

Network Config

  • systemd-networkd with IPv6 privacy extensions enabled
  • systemd-resolved for DNS
  • DHCP auto-configured for wired (ethernet) and wireless (iwd)

Other System Config

  • ClamAV — Antivirus daemon config included in airootfs/etc/clamav/
  • mkinitcpio — Archiso-specific initramfs config
  • logind — No-suspend policy for live session
  • journald — Volatile (in-memory) log storage

Local Repository (localrepo/)

Pre-built AUR packages that aren't available in any allowed repo. The local-aur repo is configured in pacman.conf and picked up automatically by mkarchiso.

Scripts

  • build-end4-deps.sh — Non-interactive AUR build for all end-4 (illogical-impulse) dependencies. Run --quick to skip large packages.
  • update.sh — Regenerates the repo database and syncs new package names to packages.x86_64.

end4-pkgbuilds/

Custom PKGBUILDs for end-4 metapackages:

  • quickshell-git — Quickshell (Qt6/QML shell for Wayland)
  • microtex-git — LaTeX previewer
  • bibata-modern-classic-bin — Bibata cursor theme

Pre-built Packages

Packages like illogical-impulse-quickshell-git, illogical-impulse-bibata-modern-classic-bin, wallust, grub-customizer, snapd, upscayl-bin, meshy-git, xwaylandvideobridge, pacserve, etc.


Boot Configuration

UEFI — systemd-boot (efiboot/)

Three boot entries: standard Arch Linux, speech/accessibility, and MemTest86+.

BIOS — GRUB (grub/)

grub.cfg for BIOS/CSM boot, loopback.cfg for booting the ISO from a mounted image.

BIOS — syslinux (syslinux/)

Legacy BIOS boot with custom splash screen. Includes PXE network boot config.


Build & Test

Building the ISO

# Build the ISO (repo root IS the profile directory)
sudo mkarchiso -v -w work -o out/ .

# Build AUR deps for end-4 (run locally before ISO build if localrepo/ is stale)
./localrepo/build-end4-deps.sh          # build all
./localrepo/build-end4-deps.sh --quick  # skip large AUR pkgs

# Refresh localrepo DB after adding/moving .pkg.tar.zst files
./localrepo/update.sh                    # re-indexes existing packages
./localrepo/update.sh pkg1.pkg.tar.zst   # add files, then re-index

CI Checks (must pass before merge)

  • ShellCheck: all .sh files checked with shellcheck -x -s bash
  • yamllint: all .yml/.yaml files (relaxed config)
  • packages.x86_64 syntax: one package per line, no trailing whitespace, [a-zA-Z0-9._@+\-]+ only
  • Package repo check: every package in packages.x86_64 must be resolvable via pacman -Si in allowed repos (cachyos, extra, multilib, chaotic-aur), OR have a pre-built .pkg.tar.zst in localrepo/, OR appear in localrepo/build-end4-deps.sh
  • RAM: 4GB minimum, 8GB recommended
  • Video Memory: 128MB
  • 3D Acceleration: Enabled
  • Storage: 40GB minimum

Guest additions (vboxservice), Hyper-V (hv_*), and VMware (vmtoolsd) tools are all auto-enabled in the live environment.


Planned Additions

The following dotfiles are not yet included but are planned for future versions:

Component Status Notes
Alacritty terminal config 🚧 Planned Catppuccin Macchiato theme to match bat
GTK 3.0/4.0 theme config 🚧 Planned Consistent theming across GTK apps
Fontconfig custom settings 🚧 Planned Font rendering and fallback rules
Dunst notification daemon 🚧 Planned Notification appearance and behavior

Troubleshooting

ISO won't boot

  • Verify the ISO was built with sudo mkarchiso (not as a regular user)
  • Check that UEFI or BIOS/CSM is correctly set in VM firmware settings
  • For Ventoy: use the .iso directly, don't extract

No network in live environment

  • iwd handles WiFi — run iwctl to connect manually if NetworkManager doesn't detect networks
  • Ethernet via systemd-networkd with DHCP should work automatically

Package installation fails during build

  • Run ./localrepo/update.sh to refresh the localrepo database
  • Ensure localrepo/*.pkg.tar.zst files are valid and not corrupted
  • Check that the package name in packages.x86_64 matches exactly

LazyVim / oh-my-zsh not installed

  • customize_airootfs.sh clones repos at build time — requires network access during mkarchiso
  • Check build logs for git clone failures

Acknowledgements

S
Description
No description provided
Readme
729 MiB
2026-10-13 22:51:52 +11:00
Languages
Shell 91.8%
Lua 8.2%