172 lines
6.1 KiB
Bash
Executable File
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
|