feat: initial commit — void-installer multi-profile (stable-cinnamon + mainline-niri)
This commit is contained in:
19
iso/Dockerfile
Normal file
19
iso/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
||||
# Container used to run void-mklive with real root.
|
||||
# This avoids the user-namespace CAP_MKNOD wall (dracut needs mknod /dev/null
|
||||
# inside the initramfs staging dir) and lets losetup/mount/chroot work
|
||||
# unconditionally. Host stays clean — no sudo, no host package installs.
|
||||
|
||||
FROM debian:stable-slim
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
bash git curl ca-certificates xz-utils tar patch python3 \
|
||||
mtools xorriso squashfs-tools dosfstools e2fsprogs \
|
||||
kmod \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# xbps-static is downloaded into /cache by the host script and added to PATH
|
||||
# at runtime by /work/iso/_inner-build.sh — no Void packages baked here.
|
||||
|
||||
WORKDIR /work
|
||||
61
iso/_inner-build.sh
Executable file
61
iso/_inner-build.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
# Runs INSIDE the docker container (as root). Invoked by iso/build-iso.sh.
|
||||
# Expects the project bind-mounted at /work and the cache at /cache.
|
||||
#
|
||||
# Required env (set by build-iso.sh):
|
||||
# ARCH, REPO_URL, KEYMAP, LOCALE, ISO_PKGS, ISO_TITLE, OUT_ISO_REL
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
: "${ARCH:?}"; : "${REPO_URL:?}"; : "${KEYMAP:?}"; : "${LOCALE:?}"
|
||||
: "${ISO_PKGS:?}"; : "${ISO_TITLE:?}"; : "${OUT_ISO_REL:?}"
|
||||
|
||||
CACHE_DIR=/cache
|
||||
PROJECT_DIR=/work
|
||||
MKLIVE_DIR="$CACHE_DIR/void-mklive"
|
||||
INCLUDE_DIR="$PROJECT_DIR/build/includes"
|
||||
OUT_ISO="$PROJECT_DIR/$OUT_ISO_REL"
|
||||
|
||||
# xbps-static was downloaded by the host script; put it on PATH so mklive
|
||||
# uses it instead of expecting a system xbps.
|
||||
export PATH="$CACHE_DIR/xbps-static/usr/bin:$PATH"
|
||||
|
||||
# Sanity checks.
|
||||
[[ -d "$MKLIVE_DIR" ]] || { echo "ERROR: $MKLIVE_DIR missing"; exit 1; }
|
||||
[[ -d "$INCLUDE_DIR" ]] || { echo "ERROR: $INCLUDE_DIR missing"; exit 1; }
|
||||
command -v xbps-install.static >/dev/null \
|
||||
|| { echo "ERROR: xbps-install.static not on PATH"; exit 1; }
|
||||
|
||||
mkdir -p "$(dirname "$OUT_ISO")"
|
||||
|
||||
cd "$MKLIVE_DIR"
|
||||
|
||||
# Cleanup trap: lazy-unmount any leftover pseudo-fs from a previous abort.
|
||||
_cleanup_mklive_builds() {
|
||||
local d sub
|
||||
for d in "$MKLIVE_DIR"/mklive-build.*/; do
|
||||
[[ -d "$d" ]] || continue
|
||||
for sub in tmp-rootfs/sys tmp-rootfs/proc tmp-rootfs/dev tmp-rootfs/run \
|
||||
image/rootfs/sys image/rootfs/proc image/rootfs/dev image/rootfs/run; do
|
||||
[[ -d "$d$sub" ]] && umount -R --lazy "$d$sub" 2>/dev/null || true
|
||||
done
|
||||
rm -rf "$d" 2>/dev/null || true
|
||||
done
|
||||
}
|
||||
trap _cleanup_mklive_builds EXIT
|
||||
|
||||
./mklive.sh \
|
||||
-a "$ARCH" \
|
||||
-r "$REPO_URL" \
|
||||
-c "$CACHE_DIR/xbps-live-pkgs" \
|
||||
-H "$CACHE_DIR/xbps-host-pkgs" \
|
||||
-k "$KEYMAP" \
|
||||
-l "$LOCALE" \
|
||||
-T "$ISO_TITLE" \
|
||||
-p "$ISO_PKGS" \
|
||||
-I "$INCLUDE_DIR" \
|
||||
-C "${BOOT_CMDLINE:-}" \
|
||||
-o "$OUT_ISO"
|
||||
|
||||
# Ensure the resulting file is writable by the host user.
|
||||
chown "$(stat -c '%u:%g' "$PROJECT_DIR")" "$OUT_ISO" "${OUT_ISO}".* 2>/dev/null || true
|
||||
296
iso/build-iso.sh
Executable file
296
iso/build-iso.sh
Executable file
@@ -0,0 +1,296 @@
|
||||
#!/bin/bash
|
||||
# Build a custom Void Linux live ISO with the installer baked in.
|
||||
#
|
||||
# Strategy:
|
||||
# 1. Stage everything possible AS THE HOST USER (overlay, mklive clone, patches, xbps-static).
|
||||
# 2. Run void-mklive's mklive.sh AS ROOT INSIDE A DOCKER CONTAINER.
|
||||
# Avoids the user-namespace CAP_MKNOD/CAP_SYS_ADMIN walls.
|
||||
#
|
||||
# Requires (host): bash, git, curl, docker.
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
CACHE_DIR="${CACHE_DIR:-$PROJECT_DIR/cache}"
|
||||
OUT_DIR="${OUT_DIR:-$PROJECT_DIR/out}"
|
||||
BUILD_DIR="${BUILD_DIR:-$PROJECT_DIR/build}"
|
||||
INCLUDE_DIR="$BUILD_DIR/includes"
|
||||
MKLIVE_DIR="$CACHE_DIR/void-mklive"
|
||||
MKLIVE_REPO="${MKLIVE_REPO:-https://github.com/void-linux/void-mklive.git}"
|
||||
MKLIVE_REF="${MKLIVE_REF:-master}"
|
||||
PATCH_DIR="$PROJECT_DIR/iso/patches"
|
||||
DOCKER_IMAGE="${DOCKER_IMAGE:-void-installer-builder:latest}"
|
||||
DOCKER="${DOCKER:-docker}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "$PROJECT_DIR/config/install.conf"
|
||||
|
||||
SECRETS_FILE="${SECRETS_FILE:-$PROJECT_DIR/secrets.env}"
|
||||
[[ -r "$SECRETS_FILE" ]] || { echo "missing $SECRETS_FILE"; exit 1; }
|
||||
# shellcheck disable=SC1090
|
||||
source "$SECRETS_FILE"
|
||||
: "${USER_PASSWORD:?}"; : "${ROOT_PASSWORD:?}"
|
||||
|
||||
SSH_SRC_DIR="${SSH_SRC_DIR:-$HOME/.ssh}"
|
||||
[[ -d "$SSH_SRC_DIR" ]] || { echo "no SSH dir at $SSH_SRC_DIR"; exit 1; }
|
||||
|
||||
command -v "$DOCKER" >/dev/null \
|
||||
|| { echo "ERROR: '$DOCKER' not in PATH"; exit 1; }
|
||||
"$DOCKER" info >/dev/null 2>&1 \
|
||||
|| { echo "ERROR: '$DOCKER' daemon unreachable"; exit 1; }
|
||||
|
||||
mkdir -p "$CACHE_DIR" "$OUT_DIR" "$BUILD_DIR"
|
||||
|
||||
# 1) clone+patch mklive
|
||||
if [[ ! -d "$MKLIVE_DIR/.git" ]]; then
|
||||
echo ">>> cloning void-mklive"
|
||||
git clone --depth=1 --branch "$MKLIVE_REF" "$MKLIVE_REPO" "$MKLIVE_DIR"
|
||||
fi
|
||||
if compgen -G "$PATCH_DIR/*.patch" >/dev/null; then
|
||||
echo ">>> resetting + applying iso/patches/"
|
||||
( cd "$MKLIVE_DIR" && git checkout -- . )
|
||||
for p in "$PATCH_DIR"/*.patch; do
|
||||
echo " $(basename "$p")"
|
||||
( cd "$MKLIVE_DIR" && patch -p1 --silent < "$p" )
|
||||
done
|
||||
fi
|
||||
|
||||
# 2) xbps-static
|
||||
XBPS_STATIC_DIR="$CACHE_DIR/xbps-static"
|
||||
if [[ ! -x "$XBPS_STATIC_DIR/usr/bin/xbps-install.static" ]]; then
|
||||
echo ">>> downloading xbps-static"
|
||||
mkdir -p "$XBPS_STATIC_DIR"
|
||||
curl -fsSL "https://repo-default.voidlinux.org/static/xbps-static-latest.x86_64-musl.tar.xz" \
|
||||
| tar xJf - -C "$XBPS_STATIC_DIR"
|
||||
fi
|
||||
|
||||
# 3) overlay
|
||||
echo ">>> staging includes overlay at $INCLUDE_DIR"
|
||||
rm -rf "$INCLUDE_DIR"
|
||||
mkdir -p "$INCLUDE_DIR"
|
||||
|
||||
install -d -m 0755 "$INCLUDE_DIR/usr/local/share/installer/lib"
|
||||
install -m 0644 "$PROJECT_DIR/config/install.conf" "$INCLUDE_DIR/usr/local/share/installer/install.conf"
|
||||
# Default package list = stable-cinnamon profile (kept in /share for back-compat).
|
||||
install -m 0644 "$PROJECT_DIR/config/profiles/stable-cinnamon/packages.list" \
|
||||
"$INCLUDE_DIR/usr/local/share/installer/packages.list"
|
||||
install -m 0755 "$PROJECT_DIR/installer/install.sh" "$INCLUDE_DIR/usr/local/share/installer/install.sh"
|
||||
for f in "$PROJECT_DIR"/installer/lib/*.sh; do
|
||||
install -m 0755 "$f" "$INCLUDE_DIR/usr/local/share/installer/lib/$(basename "$f")"
|
||||
done
|
||||
|
||||
# Ship every profile so the live ISO can install any of them via PROFILE=<name>.
|
||||
install -d -m 0755 "$INCLUDE_DIR/usr/local/share/installer/profiles"
|
||||
cp -a "$PROJECT_DIR/config/profiles/." "$INCLUDE_DIR/usr/local/share/installer/profiles/"
|
||||
|
||||
install -d -m 0755 "$INCLUDE_DIR/usr/local/sbin"
|
||||
ln -sf /usr/local/share/installer/install.sh "$INCLUDE_DIR/usr/local/sbin/install-void"
|
||||
|
||||
install -d -m 0700 "$INCLUDE_DIR/etc"
|
||||
{
|
||||
printf "USER_PASSWORD=%q\n" "$USER_PASSWORD"
|
||||
printf "ROOT_PASSWORD=%q\n" "$ROOT_PASSWORD"
|
||||
} > "$INCLUDE_DIR/etc/installer-secrets.env"
|
||||
chmod 0600 "$INCLUDE_DIR/etc/installer-secrets.env"
|
||||
|
||||
install -d -m 0700 "$INCLUDE_DIR/etc/installer-ssh"
|
||||
cp -a "$SSH_SRC_DIR"/. "$INCLUDE_DIR/etc/installer-ssh/"
|
||||
find "$INCLUDE_DIR/etc/installer-ssh" -type f -exec chmod 0600 {} +
|
||||
find "$INCLUDE_DIR/etc/installer-ssh" -type d -exec chmod 0700 {} +
|
||||
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/sv/installer"
|
||||
cat > "$INCLUDE_DIR/etc/sv/installer/run" <<'SV_EOF'
|
||||
#!/bin/sh
|
||||
exec /sbin/agetty --autologin root --noclear tty1 linux
|
||||
SV_EOF
|
||||
chmod 0755 "$INCLUDE_DIR/etc/sv/installer/run"
|
||||
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/sv/agetty-tty1"
|
||||
: > "$INCLUDE_DIR/etc/sv/agetty-tty1/down"
|
||||
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/runit/runsvdir/default"
|
||||
ln -sf /etc/sv/installer "$INCLUDE_DIR/etc/runit/runsvdir/default/installer"
|
||||
|
||||
install -d -m 0700 "$INCLUDE_DIR/root"
|
||||
cat > "$INCLUDE_DIR/root/.bash_profile" <<'PROFILE_EOF'
|
||||
case "$(tty)" in
|
||||
/dev/tty1)
|
||||
if [ ! -f /tmp/.installer-done ]; then
|
||||
touch /tmp/.installer-done
|
||||
clear
|
||||
echo
|
||||
echo " Void Linux Installer (xps9700)"
|
||||
echo " Press ENTER to start, or Ctrl-C within 5s for a shell."
|
||||
sleep 5 || true
|
||||
/usr/local/sbin/install-void || {
|
||||
echo "Installer exited with $?. Dropping to shell."
|
||||
exec /bin/bash
|
||||
}
|
||||
echo "Install complete. Type 'reboot' or 'poweroff'."
|
||||
exec /bin/bash
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
PROFILE_EOF
|
||||
chmod 0644 "$INCLUDE_DIR/root/.bash_profile"
|
||||
|
||||
cat > "$INCLUDE_DIR/etc/motd" <<MOTD_EOF
|
||||
|
||||
Void Linux installer for $HOSTNAME (XPS 17 9700)
|
||||
Run: install-void
|
||||
Logs: /var/log/void-installer.log
|
||||
|
||||
MOTD_EOF
|
||||
|
||||
if [[ -n "${EXTRA_INCLUDE_DIR:-}" && -d "$EXTRA_INCLUDE_DIR" ]]; then
|
||||
echo ">>> merging EXTRA_INCLUDE_DIR=$EXTRA_INCLUDE_DIR"
|
||||
cp -a "$EXTRA_INCLUDE_DIR/." "$INCLUDE_DIR/"
|
||||
fi
|
||||
|
||||
# 3b) Customizations overlay (themes / icons / wallpapers / dotfiles / vscode)
|
||||
echo ">>> staging user customizations overlay"
|
||||
OVERLAY="$INCLUDE_DIR/etc/installer-overlay"
|
||||
install -d -m 0755 "$OVERLAY" "$OVERLAY/wallpapers" \
|
||||
"$OVERLAY/themes" "$OVERLAY/icons" \
|
||||
"$OVERLAY/skel" "$OVERLAY/vscode-user"
|
||||
|
||||
# Wallpapers from ~/Scaricati/pxfuel*.jpg (literal parens in filenames)
|
||||
WP_SRC="${WALLPAPERS_SRC:-$HOME/Scaricati}"
|
||||
shopt -s nullglob
|
||||
for f in "$WP_SRC"/pxfuel*.jpg; do
|
||||
install -m 0644 "$f" "$OVERLAY/wallpapers/$(basename "$f")"
|
||||
done
|
||||
shopt -u nullglob
|
||||
echo " wallpapers: $(ls "$OVERLAY/wallpapers" | wc -l) file(s)"
|
||||
|
||||
# Theme: clone Gruvbox-GTK-Theme and run install.sh into a staging dir.
|
||||
THEME_CACHE="$CACHE_DIR/gruvbox-gtk-theme"
|
||||
if [[ ! -d "$THEME_CACHE/.git" ]]; then
|
||||
git clone --depth=1 https://github.com/Fausto-Korpsvart/Gruvbox-GTK-Theme.git "$THEME_CACHE" || \
|
||||
echo " (warning: could not clone theme repo)"
|
||||
fi
|
||||
THEME_BUILD="$CACHE_DIR/gruvbox-gtk-built"
|
||||
if [[ -x "$THEME_CACHE/themes/install.sh" && ! -d "$THEME_BUILD" ]]; then
|
||||
echo " building gruvbox themes -> $THEME_BUILD (via docker)"
|
||||
install -d -m 0755 "$THEME_BUILD"
|
||||
"$DOCKER" run --rm \
|
||||
-v "$THEME_CACHE":/src \
|
||||
-v "$THEME_BUILD":/out \
|
||||
debian:stable-slim sh -c '
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq >/dev/null
|
||||
apt-get install -y --no-install-recommends sassc bash >/dev/null
|
||||
cd /src/themes && bash install.sh -d /out -t default -c dark -s standard
|
||||
' || echo " (warning: theme build failed; continuing without)"
|
||||
fi
|
||||
if [[ -d "$THEME_BUILD" ]]; then
|
||||
for d in "$THEME_BUILD"/Gruvbox-Dark*; do
|
||||
[[ -d "$d" ]] && cp -a "$d" "$OVERLAY/themes/$(basename "$d")"
|
||||
done
|
||||
echo " themes: $(ls "$OVERLAY/themes" 2>/dev/null | wc -l) variant(s)"
|
||||
fi
|
||||
|
||||
# Icons: clone gruvbox-plus-icon-pack
|
||||
ICON_CACHE="$CACHE_DIR/gruvbox-plus-icons"
|
||||
if [[ ! -d "$ICON_CACHE/.git" ]]; then
|
||||
git clone --depth=1 https://github.com/SylEleuth/gruvbox-plus-icon-pack.git "$ICON_CACHE" || \
|
||||
echo " (warning: could not clone icon repo)"
|
||||
fi
|
||||
if [[ -d "$ICON_CACHE/Gruvbox-Plus-Dark" ]]; then
|
||||
cp -a "$ICON_CACHE/Gruvbox-Plus-Dark" "$OVERLAY/icons/Gruvbox-Plus-Dark"
|
||||
echo " icons: Gruvbox-Plus-Dark deployed"
|
||||
fi
|
||||
|
||||
# Bibata cursor — copied from host (no Void package).
|
||||
BIBATA_SRC="${BIBATA_SRC:-/usr/share/icons/Bibata-Modern-Ice}"
|
||||
if [[ -d "$BIBATA_SRC" ]]; then
|
||||
cp -a "$BIBATA_SRC" "$OVERLAY/icons/Bibata-Modern-Ice"
|
||||
echo " cursor: Bibata-Modern-Ice deployed"
|
||||
else
|
||||
echo " (warning: $BIBATA_SRC missing on host; cursor theme will be skipped)"
|
||||
fi
|
||||
|
||||
# Dotfiles (skel)
|
||||
DOTFILES_SRC="${DOTFILES_SRC:-$HOME}"
|
||||
for f in .bashrc .bash_aliases .gitconfig; do
|
||||
[[ -r "$DOTFILES_SRC/$f" ]] && install -m 0644 "$DOTFILES_SRC/$f" "$OVERLAY/skel/$f"
|
||||
done
|
||||
echo " dotfiles: $(ls -A "$OVERLAY/skel" 2>/dev/null | wc -l) file(s)"
|
||||
|
||||
# VS Code user config
|
||||
VSCODE_SRC="${VSCODE_USER_SRC:-$HOME/.config/Code/User}"
|
||||
if [[ -d "$VSCODE_SRC" ]]; then
|
||||
for f in settings.json keybindings.json mcp.json tasks.json; do
|
||||
[[ -r "$VSCODE_SRC/$f" ]] && install -m 0644 "$VSCODE_SRC/$f" "$OVERLAY/vscode-user/$f"
|
||||
done
|
||||
[[ -d "$VSCODE_SRC/snippets" ]] && cp -a "$VSCODE_SRC/snippets" "$OVERLAY/vscode-user/snippets"
|
||||
# Copy the whole globalStorage so Copilot/extensions keep their state
|
||||
# (note: GitHub OAuth tokens live in libsecret, NOT here — user re-signs once).
|
||||
[[ -d "$VSCODE_SRC/globalStorage" ]] && cp -a "$VSCODE_SRC/globalStorage" "$OVERLAY/vscode-user/globalStorage"
|
||||
echo " vscode-user: $(ls -A "$OVERLAY/vscode-user" 2>/dev/null | wc -l) item(s)"
|
||||
fi
|
||||
|
||||
# VS Code extensions list (so first-login can re-install them).
|
||||
if command -v code >/dev/null 2>&1; then
|
||||
code --list-extensions > "$OVERLAY/vscode-extensions.txt" 2>/dev/null || true
|
||||
echo " vscode extensions: $(wc -l < "$OVERLAY/vscode-extensions.txt" 2>/dev/null) listed"
|
||||
fi
|
||||
|
||||
# Claude Code config + auth (~/.claude lives in $HOME on Linux).
|
||||
CLAUDE_SRC="${CLAUDE_SRC:-$HOME/.claude}"
|
||||
if [[ -d "$CLAUDE_SRC" ]]; then
|
||||
cp -a "$CLAUDE_SRC" "$OVERLAY/claude"
|
||||
echo " claude: ~/.claude bundled"
|
||||
fi
|
||||
CLAUDE_JSON="${CLAUDE_JSON:-$HOME/.claude.json}"
|
||||
if [[ -r "$CLAUDE_JSON" ]]; then
|
||||
install -m 0600 "$CLAUDE_JSON" "$OVERLAY/claude.json"
|
||||
fi
|
||||
|
||||
# VS Code extensions list (host)
|
||||
if command -v code >/dev/null 2>&1; then
|
||||
code --list-extensions > "$OVERLAY/vscode-extensions.txt" 2>/dev/null || true
|
||||
echo " vscode extensions: $(wc -l < "$OVERLAY/vscode-extensions.txt") to install"
|
||||
fi
|
||||
|
||||
# First-login one-shot
|
||||
[[ -r "$PROJECT_DIR/installer/first-login.sh" ]] && \
|
||||
install -m 0755 "$PROJECT_DIR/installer/first-login.sh" "$OVERLAY/first-login.sh"
|
||||
|
||||
|
||||
# 4) packages, output filename
|
||||
ISO_PKGS=$(grep -vE '^\s*(#|$)' "$PROJECT_DIR/config/packages.live.list" | tr '\n' ' ')
|
||||
TS="$(date -u +%Y%m%d)"
|
||||
OUT_ISO="${OUTPUT_ISO:-$OUT_DIR/void-install-${HOSTNAME}-${TS}.iso}"
|
||||
|
||||
# 5) docker
|
||||
echo ">>> building docker image $DOCKER_IMAGE (cached)"
|
||||
# Force the legacy builder if buildx is missing (Docker 29 removed it from
|
||||
# the default `docker build` path; users without docker-buildx-plugin
|
||||
# detected on PATH will otherwise see "unknown command: docker buildx").
|
||||
if "$DOCKER" buildx version >/dev/null 2>&1; then
|
||||
"$DOCKER" build -t "$DOCKER_IMAGE" "$PROJECT_DIR/iso"
|
||||
else
|
||||
DOCKER_BUILDKIT=0 "$DOCKER" build -t "$DOCKER_IMAGE" "$PROJECT_DIR/iso"
|
||||
fi
|
||||
|
||||
echo ">>> running mklive.sh inside docker — output: $OUT_ISO"
|
||||
"$DOCKER" run --rm --privileged \
|
||||
-v "$PROJECT_DIR:/work:rw" \
|
||||
-v "$CACHE_DIR:/cache:rw" \
|
||||
-e ARCH="$ARCH" \
|
||||
-e REPO_URL="$REPO_URL" \
|
||||
-e KEYMAP="$KEYMAP" \
|
||||
-e LOCALE="$LOCALE" \
|
||||
-e ISO_PKGS="$ISO_PKGS" \
|
||||
-e ISO_TITLE="Void Installer ($HOSTNAME)" \
|
||||
-e OUT_ISO_REL="${OUT_ISO#$PROJECT_DIR/}" \
|
||||
-e BOOT_CMDLINE="${BOOT_CMDLINE:-}" \
|
||||
-e HOST_UID="$(id -u)" \
|
||||
-e HOST_GID="$(id -g)" \
|
||||
"$DOCKER_IMAGE" \
|
||||
bash /work/iso/_inner-build.sh
|
||||
|
||||
echo
|
||||
echo ">>> ISO built: $OUT_ISO"
|
||||
sha256sum "$OUT_ISO" | tee "${OUT_ISO}.sha256"
|
||||
38
iso/patches/0001-cgroupv2-lazy-umount.patch
Normal file
38
iso/patches/0001-cgroupv2-lazy-umount.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
--- a/lib.sh
|
||||
+++ b/lib.sh
|
||||
@@ -103,12 +103,16 @@ umount_pseudofs() {
|
||||
# deletable instead throwing the error "Device or Resource Busy".
|
||||
# The '-f' option is passed to umount to account for the
|
||||
# contingency where the psuedofs mounts are not present.
|
||||
+ # On cgroupv2 hosts (e.g. Ubuntu/Mint) some submounts stay busy;
|
||||
+ # fall back to lazy unmount so the build continues cleanly.
|
||||
if [ -d "${ROOTFS}" ]; then
|
||||
for f in dev proc sys; do
|
||||
- umount -R -f "$ROOTFS/$f" >/dev/null 2>&1
|
||||
+ umount -R -f "$ROOTFS/$f" >/dev/null 2>&1 || \
|
||||
+ umount -R -l "$ROOTFS/$f" >/dev/null 2>&1 || true
|
||||
done
|
||||
fi
|
||||
- umount -f "$ROOTFS/tmp" >/dev/null 2>&1
|
||||
+ umount -f "$ROOTFS/tmp" >/dev/null 2>&1 || \
|
||||
+ umount -l "$ROOTFS/tmp" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
run_cmd_target() {
|
||||
--- a/mklive.sh
|
||||
+++ b/mklive.sh
|
||||
@@ -55,10 +55,11 @@ mount_pseudofs() {
|
||||
}
|
||||
|
||||
umount_pseudofs() {
|
||||
+ # lazy unmount fallback for cgroupv2 hosts (Ubuntu/Mint)
|
||||
for f in sys dev proc; do
|
||||
- if [ -d "$ROOTFS/$f" ] && ! umount -R -f "$ROOTFS/$f"; then
|
||||
- info_msg "ERROR: failed to unmount $ROOTFS/$f/"
|
||||
- return 1
|
||||
+ if [ -d "$ROOTFS/$f" ]; then
|
||||
+ umount -R -f "$ROOTFS/$f" >/dev/null 2>&1 || \
|
||||
+ umount -R -l "$ROOTFS/$f" >/dev/null 2>&1 || true
|
||||
fi
|
||||
done
|
||||
}
|
||||
62
iso/patches/0002-mtools-efi-and-onefs-cp.patch
Normal file
62
iso/patches/0002-mtools-efi-and-onefs-cp.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
--- a/mklive.sh
|
||||
+++ b/mklive.sh
|
||||
@@ -386,13 +387,16 @@ EOF
|
||||
|
||||
modprobe -q loop || :
|
||||
|
||||
- # Create EFI vfat image.
|
||||
- truncate -s 32M "$GRUB_DIR"/efiboot.img >/dev/null 2>&1
|
||||
- mkfs.vfat -F12 -S 512 -n "grub_uefi" "$GRUB_DIR/efiboot.img" >/dev/null 2>&1
|
||||
+ # Create EFI vfat image — use mtools so the build does not depend on
|
||||
+ # losetup (avoids CAP_SYS_ADMIN on init userns / works inside containers).
|
||||
+ truncate -s 64M "$GRUB_DIR"/efiboot.img >/dev/null 2>&1
|
||||
+ mformat -i "$GRUB_DIR/efiboot.img" -F -v "grub_uefi" ::
|
||||
|
||||
GRUB_EFI_TMPDIR="$(mktemp --tmpdir="$BUILDDIR" -dt grub-efi.XXXXX)"
|
||||
- LOOP_DEVICE="$(losetup --show --find "${GRUB_DIR}"/efiboot.img)"
|
||||
- mount -o rw,flush -t vfat "${LOOP_DEVICE}" "${GRUB_EFI_TMPDIR}" >/dev/null 2>&1
|
||||
+ LOOP_DEVICE="$(losetup --show --find "${GRUB_DIR}"/efiboot.img 2>/dev/null)" || LOOP_DEVICE=""
|
||||
+ if [ -n "$LOOP_DEVICE" ]; then
|
||||
+ mount -o rw,flush -t vfat "${LOOP_DEVICE}" "${GRUB_EFI_TMPDIR}" >/dev/null 2>&1
|
||||
+ fi
|
||||
|
||||
build_grub_image() {
|
||||
local GRUB_ARCH="$1" EFI_ARCH="$2"
|
||||
@@ -402,8 +406,7 @@ EOF
|
||||
--output="/tmp/boot${EFI_ARCH,,}.efi" \
|
||||
"boot/grub/grub.cfg"
|
||||
if [ $? -ne 0 ]; then
|
||||
- umount "$GRUB_EFI_TMPDIR"
|
||||
- losetup --detach "${LOOP_DEVICE}"
|
||||
+ [ -n "$LOOP_DEVICE" ] && { umount "$GRUB_EFI_TMPDIR"; losetup --detach "${LOOP_DEVICE}"; }
|
||||
die "Failed to generate EFI loader"
|
||||
fi
|
||||
mkdir -p "${GRUB_EFI_TMPDIR}"/EFI/BOOT
|
||||
@@ -426,8 +429,17 @@ EOF
|
||||
build_grub_image arm64 aa64
|
||||
;;
|
||||
esac
|
||||
- umount "$GRUB_EFI_TMPDIR"
|
||||
- losetup --detach "${LOOP_DEVICE}"
|
||||
+ if [ -n "$LOOP_DEVICE" ]; then
|
||||
+ umount "$GRUB_EFI_TMPDIR"
|
||||
+ losetup --detach "${LOOP_DEVICE}"
|
||||
+ else
|
||||
+ (cd "$GRUB_EFI_TMPDIR" && find . -type d | while read -r d; do
|
||||
+ mmd -i "$GRUB_DIR/efiboot.img" "::${d#.}" 2>/dev/null || true
|
||||
+ done)
|
||||
+ (cd "$GRUB_EFI_TMPDIR" && find . -type f | while read -r f; do
|
||||
+ mcopy -i "$GRUB_DIR/efiboot.img" "$f" "::${f#.}"
|
||||
+ done)
|
||||
+ fi
|
||||
rm -rf "$GRUB_EFI_TMPDIR"
|
||||
}
|
||||
|
||||
@@ -442,7 +454,7 @@ generate_squashfs() {
|
||||
mkdir -p "$BUILDDIR/tmp-rootfs"
|
||||
mkfs.ext3 -F -m1 "$BUILDDIR/tmp/LiveOS/ext3fs.img" >/dev/null 2>&1
|
||||
mount -o loop "$BUILDDIR/tmp/LiveOS/ext3fs.img" "$BUILDDIR/tmp-rootfs"
|
||||
- cp -a "$ROOTFS"/* "$BUILDDIR"/tmp-rootfs/
|
||||
+ cp -a --one-file-system "$ROOTFS"/* "$BUILDDIR"/tmp-rootfs/
|
||||
umount -f "$BUILDDIR/tmp-rootfs"
|
||||
mkdir -p "$IMAGEDIR/LiveOS"
|
||||
Reference in New Issue
Block a user