#!/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. # Print manual if no parameters provided or invalid amount of parameters is provided if [[ ! -n $1 || -n $2 ]]; then cat <<- END Usage: arkanium-build [variant] Variants: archlinux Plain Arch Linux TTY image arkanelinux Arkane Linux GNOME image Variants are loaded based on their directory names, the ones listed here are included by default. Variables: ARKANIUM_NO_TAR Do not create a compressed tarball, only create the images ARKANIUM_OVERWRITE_RANDOM Define a custom image name END exit 0 fi ## Set common variables # declare -r workdir='/var/tmp/rootfs' declare -r configs_dir="./arkanium-build.d/" declare -r variant="$1" declare -r type="$(cat $(readlink -m $configs_dir/$variant/type))" declare -r output_target="$(pwd)/target/" ## 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 umount $workdir btrfs property set -ts $workdir ro false btrfs property set -ts $workdir/etc ro false btrfs property set -ts $workdir/var ro false # Remove temporary btrfs volumes rm -rf $workdir/etc \ $workdir/var \ $workdir # Quit program if argument provided to function [[ -n $1 ]] && exit 1 # Otherwise just quit, there is no error exit 0 } # Generate a 42 character long random string, used for generating psuedo-random # image names gen_random_string () { if [[ -v ARKANIUM_OVERWRITE_RANDOM ]]; then random=$ARKANIUM_OVERWRITE_RANDOM else random=$(openssl rand -hex 100 | head -c 42) fi printf "${random}\n" } ## Error checking # # Quit if not root [[ ! $EUID -eq 0 ]] && printf '\e[1;31m<#>\e[0m\e[1m This program has to be run as root\n\e[0m' && exit 1 # 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 [[ ! -d arkanium-build.d/$variant ]] && printf '\e[1;31m<#>\e[0m\e[1m The requested variant does not exist\e[0m\n' && exit 1 ## Variants # # Build archlinux type image if [[ $type == 'archlinux' ]]; then # Ensure base.list exists, if not error and quit if [[ ! -e arkanium-build.d/$variant/base.list ]]; then printf "\e[1;31m<#>\e[0m\e[1m The required file 'base.list' is not preset in $(readlink -m $configs_dir/$variant)\e[0m\n" && exit 1 fi printf '\e[1;34m-->\e[0m\e[1m Started Arch linux image build\e[0m\n' # Create temporary Btrfs subvolume printf "\e[1;34m-->\e[0m\e[1m Creating temporary Btrfs subvolumes at $(readlink -m $workdir)\e[0m\n" btrfs subvolume create $workdir || cleanup_and_quit "Failed to create btrfs subvolume $(readlink -m $workdir)" btrfs subvolume create $workdir/etc || cleanup_and_quit "Failed to create btrfs subvolume $(readlink -m $workdir/etc)" btrfs subvolume create $workdir/var || cleanup_and_quit "Failed to create btrfs subvolume $(readlink -m $workdir/var)" printf "\e[1;34m-->\e[0m\e[1m Creating bind mount at $(readlink -m $workdir)\e[0m\n" mount --bind $workdir $workdir # Make /usr/local symlink in var mkdir -vp $workdir/{var/usrlocal,usr} ln -s /var/usrlocal $workdir/usr/local # Read base package list and install base system readarray base_packages < arkanium-build.d/$variant/base.list printf "\e[1;34m-->\e[0m\e[1m Installing base packages\e[0m\n" pacstrap $workdir ${base_packages[*]} || cleanup_and_quit 'Failed to install secondary package list' # If overlay directory exists in variant copy it's contents to the temporary subvolume if [[ -d arkanium-build.d/$variant/overlay ]]; then cp -rv arkanium-build.d/$variant/overlay/* $workdir/ fi # Read package list and install secondary system components, skip if not used if [[ -e arkanium-build.d/$variant/package.list ]]; then printf '\e[1;34m-->\e[0m\e[1m Installing secondary packages...\e[0m\n' readarray packages < arkanium-build.d/$variant/package.list arch-chroot $workdir pacman -S --noconfirm ${packages[*]} || cleanup_and_quit 'Failed to install base packages' fi # Enable systemd services if requested if [[ -e arkanium-build.d/$variant/systemd.services ]]; then printf '\e[1;34m-->\e[0m\e[1m Enabling systemd services...\e[0m\n' readarray services < arkanium-build.d/$variant/systemd.services for service in ${services[*]}; do arch-chroot $workdir systemctl enable $service done fi # Clear pacman cache arch-chroot $workdir pacman --noconfirm -Scc # 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 # Clear pacman cache printf "\e[1;34m-->\e[0m\e[1m Clearing pacman cache\e[0m\n" rm -rf $workdir/var/cache/pacman/pkg/* rm -rf $workdir/var/lib/pacman/local/* # 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 btrfs property set -ts $workdir/etc ro true btrfs property set -ts $workdir/var ro true # Generate random name for new image printf "\e[1;34m-->\e[0m\e[1m Generating psuedo-random image name...\e[0m\n" declare -r image_name=$(gen_random_string) printf "$image_name\n" # Create dir for storing the images mkdir -vp $(readlink -m $output_target/$image_name) # 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 ARKANIUM_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 cleanup_and_quit fi