This feature allows on variant to be dependant upon another, utilizing its package lists and overlays to extend its own.
732 lines
27 KiB
Bash
Executable file
732 lines
27 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
|
|
## Common functions
|
|
#
|
|
# Cleanup and quit if error
|
|
cleanup_and_quit () {
|
|
|
|
# If any paramters are passed we will assume it to be an error
|
|
[[ -n $1 ]] && printf "\e[1;31m<#>\e[0m $*\e[0m\n" >&2
|
|
|
|
if [[ $ARKDEP_NO_CLEANUP -eq 1 ]]; then
|
|
printf 'Cleanup disabled, not running cleanup\n'
|
|
exit 1
|
|
fi
|
|
|
|
umount -Rl $build_image_mountpoint
|
|
|
|
rm $build_image
|
|
rm -rf $build_image_mountpoint
|
|
|
|
# Quit program if argument provided to function
|
|
if [[ -n $1 ]]; then
|
|
exit 1
|
|
fi
|
|
|
|
# Otherwise just quit, there is no error
|
|
exit 0
|
|
|
|
}
|
|
|
|
## Set common variables
|
|
#
|
|
declare -r build_image='/var/tmp/arkdep-build.img'
|
|
declare -r build_image_mountpoint='/var/tmp/arkdep-build'
|
|
declare -r workdir="$build_image_mountpoint/rootfs"
|
|
declare -r variant="$1"
|
|
declare -r build_image_size='15G'
|
|
|
|
# Minimum required storage in KiB
|
|
declare -r minimum_available_root_storage='31457280' # 30G
|
|
declare -r minimum_available_var_storage='20971520' # 20G
|
|
|
|
if [[ -v ARKDEP_CONFIGS ]]; then
|
|
declare -r configsdir="$ARKDEP_CONFIGS"
|
|
else
|
|
declare -r configsdir="$(readlink -m ./arkdep-build.d/)"
|
|
fi
|
|
|
|
# Before we continue setting variables, lets first ensure the configsdir actually exist
|
|
# We do this now to give better error reporting to the user
|
|
if [[ ! -d $configsdir ]]; then
|
|
printf "\e[1;31m<#>\e[0m\e[1m $configsdir does not exist, are you located inside of the configuration directory's parent directory?\n\e[0m"
|
|
exit 1
|
|
fi
|
|
|
|
declare -r variantdir="$configsdir/$variant"
|
|
declare -r type="$(cat $(readlink -m $variantdir/type) 2> /dev/null || (printf '\e[1;31m<#>\e[0m\e[1m Failed to get build type\n\e[0m'; exit 1))"
|
|
|
|
if [[ -v ARKDEP_OUTPUT_TARGET ]]; then
|
|
declare -r output_target="$ARKDEP_OUTPUT_TARGET"
|
|
else
|
|
declare -r output_target="$(pwd)/target"
|
|
fi
|
|
|
|
## Set common functions
|
|
#
|
|
# Generate a 42 character long random string, used for generating psuedo-random image names
|
|
# Unless overwritten with $ARKDEP_CUSTOM_NAME
|
|
gen_random_string () {
|
|
|
|
if [[ -v ARKDEP_CUSTOM_NAME ]]; then
|
|
random=$ARKDEP_CUSTOM_NAME
|
|
else
|
|
random=$(openssl rand -hex 100 | head -c 42)
|
|
fi
|
|
|
|
printf "${random}\n"
|
|
|
|
}
|
|
|
|
# Generate image name
|
|
# If name template exists, use it, otherwise generate random string
|
|
if [[ -f $variantdir/name.sh ]]; then
|
|
declare -r image_name=$(source $variantdir/name.sh)
|
|
else
|
|
declare -r image_name=$(gen_random_string)
|
|
fi
|
|
|
|
## Error checking
|
|
#
|
|
# Quit if not root
|
|
if [[ ! $EUID -eq 0 ]]; then
|
|
printf '\e[1;31m<#>\e[0m\e[1m This program has to be run as root\n\e[0m'
|
|
exit 1
|
|
fi
|
|
|
|
# Check if all dependencies are installed, quit if not
|
|
for prog in btrfs pacstrap; do
|
|
if ! command -v $prog > /dev/null; then
|
|
printf "\e[1;31m<#>\e[0m\e[1m Failed to locate $prog, ensure it is installed\e[0m\n"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Check if requested variant exists
|
|
if [[ ! -d $variantdir ]]; then
|
|
printf '\e[1;31m<#>\e[0m\e[1m The requested variant does not exist\e[0m\n'
|
|
exit 1
|
|
fi
|
|
|
|
# Run the storage check only if we are not building a migration
|
|
if [[ $type != 'migration' ]]; then
|
|
# Ensure we have the required storage available on both /var/tmp and root
|
|
declare root_storage_available=($(df --output=avail /))
|
|
root_storage_available=${root_storage_available[1]}
|
|
declare var_storage_available=($(df --output=avail /var/tmp))
|
|
var_storage_available=${var_storage_available[1]}
|
|
|
|
if [[ $root_storage_available -lt $minimum_available_root_storage ]]; then
|
|
printf 'Not enough storage available on root to export image\n'
|
|
exit 1
|
|
fi
|
|
|
|
if [[ $var_storage_available -lt $minimum_available_var_storage ]]; then
|
|
printf 'Not enough storage available on var to create image\n'
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
## Variants
|
|
#
|
|
# Build migration type image
|
|
if [[ $type == 'migration' ]]; then
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Started migration image build\e[0m\n'
|
|
|
|
# Create output directory structure
|
|
mkdir -p $output_target/$image_name
|
|
|
|
# Copy migration contents to compression target dir
|
|
cp -v $variantdir/migration.sh $output_target/$image_name/$image_name-migration.sh ||
|
|
cleanup_and_quit 'No primary migration script found'
|
|
|
|
# Copy migration related files if they are provided
|
|
if [[ -d $variantdir/migration ]]; then
|
|
cp -rv $variantdir/migration $output_target/$image_name/$image_name-migration
|
|
fi
|
|
|
|
# Compress migration files
|
|
tar -cv -I 'zstd -12 -T0 ' -f $output_target/$image_name.tar.zst -C $output_target/$image_name .
|
|
|
|
# We can just exit, no need to do a cleanup
|
|
exit 0
|
|
|
|
fi
|
|
|
|
# Build archlinux type image
|
|
if [[ $type == 'archlinux' ]]; then
|
|
|
|
# Ensure bootstrap.list exists, if not error and quit
|
|
# This is the mimimum requirement to perform a build and this checked first
|
|
if [[ ! -e $variantdir/bootstrap.list ]]; then
|
|
printf "\e[1;31m<#>\e[0m\e[1m The required file 'bootstrap.list' is not preset in $variantdir\e[0m\n"
|
|
exit 1
|
|
fi
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Started Arch linux image build\e[0m\n'
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Creating disk image\e[0m\n'
|
|
fallocate -l $build_image_size $build_image || cleanup_and_quit "Failed to create disk image at $build_image"
|
|
mkfs.btrfs -f $build_image || cleanup_and_quit "Failed to partition $build_image"
|
|
|
|
printf "\e[1;34m-->\e[0m\e[1m Mounting $build_image at $workdir\e[0m\n"
|
|
# The data is compressed to minimize writes to the disk, the actual export does not maintain this compression
|
|
mount -m -t btrfs -o loop,compress=zstd $build_image $build_image_mountpoint || cleanup_and_quit "Failed to mount disk image to $workdir"
|
|
|
|
# Create temporary Btrfs subvolume
|
|
printf "\e[1;34m-->\e[0m\e[1m Creating temporary Btrfs subvolumes at $workdir\e[0m\n"
|
|
btrfs subvolume create $workdir/ || cleanup_and_quit "Failed to create btrfs subvolume $workdir)"
|
|
mount --bind $workdir $workdir || cleanup_and_exit "Failed to bind mount disk $workdir"
|
|
btrfs subvolume create $workdir/etc || cleanup_and_quit "Failed to create btrfs subvolume $workdir/etc)"
|
|
btrfs subvolume create $workdir/var || cleanup_and_quit "Failed to create btrfs subvolume $workdir/var)"
|
|
|
|
# Read base package list and install base system
|
|
readarray bootstrap_packages < $variantdir/bootstrap.list
|
|
|
|
# Stores package lists from dependency variants
|
|
declare bootstrap_packages_depends=()
|
|
|
|
# Load dependency package lists if present
|
|
if [[ -e $variantdir/depends.list ]]; then
|
|
# We only have to set depends_variants once, it is later not set again in other
|
|
# tasks utilizing dependencies
|
|
readarray depends_variants < $variantdir/depends.list
|
|
# Depends list without code comments
|
|
declare depends_variants_clean=()
|
|
for depend in ${depends_variants[@]}; do
|
|
# If line starts with escape character, ignore it
|
|
[[ $depend == \#* ]] &&
|
|
continue
|
|
|
|
# If line is whitespace, ignore it
|
|
[[ ${depend//[$'\t\r\n']} == '' ]] &&
|
|
continue
|
|
|
|
# Append to depends clean, so we can use it again later
|
|
depends_variants_clean+=(${depend%%#*})
|
|
|
|
# Only run if bootstrap.list exists
|
|
[[ ! -f $configsdir/${depend%%#*}/bootstrap.list ]] &&
|
|
continue
|
|
|
|
readarray -O${#bootstrap_packages_depends[@]} bootstrap_packages_depends < $configsdir/${depend%%#*}/bootstrap.list
|
|
done
|
|
fi
|
|
|
|
# Used to store bootstrap packages list without escape characters and whitespaces
|
|
declare bootstrap_packages_clean=()
|
|
|
|
# Process bootstrap package lists, remove code comments
|
|
for bootstrap_package in "${bootstrap_packages[@]}" "${bootstrap_packages_depends[@]}"; do
|
|
# If line starts with escape character, ignore it
|
|
[[ $bootstrap_package == \#* ]] &&
|
|
continue
|
|
|
|
# If line is whitespace, ignore it
|
|
[[ ${bootstrap_package//[$'\t\r\n']} == '' ]] &&
|
|
continue
|
|
|
|
# Remove escape character at end of line and add to bootstrap_packages_clean
|
|
bootstrap_packages_clean+=(${bootstrap_package%%#*})
|
|
done
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Installing base packages\e[0m\n'
|
|
# If pacman.conf is available in overlay, use it
|
|
if [[ -f $variantdir/pacman.conf ]]; then
|
|
pacstrap -c -C $variantdir/pacman.conf $workdir ${bootstrap_packages_clean[@]} || cleanup_and_quit 'Failed to install secondary package list'
|
|
cp -v $variantdir/pacman.conf $workdir/etc/pacman.conf
|
|
else
|
|
pacstrap -c $workdir ${bootstrap_packages_clean[@]} || cleanup_and_quit 'Failed to bootstrap system'
|
|
fi
|
|
|
|
# If overlay directory exists in variant copy it's contents to the temporary subvolume
|
|
if [[ -d $variantdir/overlay/post_bootstrap ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Copying overlay/post_bootstrap to root\e[0m\n'
|
|
cp -rv $variantdir/overlay/post_bootstrap/* $workdir/
|
|
fi
|
|
|
|
# If we have a depends list, copy overlays from these dependencies, also handle code comments
|
|
if [[ -e $variantdir/depends.list ]]; then
|
|
for depend in ${depends_variants_clean[@]}; do
|
|
# Only run if post_bootstrap exists
|
|
[[ ! -d $configsdir/$depend/overlay/post_bootstrap ]] &&
|
|
continue
|
|
|
|
printf "\e[1;34m-->\e[0m\e[1m Copying $depend/overlay/post_bootstrap to root\e[0m\n"
|
|
cp -rv $configsdir/$depend/overlay/post_bootstrap/* $workdir/
|
|
done
|
|
fi
|
|
|
|
# Run post_bootstrap script if exists
|
|
if [[ -f $variantdir/extensions/post_bootstrap.sh ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Running post_bootstrap extension\e[0m\n'
|
|
(source $variantdir/extensions/post_bootstrap.sh)
|
|
fi
|
|
|
|
# Read package list and install secondary system components, skip if not used
|
|
if [[ -e $variantdir/package.list ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Installing secondary packages\e[0m\n'
|
|
|
|
# Mount the pacman cache
|
|
mount --bind /var/cache/pacman/pkg $workdir/var/cache/pacman/pkg
|
|
|
|
# Read package list and install
|
|
readarray packages < $variantdir/package.list
|
|
# Used to store packages list without escape characters and whitespaces
|
|
declare packages_clean=()
|
|
# Stores package lists from dependency variants
|
|
declare packages_depends=()
|
|
|
|
# Load dependency package lists if present, also handle code comments
|
|
if [[ -e $variantdir/depends.list ]]; then
|
|
for depend in ${depends_variants_clean[@]}; do
|
|
# Only run if package.list exists
|
|
[[ ! -f $configsdir/$depend/package.list ]] &&
|
|
continue
|
|
|
|
readarray -O${#packages_depends[@]} packages_depends < $configsdir/$depend/package.list
|
|
done
|
|
fi
|
|
|
|
# Used to store bootstrap packages list without escape characters and whitespaces
|
|
declare packages_clean=()
|
|
|
|
# Process package lists, remove code comments
|
|
for package in "${packages[@]}" "${packages_depends[@]}"; do
|
|
# If line starts with escape character, ignore it
|
|
[[ $package == \#* ]] &&
|
|
continue
|
|
|
|
# If line is whitespace, ignore it
|
|
[[ ${package//[$'\t\r\n']} == '' ]] &&
|
|
continue
|
|
|
|
# Remove escape character at end of line and add to packages_clean
|
|
packages_clean+=(${package%%#*})
|
|
done
|
|
|
|
# Install packages to new root
|
|
arch-chroot $workdir pacman -S --noconfirm ${packages_clean[@]} || cleanup_and_quit 'Failed to install packages'
|
|
|
|
# Unmount pacman cache
|
|
umount -l $workdir/var/cache/pacman/pkg
|
|
fi
|
|
|
|
# If postinstall overlay directory exists in variant copy it's contents to the temporary subvolume
|
|
if [[ -d $variantdir/overlay/post_install ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Copying overlay/post_install to root\e[0m\n'
|
|
cp -rv $variantdir/overlay/post_install/* $workdir/
|
|
fi
|
|
|
|
# If we have a depends list, copy overlays from these dependencies
|
|
if [[ -e $variantdir/depends.list ]]; then
|
|
for depend in ${depends_variants_clean[@]}; do
|
|
# Only run if post_install exists
|
|
[[ ! -d $configsdir/$depend/overlay/post_install ]] &&
|
|
continue
|
|
|
|
printf "\e[1;34m-->\e[0m\e[1m Copying $depend/overlay/post_install to root\e[0m\n"
|
|
cp -rv $configsdir/$depend/overlay/post_install/* $workdir/
|
|
done
|
|
fi
|
|
|
|
# Run post_install script if exists
|
|
if [[ -f $variantdir/extensions/post_install.sh ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Running post_install extension\e[0m\n'
|
|
(source $variantdir/extensions/post_install.sh)
|
|
fi
|
|
|
|
# Remove subvolumes created by systemd
|
|
[[ -d $workdir/var/lib/portables ]] &&
|
|
printf '\e[1;34m-->\e[0m\e[1m Removing systemd subvolume var/lib/portables\e[0m\n'
|
|
btrfs subvolume delete $workdir/var/lib/portables
|
|
[[ -d $workdir/var/lib/machines ]] &&
|
|
printf '\e[1;34m-->\e[0m\e[1m Removing systemd subvolume var/lib/machines\e[0m\n'
|
|
btrfs subvolume delete $workdir/var/lib/machines
|
|
|
|
# Make /usr/local symlink in var
|
|
printf '\e[1;34m-->\e[0m\e[1m Moving dirs to var and creating symlinks\e[0m\n'
|
|
mv $workdir/usr/local $workdir/var/usrlocal || cleanup_and_quit 'Failed to move usr/local to var/usrlocal'
|
|
ln -sv ../var/usrlocal $workdir/usr/local || cleanup_and_quit 'Failed to create usrlocal symlink'
|
|
|
|
# Opt symlink
|
|
mv $workdir/opt $workdir/var/ || cleanup_and_quit 'Failed to move opt to var/opt'
|
|
ln -sv var/opt $workdir/opt || cleanup_and_quit 'Failed to create opt symlink'
|
|
|
|
# srv symlink
|
|
mv $workdir/srv $workdir/var/srv || cleanup_and_quit 'Failed to move srv to var/srv'
|
|
ln -sv var/srv $workdir/srv || cleanup_and_quit 'Failed to create srv symlink'
|
|
|
|
# mnt symlink
|
|
mv $workdir/mnt $workdir/var/mnt || cleanup_and_quit 'Failed to move mnt to var/mnt'
|
|
ln -sv var/mnt $workdir/mnt || cleanup_and_quit 'Failed to create mnt symlink'
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Creating mountpoints for shared subvolumes\e[0m\n'
|
|
|
|
# Remove the folders to ensure they are empty
|
|
rm -rf $workdir/root
|
|
rm -rf $workdir/var/lib/flatpak
|
|
|
|
# Ensure these folder exist
|
|
mkdir -pv $workdir/root
|
|
mkdir -pv $workdir/arkdep
|
|
mkdir -pv $workdir/var/lib/flatpak
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Moving passwd, shadow and group files to usr/lib\e[0m\n'
|
|
|
|
# Create second passwd, group and shadow file in usr/lib and configure
|
|
for file in passwd group shadow; do
|
|
grep -v "^root:" $workdir/etc/$file > $workdir/usr/lib/$file
|
|
done
|
|
|
|
# Remove all users except for root, is typically overwritten by user overlay but
|
|
# may be used during os installation as a template
|
|
for file in passwd group shadow; do
|
|
grep "^root:" $workdir/etc/$file > $workdir/etc/$file-tmp
|
|
mv $workdir/etc/$file-tmp $workdir/etc/$file
|
|
done
|
|
|
|
# Ensure passwd/group/shadow permissions are set properly
|
|
chmod 600 $workdir/etc/shadow $workdir/usr/lib/shadow
|
|
chmod 644 $workdir/etc/{passwd,group} $workdir/usr/lib/{passwd,group}
|
|
|
|
#
|
|
# nss-switch.conf is added using the overlay
|
|
#
|
|
|
|
# Remove passwd/group/shadow backup files
|
|
rm $workdir/etc/{passwd-,shadow-,group-}
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Moving CPU microcode to usr/lib\e[0m\n'
|
|
# Move CPU firmware to /usr/lib if present
|
|
mv $workdir/boot/*-ucode.img $workdir/usr/lib/
|
|
|
|
# Make subvolume read-only
|
|
printf '\e[1;34m-->\e[0m\e[1m Adding read-only property to subvolumes\e[0m\n'
|
|
btrfs property set -ts $workdir ro true || cleanup_and_quit 'Failed to set root to read-only'
|
|
btrfs property set -ts $workdir/etc ro true || cleanup_and_quit 'Failed to set etc to read-only'
|
|
btrfs property set -ts $workdir/var ro true || cleanup_and_quit 'Failed to set var to read-only'
|
|
|
|
# Create dir for storing the images
|
|
mkdir -p $output_target/$image_name
|
|
|
|
# Add update script, utilized to perform minor system changes and updates
|
|
if [[ -f $variantdir/update.sh ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Including update script\e[0m\n'
|
|
cp -v $variantdir/update.sh $output_target/$image_name/$image_name-update.sh ||
|
|
cleanup_and_quit 'Failed copying update script to image'
|
|
fi
|
|
|
|
# Generate package list
|
|
pacman -Q --root=$workdir > $output_target/$image_name.pkgs
|
|
|
|
# Write subvolume to image
|
|
printf '\e[1;34m-->\e[0m\e[1m Creating images\e[0m\n'
|
|
btrfs send -f $output_target/$image_name/$image_name-rootfs.img $workdir
|
|
btrfs send -f $output_target/$image_name/$image_name-etc.img $workdir/etc
|
|
btrfs send -f $output_target/$image_name/$image_name-var.img $workdir/var
|
|
|
|
if [[ ! -v ARKDEP_NO_TAR ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Compressing images\e[0m\n'
|
|
tar -cv -I 'zstd -12 -T0 ' -f $output_target/$image_name.tar.zst -C $output_target/$image_name .
|
|
fi
|
|
|
|
if [[ -f $variantdir/extensions/post_build.sh ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Running post_build extension\e[0m\n'
|
|
(source $variantdir/extensions/post_build.sh)
|
|
fi
|
|
|
|
cleanup_and_quit
|
|
|
|
fi
|
|
|
|
# Build debian type image
|
|
if [[ $type == 'debian' ]]; then
|
|
|
|
# Get repo configuration
|
|
if [[ ! -s $variant_dir/apt.conf ]]; then
|
|
cleanup_and_quite 'apt.conf expected but is empty or not found'
|
|
else
|
|
declare -r apt_conf=($(cat $variantdir/apt.conf 2> /dev/null))
|
|
# 0. Repo URL (http://deb.debian.org/debian)
|
|
# 1. Suite (focal, sid, unstable etc..)
|
|
declare -r deb_repo=${apt_conf[0]}
|
|
declare -r deb_suite=${apt_conf[1]}
|
|
fi
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Started Debian image build\e[0m\n'
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Creating disk image\e[0m\n'
|
|
fallocate -l $build_image_size $build_image || cleanup_and_quit "Failed to create disk image at $build_image"
|
|
mkfs.btrfs -f $build_image || cleanup_and_quit "Failed to partition $build_image"
|
|
|
|
printf "\e[1;34m-->\e[0m\e[1m Mounting $build_image at $workdir\e[0m\n"
|
|
# The data is compressed to minimize writes to the disk, the actual export does not maintain this compression
|
|
mount -m -t btrfs -o loop,compress=zstd $build_image $build_image_mountpoint || cleanup_and_quit "Failed to mount disk image to $workdir"
|
|
|
|
# Create temporary Btrfs subvolume
|
|
printf "\e[1;34m-->\e[0m\e[1m Creating temporary Btrfs subvolumes at $workdir\e[0m\n"
|
|
btrfs subvolume create $workdir/ || cleanup_and_quit "Failed to create btrfs subvolume $workdir)"
|
|
mount --bind $workdir $workdir || cleanup_and_exit "Failed to bind mount disk $workdir"
|
|
btrfs subvolume create $workdir/etc || cleanup_and_quit "Failed to create btrfs subvolume $workdir/etc)"
|
|
btrfs subvolume create $workdir/var || cleanup_and_quit "Failed to create btrfs subvolume $workdir/var)"
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Installing base packages\e[0m\n'
|
|
# TODO: Do not hard code arch
|
|
[[ ! -d /var/cache/arkdep-debootstrap ]] && mkdir -p /var/cache/apt/archives
|
|
DEBIAN_FRONTEND=noninteractive debootstrap \
|
|
--cache-dir=/var/cache/apt/archives \
|
|
$deb_suite \
|
|
$workdir \
|
|
$deb_repo ||
|
|
cleanup_and_quit 'Failed to bootstrap'
|
|
|
|
# If overlay directory exists in variant copy it's contents to the temporary subvolume
|
|
if [[ -d $variantdir/overlay/post_bootstrap ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Copying overlay/post_bootstrap to root\e[0m\n'
|
|
cp -rv $variantdir/overlay/post_bootstrap/* $workdir/
|
|
fi
|
|
|
|
# Load dependency package lists if present
|
|
if [[ -e $variantdir/depends.list ]]; then
|
|
# We only have to set depends_variants once, it is later not set again in other
|
|
# tasks utilizing dependencies
|
|
readarray depends_variants < $variantdir/depends.list
|
|
# Depends list without code comments
|
|
declare depends_variants_clean=()
|
|
# If we have a depends list, copy overlays from these dependencies
|
|
for depend in ${depends_variants[@]}; do
|
|
# If line starts with escape character, ignore it
|
|
[[ $bootstrap_package == \#* ]] &&
|
|
continue
|
|
|
|
# If line is whitespace, ignore it
|
|
[[ ${bootstrap_package//[$'\t\r\n']} == '' ]] &&
|
|
continue
|
|
|
|
# Append to depends clean, so we can use it again later
|
|
depends_variants_clean+=(${depend%%#*})
|
|
|
|
# Only run if bootstrap.list exists
|
|
[[ ! -d $configsdir/${depend%%#*}/post_bootstrap ]] &&
|
|
continue
|
|
|
|
printf "\e[1;34m-->\e[0m\e[1m Copying ${depend%%#*}/overlay/post_bootstrap to root\e[0m\n"
|
|
cp -rv $configsdir/${depend%%#*}/overlay/post_bootstrap/* $workdir/
|
|
done
|
|
fi
|
|
|
|
# Run post_bootstrap script if exists
|
|
if [[ -f $variantdir/extensions/post_bootstrap.sh ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Running post_bootstrap extension\e[0m\n'
|
|
(source $variantdir/extensions/post_bootstrap.sh)
|
|
fi
|
|
|
|
# Read package list and install secondary system components, skip if not used
|
|
if [[ -f $variantdir/package.list ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Installing secondary packages\e[0m\n'
|
|
|
|
# Mount deb package cache inside of new root
|
|
mount --bind /var/cache/apt/archives $workdir/var/cache/apt/archives
|
|
|
|
# Read package list and install
|
|
readarray packages < $variantdir/package.list
|
|
# Used to store packages list without escape characters and whitespaces
|
|
declare packages_clean=()
|
|
|
|
# Stores package lists from dependency variants
|
|
declare packages_depends=()
|
|
|
|
# Load dependency package lists if present
|
|
if [[ -e $variantdir/depends.list ]]; then
|
|
# We only have to set depends_variants once, it is later not set again in other
|
|
# tasks utilizing dependencies
|
|
readarray depends_variants < $variantdir/depends.list
|
|
for depend in ${depends_variants_clean[@]}; do
|
|
[[ ! -f $configsdir/$depend/package.list ]] &&
|
|
continue
|
|
|
|
# If line starts with escape character, ignore it
|
|
[[ $depend == \#* ]] &&
|
|
continue
|
|
|
|
# If line is whitespace, ignore it
|
|
[[ ${depend//[$'\t\r\n']} == '' ]] &&
|
|
continue
|
|
|
|
readarray -O${#packages_depends[@]} packages_depends < $configsdir/$depend/package.list
|
|
done
|
|
fi
|
|
|
|
# Process package list, remove code comments
|
|
for package in "${packages[@]}" "${packages_depends}"; do
|
|
# If line starts with escape character, ignore it
|
|
[[ $package == \#* ]] &&
|
|
continue
|
|
|
|
# If line is whitespace, ignore it
|
|
[[ ${package//[$'\t\r\n']} == '' ]] &&
|
|
continue
|
|
|
|
# Remove escape character at end of line and add to packages_clean
|
|
packages_clean+=(${package%%#*})
|
|
done
|
|
|
|
# Install packages to new root
|
|
# TODO: Keep using arch-chroot?`
|
|
DEBIAN_FRONTEND=noninteractive arch-chroot $workdir apt-get update ||
|
|
cleanup_and_quit 'Failed to apt update'
|
|
|
|
DEBIAN_FRONTEND=noninteractive arch-chroot $workdir apt-get install -y ${packages_clean[@]} ||
|
|
cleanup_and_quit 'Failed to install packages'
|
|
|
|
umount -l $workdir/var/cache/apt/archives
|
|
|
|
fi
|
|
|
|
# If postinstall overlay directory exists in variant copy it's contents to the temporary subvolume
|
|
if [[ -d $variantdir/overlay/post_install ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Copying overlay/post_install to root\e[0m\n'
|
|
cp -rv $variantdir/overlay/post_install/* $workdir/
|
|
fi
|
|
|
|
# If we have a depends list, copy overlays from these dependencies
|
|
if [[ -e $variantdir/depends.list ]]; then
|
|
for depend in ${depends_variants_clean[@]}; do
|
|
[[ ! -d $configsdir/$depend/overlay/post_install ]] && continue
|
|
printf "\e[1;34m-->\e[0m\e[1m Copying $depend/overlay/post_install to root\e[0m\n"
|
|
cp -rv $variantdir/overlay/post_install/* $workdir/
|
|
done
|
|
fi
|
|
|
|
# Run post_install script if exists
|
|
if [[ -f $variantdir/extensions/post_install.sh ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Running post_install extension\e[0m\n'
|
|
(source $variantdir/extensions/post_install.sh)
|
|
fi
|
|
|
|
# Remove subvolumes created by systemd
|
|
[[ -d $workdir/var/lib/portables ]] &&
|
|
printf '\e[1;34m-->\e[0m\e[1m Removing systemd subvolume var/lib/portables\e[0m\n'
|
|
btrfs subvolume delete $workdir/var/lib/portables
|
|
[[ -d $workdir/var/lib/machines ]] &&
|
|
printf '\e[1;34m-->\e[0m\e[1m Removing systemd subvolume var/lib/machines\e[0m\n'
|
|
btrfs subvolume delete $workdir/var/lib/machines
|
|
|
|
# Make /usr/local symlink in var
|
|
printf '\e[1;34m-->\e[0m\e[1m Moving dirs to var and creating symlinks\e[0m\n'
|
|
mv $workdir/usr/local $workdir/var/usrlocal || cleanup_and_quit 'Failed to move usr/local to var/usrlocal'
|
|
ln -sv ../var/usrlocal $workdir/usr/local || cleanup_and_quit 'Failed to create usrlocal symlink'
|
|
|
|
# Opt symlink
|
|
mv $workdir/opt $workdir/var/ || cleanup_and_quit 'Failed to move opt to var/opt'
|
|
ln -sv var/opt $workdir/opt || cleanup_and_quit 'Failed to create opt symlink'
|
|
|
|
# srv symlink
|
|
mv $workdir/srv $workdir/var/srv || cleanup_and_quit 'Failed to move srv to var/srv'
|
|
ln -sv var/srv $workdir/srv || cleanup_and_quit 'Failed to create srv symlink'
|
|
|
|
# mnt symlink
|
|
mv $workdir/mnt $workdir/var/mnt || cleanup_and_quit 'Failed to move mnt to var/mnt'
|
|
ln -sv var/mnt $workdir/mnt || cleanup_and_quit 'Failed to create mnt symlink'
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Creating mountpoints for shared subvolumes\e[0m\n'
|
|
|
|
# Remove the folders to ensure they are empty
|
|
rm -rf $workdir/root
|
|
rm -rf $workdir/var/lib/flatpak
|
|
|
|
# Ensure these folder exist
|
|
mkdir -pv $workdir/root
|
|
mkdir -pv $workdir/arkdep
|
|
mkdir -pv $workdir/var/lib/flatpak
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Moving passwd, shadow and group files to usr/lib\e[0m\n'
|
|
|
|
# Create second passwd, group and shadow file in usr/lib and configure
|
|
for file in passwd group shadow; do
|
|
grep -v "^root:" $workdir/etc/$file > $workdir/usr/lib/$file
|
|
done
|
|
|
|
# Remove all users except for root, is typically overwritten by user overlay but
|
|
# may be used during os installation as a template
|
|
for file in passwd group shadow; do
|
|
grep "^root:" $workdir/etc/$file > $workdir/etc/$file-tmp
|
|
mv $workdir/etc/$file-tmp $workdir/etc/$file
|
|
done
|
|
|
|
# Ensure passwd/group/shadow permissions are set properly
|
|
chmod 600 $workdir/etc/shadow $workdir/usr/lib/shadow
|
|
chmod 644 $workdir/etc/{passwd,group} $workdir/usr/lib/{passwd,group}
|
|
|
|
#
|
|
# nss-switch.conf is added using the overlay
|
|
#
|
|
|
|
# Remove passwd/group/shadow backup files
|
|
rm $workdir/etc/{passwd-,shadow-,group-}
|
|
|
|
printf '\e[1;34m-->\e[0m\e[1m Moving kernel to usr/lib/modules/\e[0m\n'
|
|
# Move vmlinuz from boot to modules
|
|
# Get kernel version and vmlinuz location
|
|
declare vmlinuz_path=$(readlink -f $workdir/vmlinuz)
|
|
echo $vmlinuz_path
|
|
vmlinuz_path=${vmlinuz_path//$workdir}
|
|
echo $vmlinuz_path
|
|
declare vmlinuz_version=${vmlinuz_path//\/boot\/vmlinuz-}
|
|
echo $vmlinuz_version
|
|
|
|
mv $workdir/$vmlinuz_path $workdir/usr/lib/modules/$vmlinuz_version/vmlinuz || cleanup_and_quit 'Failed to move kernel to modules'
|
|
|
|
#printf '\e[1;34m-->\e[0m\e[1m Moving CPU microcode to usr/lib\e[0m\n'
|
|
# Move CPU firmware to /usr/lib if present
|
|
# TODO: Figure out how to properly handle this
|
|
#mv $workdir/boot/*-ucode.img $workdir/usr/lib/
|
|
|
|
# Make subvolume read-only
|
|
printf '\e[1;34m-->\e[0m\e[1m Adding read-only property to subvolumes\e[0m\n'
|
|
btrfs property set -ts $workdir ro true || cleanup_and_quit 'Failed to set root to read-only'
|
|
btrfs property set -ts $workdir/etc ro true || cleanup_and_quit 'Failed to set etc to read-only'
|
|
btrfs property set -ts $workdir/var ro true || cleanup_and_quit 'Failed to set var to read-only'
|
|
|
|
# Create dir for storing the images
|
|
mkdir -p $output_target/$image_name
|
|
|
|
# Add update script, utilized to perform minor system changes and updates
|
|
if [[ -f $variantdir/update.sh ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Including update script\e[0m\n'
|
|
cp -v $variantdir/update.sh $output_target/$image_name/$image_name-update.sh ||
|
|
cleanup_and_quit 'Failed copying update script to image'
|
|
fi
|
|
|
|
# TODO: Generate package list
|
|
|
|
# Write subvolume to image
|
|
printf '\e[1;34m-->\e[0m\e[1m Creating images\e[0m\n'
|
|
btrfs send -f $output_target/$image_name/$image_name-rootfs.img $workdir
|
|
btrfs send -f $output_target/$image_name/$image_name-etc.img $workdir/etc
|
|
btrfs send -f $output_target/$image_name/$image_name-var.img $workdir/var
|
|
|
|
if [[ ! -v ARKDEP_NO_TAR ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Compressing images\e[0m\n'
|
|
tar -cv -I 'zstd -12 -T0 ' -f $output_target/$image_name.tar.zst -C $output_target/$image_name .
|
|
fi
|
|
|
|
if [[ -f $variantdir/extensions/post_build.sh ]]; then
|
|
printf '\e[1;34m-->\e[0m\e[1m Running post_build extension\e[0m\n'
|
|
(source $variantdir/extensions/post_build.sh)
|
|
fi
|
|
|
|
cleanup_and_quit
|
|
|
|
fi
|
|
|
|
# No valid variant was found
|
|
printf 'No valid type set in configuration\n'
|
|
exit 2
|