Initial commit: DarkForge Linux — Phases 0-12

Complete from-scratch Linux distribution targeting AMD Ryzen 9 9950X3D +
NVIDIA RTX 5090 on ASUS ROG CROSSHAIR X870E HERO.

Deliverables:
- dpack: custom package manager in Rust (3,800 lines)
  - TOML package parser, dependency resolver, build sandbox
  - CRUX Pkgfile and Gentoo ebuild converters
  - Shared library conflict detection
- 124 package definitions across 4 repos (core/extra/desktop/gaming)
- 34 toolchain bootstrap scripts (LFS 13.0 adapted for Zen 5)
- Linux 6.19.8 kernel config (hardware-specific, fully commented)
- SysVinit init system with rc.d service scripts
- Live ISO builder (UEFI-only, squashfs+xorriso)
- Interactive installer (GPT partitioning, EFISTUB boot)
- Integration test checklist (docs/TESTING.md)

No systemd. No bootloader. No display manager.
Kernel boots via EFISTUB → auto-login → dwl Wayland compositor.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 11:30:40 +01:00
commit 029642ae5b
206 changed files with 14696 additions and 0 deletions

75
src/install/README.md Normal file
View File

@@ -0,0 +1,75 @@
# DarkForge Linux Installer
A CRUX-style interactive text-mode installer that runs from the DarkForge live ISO.
## Overview
The installer walks through 9 steps to get a working DarkForge system on disk:
1. **Disk selection** — choose the target drive
2. **Partitioning** — GPT auto-partition (ESP 512MB + Swap 96GB + Root)
3. **Filesystem creation** — FAT32 (ESP), ext4 (root), swap
4. **Base system install** — via dpack or direct copy from live environment
5. **Kernel install** — copies kernel to ESP
6. **User setup** — root password, user account with groups
7. **Locale/timezone** — timezone, locale, keyboard layout
8. **Boot config** — EFISTUB boot entry via efibootmgr
9. **Optional packages** — desktop, gaming, dev tool groups
## Requirements
The installer runs from the DarkForge live ISO environment. It expects:
- UEFI firmware (no legacy BIOS support)
- At least one NVMe or SATA disk
- `sgdisk` (GPT partitioning)
- `mkfs.ext4`, `mkfs.fat`, `mkswap`
- `efibootmgr` (UEFI boot entry creation)
## Usage
Boot the DarkForge live ISO, then:
```bash
install
```
Or run directly:
```bash
/install/install.sh
```
## Module Structure
```
install/
├── install.sh # Main entry point (9-step wizard)
└── modules/
├── disk.sh # Disk selection, partitioning, formatting, mounting
├── user.sh # User account and hostname setup
├── locale.sh # Timezone, locale, keyboard
└── packages.sh # Base system install, kernel, optional packages
```
## Partition Scheme
The auto-partitioner creates:
| # | Type | Size | Filesystem | Mount |
|---|------|------|------------|-------|
| 1 | EFI System | 512MB | FAT32 | /boot/efi |
| 2 | Linux Swap | 96GB | swap | — |
| 3 | Linux Root | Remaining | ext4 | / |
The 96GB swap matches the RAM size to enable hibernation.
## Post-Install
After installation and reboot, the system boots via EFISTUB directly to a tty1 auto-login, which launches the dwl Wayland compositor.
## Repository
```
git@git.dannyhaslund.dk:danny8632/darkforge.git
```

150
src/install/install.sh Executable file
View File

