Dotfiles/setup/archiso/build.sh

172 lines
6.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# build.sh — build the M-Archy Arch Linux ISO + netboot artifacts
#
# Usage:
# bash build.sh [--preconf [FILE]] [--netboot-url URL] [OUT_DIR]
#
# --preconf Embed ~/answerfile.json into the ISO at /answerfile.json
# --preconf FILE Embed the specified answerfile instead
# --netboot-url URL Base URL where netboot artifacts will be served
# (generates m-archy-netboot.ipxe in OUT_DIR)
# OUT_DIR Output directory (default: ~/m-archy-out, or $OUT_DIR env)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOTFILES_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
# ── Argument parsing ───────────────────────────────────────────────────────────
PRECONF_FILE=""
NETBOOT_URL=""
OUT_ARG=""
while [[ $# -gt 0 ]]; do
case "$1" in
--preconf)
# Optional next arg: a file path (doesn't start with -)
if [[ $# -gt 1 && "${2:0:1}" != "-" ]]; then
PRECONF_FILE="$2"; shift
else
PRECONF_FILE="$HOME/answerfile.json"
fi
shift
;;
--preconf=*)
PRECONF_FILE="${1#--preconf=}"
shift
;;
--netboot-url)
[[ $# -gt 1 ]] || { echo "ERROR: --netboot-url requires a URL argument" >&2; exit 1; }
NETBOOT_URL="$2"; shift 2
;;
--netboot-url=*)
NETBOOT_URL="${1#--netboot-url=}"
shift
;;
-*)
echo "Unknown flag: $1" >&2; exit 1
;;
*)
OUT_ARG="$1"; shift
;;
esac
done
WORK_DIR="${WORK_DIR:-$HOME/m-archy-build}"
OUT_DIR="${OUT_ARG:-${OUT_DIR:-$HOME/m-archy-out}}"
PROFILE="$WORK_DIR/profile"
RELENG="/usr/share/archiso/configs/releng"
if ! command -v mkarchiso &>/dev/null; then
echo "Installing archiso..."
sudo pacman -S --noconfirm archiso
fi
[[ -d "$RELENG" ]] || { echo "ERROR: $RELENG not found — is archiso installed?"; exit 1; }
# Validate answerfile early if --preconf was given
if [[ -n "$PRECONF_FILE" ]]; then
[[ -f "$PRECONF_FILE" ]] \
|| { echo "ERROR: answerfile not found: $PRECONF_FILE"; exit 1; }
command -v jq &>/dev/null \
&& jq empty "$PRECONF_FILE" \
|| echo "Warning: jq not available — skipping answerfile JSON validation"
echo "Answerfile to embed: $PRECONF_FILE"
fi
rm -rf "$WORK_DIR"
mkdir -p "$WORK_DIR" "$OUT_DIR"
echo "Copying releng base profile..."
cp -r "$RELENG" "$PROFILE"
echo "Applying M-Archy overlay..."
cp -r "$SCRIPT_DIR/overlay/airootfs/." "$PROFILE/airootfs/"
echo "Replacing profiledef..."
cp "$SCRIPT_DIR/overlay/profiledef.sh" "$PROFILE/profiledef.sh"
echo "Adding extra packages..."
while IFS= read -r pkg || [[ -n "$pkg" ]]; do
[[ -z "$pkg" || "$pkg" == \#* ]] && continue
grep -qxF "$pkg" "$PROFILE/packages.x86_64" || echo "$pkg" >> "$PROFILE/packages.x86_64"
done < "$SCRIPT_DIR/overlay/packages.extra"
echo "Embedding installer scripts..."
mkdir -p "$PROFILE/airootfs/root/installer"
cp "$DOTFILES_DIR/setup/archbaseos-guided-install.sh" "$PROFILE/airootfs/root/installer/"
cp "$DOTFILES_DIR/setup/arch-autoinstall.sh" "$PROFILE/airootfs/root/installer/"
cp "$DOTFILES_DIR/setup/reset-arch.sh" "$PROFILE/airootfs/root/installer/"
chmod 755 \
"$PROFILE/airootfs/root/launch.sh" \
"$PROFILE/airootfs/root/.automated_script.sh" \
"$PROFILE/airootfs/usr/local/bin/install-arch" \
"$PROFILE/airootfs/root/installer/"*.sh
# ── Embed answerfile (--preconf) ───────────────────────────────────────────────
if [[ -n "$PRECONF_FILE" ]]; then
echo "Embedding answerfile: $PRECONF_FILE → /answerfile.json"
install -m 644 "$PRECONF_FILE" "$PROFILE/airootfs/answerfile.json"
fi
echo "Building ISO (this may take a while)..."
sudo mkarchiso -v -w "$WORK_DIR/mkarchiso" -o "$OUT_DIR" "$PROFILE"
sudo chmod -R 777 "$WORK_DIR" "$OUT_DIR"
sudo chown -R "$(id -u):$(id -g)" "$WORK_DIR" "$OUT_DIR"
echo
echo "Done."
ls -lh "$OUT_DIR/"*.iso 2>/dev/null || true
if [[ -n "$PRECONF_FILE" ]]; then
echo "Answerfile embedded — automated install will activate on boot."
else
echo "No answerfile — guided (manual) installer will start automatically on boot."
fi
# ── Netboot artifacts ──────────────────────────────────────────────────────────
NETBOOT_TARBALL="$(ls "$OUT_DIR/"*-netboot-*.tar.gz 2>/dev/null | head -n1 || true)"
if [[ -n "$NETBOOT_TARBALL" ]]; then
echo
echo "Netboot artifact: $NETBOOT_TARBALL"
echo " Extract and serve its contents from an HTTP server, then boot via PXE."
echo " Internal layout (relative to tarball root):"
tar -tzf "$NETBOOT_TARBALL" | sed 's/^/ /'
if [[ -n "$NETBOOT_URL" ]]; then
# Strip trailing slash for consistency
BASE_URL="${NETBOOT_URL%/}"
IPXE_FILE="$OUT_DIR/m-archy-netboot.ipxe"
cat > "$IPXE_FILE" <<IPXE
#!ipxe
# M-Archy Arch Linux Installer — PXE Boot
# Generated by build.sh on $(date -u +%Y-%m-%dT%H:%M:%SZ)
#
# Deploy:
# 1. Extract the netboot tarball to the web root at: ${BASE_URL}/
# 2. Add this script as a custom entry in netboot.xyz, or chainload it directly.
#
# netboot.xyz custom menu entry (paste into your netboot.xyz config):
# item m-archy M-Archy Arch Linux Installer
# goto m-archy
# :m-archy
# chain ${BASE_URL}/m-archy-netboot.ipxe
set base-url ${BASE_URL}
kernel \${base-url}/arch/boot/x86_64/vmlinuz-linux \\
archiso_http_srv=\${base-url}/ \\
archisobasedir=arch \\
ip=dhcp
initrd \${base-url}/arch/boot/x86_64/initramfs-linux.img
boot
IPXE
echo
echo "iPXE script written to: $IPXE_FILE"
echo " Serve it alongside the netboot tarball contents at: ${BASE_URL}/"
else
echo
echo "Tip: rerun with --netboot-url <http://your-server/path> to generate an iPXE script."
fi
fi