diff --git a/Dockerfile b/Dockerfile index 588026c..67c8e0c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,6 @@ # Use the official Void Linux container FROM ghcr.io/void-linux/void-glibc-full -LABEL org.opencontainers.image.source=https://github.com/midzelis/zquickinit ARG XBPS_REPOS="https://repo-fastly.voidlinux.org/current https://repo-fastly.voidlinux.org/current/nonfree" diff --git a/zquickinit.sh b/zquickinit.sh index bf048e7..2865414 100755 --- a/zquickinit.sh +++ b/zquickinit.sh @@ -27,12 +27,24 @@ SRC_ROOT=${DIR} ZBM_ROOT=${SRC_ROOT}/../zfsbootmenu RECIPES_ROOT=${RECIPES_ROOT:-${SRC_ROOT}/recipes} -RECIPE_BUILDER="ghcr.io/midzelis/zquickinit" -ZQUICKEFI_URL="https://github.com/midzelis/zquickinit/releases/latest" -# if empty, use latest release tag -ZBM_TAG= +RECIPE_BUILDER="${RECIPE_BUILDER:-ghcr.io/midzelis/zquickinit}" +ZQUICKINIT_REPO="${ZQUICKINIT_REPO:-https://github.com/midzelis/zquickinit}" +ZQUICKEFI_URL="${ZQUICKEFI_URL:-${ZQUICKINIT_REPO}/releases/latest}" + +# provide default stable, latest ZBM_TAG if not specified +ZBM_TAG="${ZBM_TAG:-v3.0.1}" +# if empty, then unset to get latest release +if [[ -z "$ZBM_TAG" ]]; then + ZBM_TAG="" +fi + # if specified, takes precedence over ZBM_TAG -ZBM_COMMIT_HASH=db78c980f40937f3b4de8d85e7430f6553a39972 +ZBM_COMMIT_HASH="${ZBM_COMMIT_HASH:-}" +# if ZBM_COMMIT_HASH is specified, unset ZBM_TAG +if [[ -n "$ZBM_COMMIT_HASH" ]]; then + ZBM_TAG="" +fi + INPUT=/input OUTPUT=/output ADD_LOADER= @@ -40,8 +52,10 @@ MKINIT_VERBOSE= KERNEL_BOOT= ENGINE= OBJCOPY= +DU= FIND= YG= +STAT= NOASK=0 DEBUG=0 ENTER=0 @@ -101,10 +115,10 @@ check() { fi fi if [[ $1 == docker || $1 == podman ]]; then - if command -v docker &>/dev/null; then + if [ -z "$ENGINE" ] && command -v docker &>/dev/null; then ENGINE=docker return 0 - elif command -v podman &>/dev/null; then + elif [ -z "$ENGINE" ] && command -v podman &>/dev/null; then ENGINE=podman return 0 fi @@ -142,17 +156,6 @@ check() { OBJCOPY=objcopy fi fi - if ! command -v "$1" &>/dev/null; then - echo "$1 not found. usually part of the $2 package" - if [[ $1 == "gum" && -f "/etc/debian_version" ]]; then - echo "To install, try:" - echo 'sudo mkdir -p /etc/apt/keyrings' - echo 'curl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg' - echo 'echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.list' - echo 'sudo apt update && sudo apt install gum' - fi - exit 1 - fi if [[ $1 == find ]] && [[ -z "${FIND}" ]]; then if command -v gfind &>/dev/null; then FIND="gfind" @@ -168,6 +171,47 @@ check() { exit 1 fi fi + if [[ $1 == du ]] && [[ -z "${DU}" ]]; then + if command -v gdu &>/dev/null; then + DU="gdu" + else + DU="du" + fi + if [[ ! "$(${DU} --version 2>&1 | head -n1)" == *GNU* ]]; then + echo "du must be GNU flavored. Update or install coreutils package. " + if [[ "$OSTYPE" == "darwin"* ]]; then + echo "On MacOS, use brew to install coreutils" + echo "Note: brew uses /usr/local/bin on Intel, and /opt/homebrew/bin on Apple" + fi + exit 1 + fi + fi + if [[ $1 == stat ]] && [[ -z "${STAT}" ]]; then + if command -v gstat &>/dev/null; then + STAT="gstat" + else + STAT="stat" + fi + if [[ ! "$(${STAT} --version 2>&1 | head -n2)" =~ (GNU|BusyBox) ]]; then + echo "stat must be GNU or BusyBox flavored. Update or install coreutils package." + if [[ "$OSTYPE" == "darwin"* ]]; then + echo "On MacOS, use brew to install coreutils" + echo "Note: brew uses /usr/local/bin on Intel, and /opt/homebrew/bin on Apple" + fi + exit 1 + fi + fi + if ! command -v "$1" &>/dev/null; then + echo "$1 not found. usually part of the $2 package" + if [[ $1 == "gum" && -f "/etc/debian_version" ]]; then + echo "To install, try:" + echo 'sudo mkdir -p /etc/apt/keyrings' + echo 'curl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg' + echo 'echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.list' + echo 'sudo apt update && sudo apt install gum' + fi + exit 1 + fi } # This will build the main ZquickInit Builder OCI image @@ -197,6 +241,7 @@ builder() { echo cmd=("$ENGINE" build . -t "$RECIPE_BUILDER" + --label org.opencontainers.image.source="${ZQUICKINIT_REPO}" --build-arg KERNELS=linux6.6 --build-arg "PACKAGES=${packages[*]}" --build-arg ZBM_COMMIT_HASH="${ZBM_COMMIT_HASH}" @@ -225,6 +270,7 @@ tailscale() { make_zquick_initramfs() { check gum gum check mkinitcpio mkinitcpio + check stat stat gum style --bold --border double --align center \ --width 50 --margin "1 2" --padding "0 2" "Welcome to ZQuickInit make initramfs" @@ -234,13 +280,13 @@ make_zquick_initramfs() { local hash echo "Downloading zquickinit" rm -rf "${INPUT}" - git clone --quiet --depth 1 https://github.com/midzelis/zquickinit.git "${INPUT}" + git clone --quiet --depth 1 "${ZQUICKINIT_REPO}" "${INPUT}" hash=$(cat /etc/zquickinit-commit-hash || echo '') if [[ -n "${hash}" ]]; then (cd "${INPUT}" && git fetch --depth 1 origin "$hash" && git checkout FETCH_HEAD) fi fi - [[ -x /etc/zquickinit-commit-hash ]] && (cd "${INPUT}" && git config --global --add safe.directory "${INPUT}" && /etc/zquickinit-commit-hash && git rev-parse HEAD >/etc/zquickinit-commit-hash && echo "ZQuickInit (https://github.com/midzelis/zquickinit) commit hash: $(git rev-parse --short HEAD) ($(git rev-parse HEAD))") + [[ -x /etc/zquickinit-commit-hash ]] && (cd "${INPUT}" && git config --global --add safe.directory "${INPUT}" && /etc/zquickinit-commit-hash && git rev-parse HEAD >/etc/zquickinit-commit-hash && echo "ZQuickInit (${ZQUICKINIT_REPO}) commit hash: $(git rev-parse --short HEAD) ($(git rev-parse HEAD))") if [[ ! -f "${ZBM}/bin/generate-zbm" ]]; then echo "Downloading latest zfsbootmenu" @@ -576,9 +622,9 @@ make_zquick_initramfs() { ) chmod o+rw -R "${OUTPUT}"/* chmod g+rw -R "${OUTPUT}"/* - env LC_ALL=en_US.UTF-8 printf "Kernel size: \t\t%'.0f bytes\n" "$(stat -c '%s' "${OUTPUT}/zquickinit-$build_time.vmlinuz-$kernel")" - env LC_ALL=en_US.UTF-8 printf "initramfs size: \t%'.0f bytes\n" "$(stat -c '%s' "$output_img")" - env LC_ALL=en_US.UTF-8 printf "EFI size: \t\t%'.0f bytes\n" "$(stat -c '%s' "$output_uki")" + env LC_ALL=en_US.UTF-8 printf "Kernel size: \t\t%'.0f bytes\n" "$(${STAT} -c '%s' "${OUTPUT}/zquickinit-$build_time.vmlinuz-$kernel")" + env LC_ALL=en_US.UTF-8 printf "initramfs size: \t%'.0f bytes\n" "$(${STAT} -c '%s' "$output_img")" + env LC_ALL=en_US.UTF-8 printf "EFI size: \t\t%'.0f bytes\n" "$(${STAT} -c '%s' "$output_uki")" find "${OUTPUT}" -name 'zquickinit*.img' | sort -r | tail -n +4 | xargs -r rm find "${OUTPUT}" -name 'zquickinit*.efi' | sort -r | tail -n +4 | xargs -r rm find "${OUTPUT}" -name 'zquickinit*.vmlinuz-*' | sort -r | tail -n +4 | xargs -r rm @@ -631,7 +677,7 @@ getefi() { echo "No image found, finding latest release..." local version='' download='' version=$(curl --silent -qI "${ZQUICKEFI_URL}" | awk -F '/' '/^location/ {print substr($NF, 1, length($NF)-1)}') - download="https://github.com/midzelis/zquickinit/releases/download/$version/zquickinit.efi" + download="${ZQUICKINIT_REPO}/releases/download/$version/zquickinit.efi" source="${tmp}/zquickinit-${version}.efi" echo "Downloading from ${download} to ${source}..." curl -o "$source" --progress-bar -L "${download}" @@ -736,6 +782,7 @@ inject() { check bsdtar "libarchive-tools" check objcopy binutils check truncate coreutils + check stat coreutils check find findutils echo "Secrets were injected, appending '_injected' to name" @@ -753,7 +800,7 @@ inject() { # To append an additional initrd segment, the new archive must aligned to a # 4-byte boundary: https://unix.stackexchange.com/a/737219 - initrd_size=$(stat -c '%s' "${initrd}") + initrd_size=$(${STAT} -c '%s' "${initrd}") initrd_size=$(((initrd_size + 3) / 4 * 4)) truncate -s "${initrd_size}" "${initrd}" @@ -829,6 +876,7 @@ iso() { check xorriso xorriso check truncate coreutils check find findutils + check du coreutils local target=${1:-zquickinit.iso} local source=${2:-} @@ -844,7 +892,7 @@ iso() { local isoroot="${tmp}/iso" mkdir -p "${isoroot}" local size - read -ra size <<<"$(du --apparent-size --block-size=1M "$source")" + read -ra size <<<"$(${DU} --apparent-size --block-size=1M "$source")" local padded=$((size[0] + 12)) local part_img="${tmp}/efs_partition.img" rm -rf "${part_img}" @@ -878,6 +926,7 @@ playground() { check truncate coreutils check qemu-system-x86_64 qemu check find findutils + check nproc coreutils # shellcheck disable=SC2155 local tmp=$(tmpdir) @@ -1101,6 +1150,12 @@ if [[ $(type -t "$command") == function ]]; then shift fi ;; + --engine) + if [[ -n ${2:-} ]]; then + ENGINE=$2 + shift + fi + ;; --no-container) NOCONTAINER=1 ;; @@ -1188,6 +1243,7 @@ else echo " --no-container Do not use containers to build initramfs" echo " --release Do not add QEMU debug, or any secrets" echo " --secrets