@@ -0,0 +1,150 @@
#!/bin/bash
# ============================================================================
# DarkForge Linux — Interactive Installer
# ============================================================================
# Purpose: CRUX-style interactive installer that runs from the live environment.
# Walks the user through disk selection, partitioning, base install,
# user creation, locale setup, and boot configuration.
# Inputs: User input (interactive prompts)
# Outputs: A fully installed DarkForge Linux system on the target disk
# ============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULES_DIR="${SCRIPT_DIR}/modules"
MOUNT_POINT="/mnt/darkforge"
REPOS_DIR="/var/lib/dpack/repos"
# --- Colors and formatting --------------------------------------------------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
info() { echo -e "${CYAN}:: ${1}${NC}"; }
ok() { echo -e "${GREEN}:: ${1}${NC}"; }
warn() { echo -e "${YELLOW}!! ${1}${NC}"; }
error() { echo -e "${RED}!! ${1}${NC}"; }
ask() { echo -en "${BOLD}${1}${NC}"; }
# --- Welcome ----------------------------------------------------------------
clear
echo -e "${BOLD}"
echo " ╔══════════════════════════════════════════════════════════════╗"
echo " ║ ║"
echo " ║ DarkForge Linux Installer v1.0 ║"
echo " ║ ║"
echo " ║ A custom Linux distribution optimized for gaming ║"
echo " ║ and development on AMD Ryzen 9 9950X3D + RTX 5090 ║"
echo " ║ ║"
echo " ╚══════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
echo ""
echo " This installer will guide you through:"
echo " 1. Disk selection and partitioning"
echo " 2. Filesystem creation"
echo " 3. Base system installation"
echo " 4. Kernel installation"
echo " 5. User account setup"
echo " 6. Locale, timezone, and keyboard"
echo " 7. Boot configuration (EFISTUB)"
echo " 8. Post-install package selection"
echo ""
ask "Press Enter to begin, or Ctrl+C to exit..."
read -r
# --- Step 1: Disk selection -------------------------------------------------
info "Step 1: Disk Selection"
echo ""
source "${MODULES_DIR}/disk.sh"
select_disk
echo ""
# --- Step 2: Partitioning ---------------------------------------------------
info "Step 2: Partitioning"
echo ""
partition_disk
echo ""
# --- Step 3: Format and mount -----------------------------------------------
info "Step 3: Filesystem Creation"
echo ""
format_partitions
mount_partitions
echo ""
# --- Step 4: Base system installation ----------------------------------------
info "Step 4: Base System Installation"
echo ""
source "${MODULES_DIR}/packages.sh"
install_base_system
echo ""
# --- Step 5: Kernel installation ---------------------------------------------
info "Step 5: Kernel Installation"
echo ""
install_kernel
echo ""
# --- Step 6: User account setup ---------------------------------------------
info "Step 6: User Account Setup"
echo ""
source "${MODULES_DIR}/user.sh"
setup_users
echo ""
# --- Step 7: Locale, timezone, keyboard --------------------------------------
info "Step 7: Locale, Timezone, and Keyboard"
echo ""
source "${MODULES_DIR}/locale.sh"
configure_locale
echo ""
# --- Step 8: Boot configuration (EFISTUB) ------------------------------------
info "Step 8: Boot Configuration"
echo ""
configure_boot
echo ""
# --- Step 9: Post-install package selection ----------------------------------
info "Step 9: Additional Packages (Optional)"
echo ""
select_additional_packages
echo ""
# --- Finalize ----------------------------------------------------------------
info "Finalizing installation..."
# Generate fstab
generate_fstab
# Set hostname
echo "${INSTALL_HOSTNAME}" > "${MOUNT_POINT}/etc/hostname"
# Copy rc.conf with configured values
configure_rc_conf
# Unmount
info "Unmounting filesystems..."
umount -R "${MOUNT_POINT}" 2>/dev/null || true
echo ""
echo -e "${GREEN}${BOLD}"
echo " ╔══════════════════════════════════════════════════════════════╗"
echo " ║ ║"
echo " ║ Installation Complete! ║"
echo " ║ ║"
echo " ║ Remove the installation media and reboot. ║"
echo " ║ Your DarkForge system will boot directly via EFISTUB. ║"
echo " ║ ║"
echo " ╚══════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
echo ""
ask "Reboot now? [y/N] "
read -r response
if [[ "${response}" =~ ^[Yy]$ ]]; then
reboot
fi

175
src/install/modules/disk.sh Executable file
View File

