Files
parchlinux-cloud/build.sh
T

192 lines
5.5 KiB
Bash
Raw Normal View History

2026-10-18 16:42:25 +03:30
#!/bin/bash
set -o nounset -o errexit
readonly DEFAULT_DISK_SIZE="2G"
readonly IMAGE="image.img"
readonly MIRROR='https://fastly.mirror.pkgbuild.com/$repo/os/$arch'
function init() {
readonly ORIG_PWD="${PWD}"
readonly OUTPUT="${PWD}/output"
mkdir -p "${OUTPUT}" "${PWD}/tmp"
local tmpdir
tmpdir="$(mktemp --directory --tmpdir="${PWD}/tmp")"
readonly TMPDIR="${tmpdir}"
if [ -n "${SUDO_UID:-}" ] && [[ -n "${SUDO_GID:-}" ]]; then
chown "${SUDO_UID}:${SUDO_GID}" "${OUTPUT}" "${TMPDIR}"
fi
cd "${TMPDIR}"
readonly MOUNT="${PWD}/mount"
mkdir "${MOUNT}"
}
function cleanup() {
set +o errexit
if [ -n "${MOUNT:-}" ] && mountpoint -q "${MOUNT}"; then
umount --recursive "${MOUNT}" || exit 1
fi
if [ -n "${LOOPDEV:-}" ]; then
losetup -d "${LOOPDEV}"
fi
if [ -n "${TMPDIR:-}" ]; then
rm -rf "${TMPDIR}"
fi
}
trap cleanup EXIT
function setup_disk() {
truncate -s "${DEFAULT_DISK_SIZE}" "${IMAGE}"
sgdisk --align-end \
--clear \
--new 0:0:+1M --typecode=0:ef02 --change-name=0:'BIOS boot partition' \
--new 0:0:+300M --typecode=0:ef00 --change-name=0:'EFI system partition' \
--new 0:0:0 --typecode=0:8304 --change-name=0:'Parch Linux root' \
"${IMAGE}"
LOOPDEV=$(losetup --find --partscan --show "${IMAGE}")
wait_until_settled "${LOOPDEV}"
mkfs.fat -F 32 -S 4096 "${LOOPDEV}p2"
mkfs.btrfs "${LOOPDEV}p3"
mount -o compress=zstd:1 "${LOOPDEV}p3" "${MOUNT}"
mount --mkdir "${LOOPDEV}p2" "${MOUNT}/efi"
}
function bootstrap() {
cat <<EOF >pacman.conf
[options]
Architecture = auto
SigLevel = DatabaseOptional
[world]
SigLevel = Never
Server = https://github.com/parchlinux/world/raw/refs/heads/main/\$arch/
[core]
Include = mirrorlist
[extra]
Include = mirrorlist
EOF
echo "Server = ${MIRROR}" >mirrorlist
pacstrap -c -C pacman.conf -M "${MOUNT}" base linux grub openssh sudo btrfs-progs dosfstools efibootmgr qemu-guest-agent parchlinux-keyring parch-branding lsb-release
gpgconf --homedir "${MOUNT}/etc/pacman.d/gnupg" --kill gpg-agent
cp -a --no-preserve=ownership "${ORIG_PWD}/branding/." "${MOUNT}/"
install -Dm 644 "${ORIG_PWD}/branding/usr/lib/os-release_parch" "${MOUNT}/usr/local/share/parch-branding/os-release"
install -Dm 644 "${ORIG_PWD}/branding/etc/issue_parch" "${MOUNT}/usr/local/share/parch-branding/issue"
install -Dm 644 "${ORIG_PWD}/branding/etc/lsb-release_parch" "${MOUNT}/usr/local/share/parch-branding/lsb-release"
install -Dm 644 "${ORIG_PWD}/branding/usr/share/pixmaps/parch-logo.svg" "${MOUNT}/usr/local/share/parch-branding/pixmaps/parch-logo.svg"
install -Dm 644 "${ORIG_PWD}/branding/usr/share/pixmaps/parch-logo-dark.svg" "${MOUNT}/usr/local/share/parch-branding/pixmaps/parch-logo-dark.svg"
}
function image_cleanup() {
rm -rf "${MOUNT}/etc/pacman.d/gnupg/"
printf '\nMODULES=(virtio_pci virtio_blk virtio_scsi btrfs sr_mod)\n' >>"${MOUNT}/etc/mkinitcpio.conf"
arch-chroot "${MOUNT}" /usr/bin/mkinitcpio -P
sync -f "${MOUNT}/etc/os-release"
fstrim --verbose "${MOUNT}"
fstrim --verbose "${MOUNT}/efi"
}
function wait_until_settled() {
udevadm settle
blockdev --flushbufs --rereadpt "${1}"
until test -e "${1}p3"; do
echo "${1}p3 doesn't exist yet..."
sleep 1
done
}
function mount_image() {
LOOPDEV=$(losetup --find --partscan --show "${1:-${IMAGE}}")
wait_until_settled "${LOOPDEV}"
mount -o compress=zstd:1 "${LOOPDEV}p3" "${MOUNT}"
mount --bind "/var/cache/pacman/pkg" "${MOUNT}/var/cache/pacman/pkg"
}
function unmount_image() {
umount --recursive "${MOUNT}"
losetup -d "${LOOPDEV}"
LOOPDEV=""
}
function mv_to_output() {
sha256sum "${1}" >"${1}.SHA256"
if [ -n "${SUDO_UID:-}" ]; then
chown "${SUDO_UID}:${SUDO_GID}" "${1}"{,.SHA256}
fi
mv "${1}"{,.SHA256} "${OUTPUT}/"
}
function create_image() {
local tmp_image
tmp_image="$(basename "$(mktemp -u)")"
cp -a "${IMAGE}" "${tmp_image}"
if [ -n "${DISK_SIZE}" ]; then
truncate -s "${DISK_SIZE}" "${tmp_image}"
sgdisk --align-end --delete 3 "${tmp_image}"
sgdisk --align-end --move-second-header \
--new 0:0:0 --typecode=0:8304 --change-name=0:'Parch Linux root' \
"${tmp_image}"
fi
mount_image "${tmp_image}"
if [ -n "${DISK_SIZE}" ]; then
btrfs filesystem resize max "${MOUNT}"
fi
if [ 0 -lt "${#PACKAGES[@]}" ]; then
arch-chroot "${MOUNT}" /usr/bin/pacman -S --noconfirm "${PACKAGES[@]}"
fi
if [ 0 -lt "${#SERVICES[@]}" ]; then
arch-chroot "${MOUNT}" /usr/bin/systemctl enable "${SERVICES[@]}"
fi
"${2}"
image_cleanup
unmount_image
"${3}" "${tmp_image}" "${1}"
mv_to_output "${1}"
}
function main() {
if [ "$(id -u)" -ne 0 ]; then
echo "root is required"
exit 1
fi
init
if [ -n "${2:-}" ] && [ ! -f "${ORIG_PWD}/images/${2}.sh" ]; then
echo "Unknown image variant '${2}'. Available variants are: $(find "${ORIG_PWD}/images" -maxdepth 1 -type f -name '*.sh' ! -name base.sh -printf '%f\n' | sed 's/\.sh$//' | tr '\n' ' ')"
exit 1
fi
setup_disk
bootstrap
source "${ORIG_PWD}/images/base.sh"
pre
unmount_image
local build_version
if [ -z "${1:-}" ]; then
build_version="$(date +%Y%m%d).0"
echo "WARNING: BUILD_VERSION wasn't set!"
echo "Falling back to $build_version"
else
build_version="${1}"
fi
for image in "${ORIG_PWD}/images/"*.sh; do
if [ "$(basename "${image}")" = "base.sh" ]; then
continue
fi
if [ -n "${2:-}" ] && [ "$(basename "${image}" .sh)" != "${2}" ]; then
continue
fi
source "${image}"
create_image "${IMAGE_NAME}" pre post
done
}
main "$@"