@@ -0,0 +1,175 @@
#!/bin/bash
# ============================================================================
# DarkForge Linux Installer — Disk Module
# ============================================================================
# Handles disk selection, partitioning, formatting, and mounting.
# Partition scheme: GPT with ESP (512MB) + Swap (96GB) + Root (remaining)
# ============================================================================
INSTALL_DISK=""
PART_ESP=""
PART_SWAP=""
PART_ROOT=""
# --- List available disks and let user choose -------------------------------
select_disk() {
echo "Available disks:"
echo ""
lsblk -d -o NAME,SIZE,MODEL,TRAN -n | grep -v "loop\|sr\|rom" | while read -r line; do
echo " ${line}"
done
echo ""
ask "Enter the target disk (e.g., nvme0n1, sda): "
read -r INSTALL_DISK
# Validate
if [ ! -b "/dev/${INSTALL_DISK}" ]; then
error "Disk /dev/${INSTALL_DISK} not found."
select_disk
return
fi
echo ""
warn "ALL DATA ON /dev/${INSTALL_DISK} WILL BE DESTROYED!"
ask "Are you sure? Type 'yes' to confirm: "
read -r confirm
if [ "${confirm}" != "yes" ]; then
error "Aborted."
exit 1
fi
export INSTALL_DISK
}
# --- Partition the disk (GPT: ESP + swap + root) ----------------------------
partition_disk() {
local disk="/dev/${INSTALL_DISK}"
info "Creating GPT partition table on ${disk}..."
# Wipe existing partition table
sgdisk --zap-all "${disk}"
# Create partitions:
# 1: EFI System Partition (512MB)
# 2: Swap (96GB — matches RAM for hibernation)
# 3: Root (remaining space)
sgdisk -n 1:0:+512M -t 1:ef00 -c 1:"EFI System" "${disk}"
sgdisk -n 2:0:+96G -t 2:8200 -c 2:"Linux Swap" "${disk}"
sgdisk -n 3:0:0 -t 3:8300 -c 3:"Linux Root" "${disk}"
# Determine partition device names
if [[ "${INSTALL_DISK}" == nvme* ]]; then
PART_ESP="${disk}p1"
PART_SWAP="${disk}p2"
PART_ROOT="${disk}p3"
else
PART_ESP="${disk}1"
PART_SWAP="${disk}2"
PART_ROOT="${disk}3"
fi
export PART_ESP PART_SWAP PART_ROOT
ok "Partitions created:"
echo " ESP: ${PART_ESP} (512MB)"
echo " Swap: ${PART_SWAP} (96GB)"
echo " Root: ${PART_ROOT} (remaining)"
# Wait for kernel to recognize new partitions
partprobe "${disk}" 2>/dev/null || true
sleep 1
}
# --- Format partitions ------------------------------------------------------
format_partitions() {
info "Formatting partitions..."
# ESP — FAT32
mkfs.fat -F 32 -n "ESP" "${PART_ESP}"
ok "ESP formatted (FAT32)"
# Swap
mkswap -L "darkforge-swap" "${PART_SWAP}"
ok "Swap formatted (96GB)"
# Root — ext4 (user chose ext4)
mkfs.ext4 -L "darkforge-root" -O ^metadata_csum_seed "${PART_ROOT}"
ok "Root formatted (ext4)"
}
# --- Mount partitions -------------------------------------------------------
mount_partitions() {
info "Mounting filesystems to ${MOUNT_POINT}..."
mkdir -p "${MOUNT_POINT}"
mount "${PART_ROOT}" "${MOUNT_POINT}"
mkdir -p "${MOUNT_POINT}/boot/efi"
mount "${PART_ESP}" "${MOUNT_POINT}/boot/efi"
swapon "${PART_SWAP}"
ok "Filesystems mounted"
}
# --- Generate fstab from current mounts ------------------------------------
generate_fstab() {
info "Generating /etc/fstab..."
local root_uuid=$(blkid -o value -s UUID "${PART_ROOT}")
local esp_uuid=$(blkid -o value -s UUID "${PART_ESP}")
local swap_uuid=$(blkid -o value -s UUID "${PART_SWAP}")
cat > "${MOUNT_POINT}/etc/fstab" << EOF
# DarkForge Linux — /etc/fstab
# Generated by installer on $(date -u +%Y-%m-%d)
# Root filesystem
UUID=${root_uuid} / ext4 defaults,noatime 0 1
# EFI System Partition
UUID=${esp_uuid} /boot/efi vfat defaults,noatime 0 2
# Swap (96GB for hibernation)
UUID=${swap_uuid} none swap defaults 0 0
# Tmpfs
tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0
EOF
ok "fstab generated"
}
# --- Configure EFISTUB boot entry -------------------------------------------
configure_boot() {
info "Configuring UEFI boot entry (EFISTUB)..."
local root_uuid=$(blkid -o value -s UUID "${PART_ROOT}")
local esp_dev=$(blkid -o value -s PARTUUID "${PART_ESP}")
# Copy kernel to ESP
if [ -f "${MOUNT_POINT}/boot/vmlinuz" ]; then
cp "${MOUNT_POINT}/boot/vmlinuz" "${MOUNT_POINT}/boot/efi/EFI/Linux/vmlinuz.efi"
mkdir -p "${MOUNT_POINT}/boot/efi/EFI/Linux"
ok "Kernel copied to ESP"
else
warn "No kernel found — you'll need to install one before booting"
fi
# Create UEFI boot entry via efibootmgr
if command -v efibootmgr >/dev/null 2>&1; then
local disk_dev="/dev/${INSTALL_DISK}"
efibootmgr --create \
--disk "${disk_dev}" \
--part 1 \
--label "DarkForge Linux" \
--loader "/EFI/Linux/vmlinuz.efi" \
--unicode "root=UUID=${root_uuid} rw quiet" \
2>/dev/null && ok "UEFI boot entry created" \
|| warn "Failed to create UEFI boot entry — you may need to set it manually in BIOS"
else
warn "efibootmgr not found — set boot entry manually in UEFI firmware"
fi
}

52
src/install/modules/locale.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
# ============================================================================
# DarkForge Linux Installer — Locale Module
# ============================================================================
# Configures locale, timezone, and keyboard layout.
# ============================================================================
configure_locale() {
# --- Timezone ---
info "Available timezones: /usr/share/zoneinfo/"
echo " Common: America/New_York, America/Chicago, America/Denver,"
echo " America/Los_Angeles, Europe/London, Europe/Berlin"
echo ""
ask "Timezone [America/New_York]: "
read -r tz
tz="${tz:-America/New_York}"
if [ -f "${MOUNT_POINT}/usr/share/zoneinfo/${tz}" ]; then
ln -sf "/usr/share/zoneinfo/${tz}" "${MOUNT_POINT}/etc/localtime"
ok "Timezone set to ${tz}"
else
warn "Timezone '${tz}' not found — using UTC"
ln -sf /usr/share/zoneinfo/UTC "${MOUNT_POINT}/etc/localtime"
tz="UTC"
fi
# --- Locale ---
echo ""
ask "Locale [en_US.UTF-8]: "
read -r locale
locale="${locale:-en_US.UTF-8}"
# Generate locale
echo "${locale} UTF-8" > "${MOUNT_POINT}/etc/locale.gen"
chroot "${MOUNT_POINT}" locale-gen 2>/dev/null || true
echo "LANG=${locale}" > "${MOUNT_POINT}/etc/locale.conf"
ok "Locale set to ${locale}"
# --- Keyboard ---
echo ""
ask "Keyboard layout [us]: "
read -r keymap
keymap="${keymap:-us}"
echo "KEYMAP=${keymap}" > "${MOUNT_POINT}/etc/vconsole.conf"
ok "Keyboard layout set to ${keymap}"
# Store for rc.conf generation
export INSTALL_TIMEZONE="${tz}"
export INSTALL_LOCALE="${locale}"
export INSTALL_KEYMAP="${keymap}"
}

189
src/install/modules/packages.sh Executable file
View File

@@ -0,0 +1,189 @@
#!/bin/bash
# ============================================================================
# DarkForge Linux Installer — Packages Module
# ============================================================================
# Installs the base system packages and optional package groups.
# Uses dpack for package management if available, falls back to direct copy.
# ============================================================================
install_base_system() {
info "Installing base system packages..."
# Bind-mount essential virtual filesystems for chroot
mkdir -p "${MOUNT_POINT}"/{dev,proc,sys,run}
mount --bind /dev "${MOUNT_POINT}/dev"
mount --bind /dev/pts "${MOUNT_POINT}/dev/pts"
mount -t proc proc "${MOUNT_POINT}/proc"
mount -t sysfs sysfs "${MOUNT_POINT}/sys"
mount -t tmpfs tmpfs "${MOUNT_POINT}/run"
# Copy package repos into the target
mkdir -p "${MOUNT_POINT}/var/lib/dpack/repos"
cp -a "${REPOS_DIR}"/* "${MOUNT_POINT}/var/lib/dpack/repos/" 2>/dev/null || true
# Check if dpack is available
if command -v dpack >/dev/null 2>&1; then
info "Installing via dpack..."
# Install core packages
local core_packages=(
glibc gcc binutils linux bash coreutils util-linux
sed grep gawk findutils diffutils tar gzip xz zstd bzip2
ncurses readline file less make patch m4 bison flex
autoconf automake libtool gettext texinfo
perl python pkg-config cmake meson ninja
gmp mpfr mpc zlib openssl curl git expat libffi
eudev sysvinit dbus dhcpcd shadow procps-ng e2fsprogs
kmod iproute2 kbd groff man-db man-pages
)
for pkg in "${core_packages[@]}"; do
echo -n " Installing ${pkg}... "
dpack install "${pkg}" 2>/dev/null && echo "OK" || echo "SKIP"
done
else
info "dpack not available — installing from live filesystem..."
# Direct copy from the live root to the target
# This copies the base system that's already installed in the live env
local dirs_to_copy=(
usr/bin usr/sbin usr/lib usr/lib64 usr/include usr/share
etc lib lib64 bin sbin
)
for dir in "${dirs_to_copy[@]}"; do
if [ -d "/${dir}" ]; then
echo -n " Copying /${dir}... "
mkdir -p "${MOUNT_POINT}/${dir}"
cp -a "/${dir}"/* "${MOUNT_POINT}/${dir}/" 2>/dev/null || true
echo "OK"
fi
done
fi
# Create essential directories
mkdir -p "${MOUNT_POINT}"/{boot,home,mnt,opt,srv,tmp}
mkdir -p "${MOUNT_POINT}"/var/{cache,lib,log,lock,run,spool,tmp}
chmod 1777 "${MOUNT_POINT}/tmp"
ok "Base system installed"
}
# --- Install kernel to the target system ------------------------------------
install_kernel() {
info "Installing kernel..."
if [ -f "/boot/vmlinuz" ]; then
cp "/boot/vmlinuz" "${MOUNT_POINT}/boot/vmlinuz"
ok "Kernel installed to /boot/vmlinuz"
elif [ -f "/boot/vmlinuz-6.19.8-darkforge" ]; then
cp "/boot/vmlinuz-6.19.8-darkforge" "${MOUNT_POINT}/boot/vmlinuz"
ok "Kernel installed"
else
warn "No kernel found in live environment"
warn "You'll need to build and install the kernel manually:"
warn " cd /usr/src/linux && make -j32 && make modules_install"
warn " cp arch/x86/boot/bzImage /boot/vmlinuz"
fi
# Install kernel modules
if [ -d "/lib/modules" ]; then
cp -a /lib/modules "${MOUNT_POINT}/lib/"
ok "Kernel modules installed"
fi
# Install AMD microcode (if available)
if [ -f "/boot/amd-ucode.img" ]; then
cp "/boot/amd-ucode.img" "${MOUNT_POINT}/boot/"
ok "AMD microcode installed"
fi
}
# --- Optional package groups ------------------------------------------------
select_additional_packages() {
echo " Available package groups:"
echo ""
echo " 1. Desktop Environment (dwl + Wayland + foot + fuzzel)"
echo " 2. Gaming Stack (Steam + Wine + Proton + gamemode + mangohud)"
echo " 3. Development Tools (rust + extra compilers)"
echo " 4. All of the above"
echo " 5. Skip (install later)"
echo ""
ask " Select groups to install [4]: "
read -r choice
choice="${choice:-4}"
case "${choice}" in
1) install_group_desktop ;;
2) install_group_gaming ;;
3) install_group_dev ;;
4)
install_group_desktop
install_group_gaming
install_group_dev
;;
5) info "Skipping additional packages" ;;
*) warn "Invalid choice — skipping" ;;
esac
}
install_group_desktop() {
info "Installing desktop environment..."
if command -v dpack >/dev/null 2>&1; then
dpack install wayland wayland-protocols wlroots dwl xwayland \
foot fuzzel libinput libxkbcommon xkeyboard-config \
pipewire wireplumber polkit seatd \
fontconfig freetype harfbuzz firefox zsh \
wl-clipboard grim slurp 2>/dev/null
fi
ok "Desktop environment installed"
}
install_group_gaming() {
info "Installing gaming stack..."
if command -v dpack >/dev/null 2>&1; then
dpack install nvidia-open steam wine gamemode mangohud \
sdl2 vulkan-loader vulkan-tools dxvk vkd3d-proton 2>/dev/null
fi
ok "Gaming stack installed"
}
install_group_dev() {
info "Installing development tools..."
if command -v dpack >/dev/null 2>&1; then
dpack install rust wezterm 2>/dev/null
fi
ok "Development tools installed"
}
# --- Configure rc.conf with install-time values ----------------------------
configure_rc_conf() {
info "Configuring rc.conf..."
cat > "${MOUNT_POINT}/etc/rc.conf" << EOF
#!/bin/bash
# DarkForge Linux — System Configuration
# Generated by installer on $(date -u +%Y-%m-%d)
HOSTNAME="${INSTALL_HOSTNAME:-darkforge}"
TIMEZONE="${INSTALL_TIMEZONE:-America/New_York}"
KEYMAP="${INSTALL_KEYMAP:-us}"
LOCALE="${INSTALL_LOCALE:-en_US.UTF-8}"
FONT="ter-v18n"
DAEMONS=(eudev syslog dbus dhcpcd pipewire)
MODULES=(nvidia nvidia-modeset nvidia-drm nvidia-uvm)
MODULE_PARAMS=(
"nvidia-drm modeset=1"
)
NETWORK_INTERFACE="enp6s0"
NETWORK_DHCP=yes
HARDWARECLOCK="UTC"
EOF
ok "rc.conf configured"
}

51
src/install/modules/user.sh Executable file
View File

@@ -0,0 +1,51 @@
#!/bin/bash
# ============================================================================
# DarkForge Linux Installer — User Module
# ============================================================================
# Creates root password and user account.
# Default: username 'danny', added to wheel/video/audio/input groups.
# ============================================================================
INSTALL_USERNAME=""
INSTALL_HOSTNAME=""
setup_users() {
# --- Hostname ---
ask "Hostname [darkforge]: "
read -r INSTALL_HOSTNAME
INSTALL_HOSTNAME="${INSTALL_HOSTNAME:-darkforge}"
export INSTALL_HOSTNAME
# --- Root password ---
echo ""
info "Set the root password:"
chroot "${MOUNT_POINT}" /bin/bash -c "passwd root"
# --- User account ---
echo ""
ask "Username [danny]: "
read -r INSTALL_USERNAME
INSTALL_USERNAME="${INSTALL_USERNAME:-danny}"
export INSTALL_USERNAME
info "Creating user '${INSTALL_USERNAME}'..."
chroot "${MOUNT_POINT}" /bin/bash -c "
useradd -m -G wheel,video,audio,input,kvm -s /bin/zsh '${INSTALL_USERNAME}'
"
info "Set password for '${INSTALL_USERNAME}':"
chroot "${MOUNT_POINT}" /bin/bash -c "passwd '${INSTALL_USERNAME}'"
# Install user shell profile
if [ -f "/install/configs/zprofile" ]; then
cp "/install/configs/zprofile" "${MOUNT_POINT}/home/${INSTALL_USERNAME}/.zprofile"
chroot "${MOUNT_POINT}" chown "${INSTALL_USERNAME}:${INSTALL_USERNAME}" "/home/${INSTALL_USERNAME}/.zprofile"
fi
# Update inittab with the correct username for auto-login
sed -i "s/--autologin danny/--autologin ${INSTALL_USERNAME}/" \
"${MOUNT_POINT}/etc/inittab"
ok "User '${INSTALL_USERNAME}' created"
}