#!/usr/bin/env bash ALPINE="https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86_64/alpine-minirootfs-3.20.3-x86_64.tar.gz" CHROOTDIR="./alpine_chroot" log() { case "$2" in error) printf "\e[1m\e[31mERROR:\e[0m \e[1m%s\e[0m\n" "$1">&2;; internal) printf "\e[1m\e[96m >>\e[0m \e[1m%s\e[0m\n" "$1">&2;; ierror) printf "\e[1m\e[31m >>\e[0m \e[1m%s\e[0m\n" "$1">&2;; *) printf "\e[1m\e[92m>>>\e[0m \e[1m%s\e[0m\n" "$1">&2;; esac } mkdir_if_not_exists() { [ -d "$1" ] && return 0 [ -f "$1" ] && rm -f "$1" mkdir "$1" } umount_if_mouted() { [ ! -d "$1" ] && return 0 if grep -qs "$(realpath "$1")" /proc/mounts; then umount "$1" return $? else return 0 fi } require () { which "$1" > /dev/null 2>&1 || { log "$1 not found" error exit 1 } } # shellcheck disable=SC2161 # shellcheck disable=SC2086 arguments() { while [[ $# -gt 0 ]]; do opt="$1" shift case "$(echo ${opt} | tr '[:upper:]' '[:lower:]')" in install) install_chroot break 2 ;; remove) remove_chroot break 2 ;; chroot) chroot_into break 2 ;; -h | -help | --help) usage ;; *) log "Unknown option: $opt" error break 2 ;; esac done } usage() { log "Usage commands:" cat <>\e[0m \e[1m%s\e[0m\n" "Shutdown signal received." _shutdown $sig } trap 'trap " " SIGINT SIGTERM SIGHUP; kill 0; wait; sigterm_handler' SIGINT SIGTERM SIGHUP # Chroot functions require "lsof" require "tar" require "gzip" require "wget" setup_inet() { [ ! -d "$CHROOTDIR" ] && { log "Rootdir [$CHROOTDIR] does not exists" ierror return 2 } echo "nameserver 1.1.1.1" > "$CHROOTDIR/etc/resolv.conf" echo "makelnichroot" > "$CHROOTDIR/etc/hostname" echo "127.0.0.1 localhost" > "$CHROOTDIR/etc/hosts" } prepare_chroot() { [ ! -d "$CHROOTDIR" ] && { log "Rootdir [$CHROOTDIR] does not exists" ierror return 2 } export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:\$PATH mount --bind "$CHROOTDIR" "$CHROOTDIR" mount -t proc proc "$CHROOTDIR/proc" mount -t sysfs sysfs "$CHROOTDIR/sys" mount -t devtmpfs devtmpfs "$CHROOTDIR/dev" mount -t devpts devpts "$CHROOTDIR/dev/pts" mount -t tmpfs devshm "$CHROOTDIR/dev/shm" if uname -m | grep -q aarch64 || [ -f "/proc/sys/fs/binfmt_misc/qemu-aarch64" ]; then log "Cancel qemu-aarch64-static register" else # shellcheck disable=SC2028 echo ':aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:'"$(realpath $CHROOTDIR/qemu-aarch64-static):PF" > /proc/sys/fs/binfmt_misc/register 2> /dev/null || true # shellcheck disable=SC2028 echo ':aarch64ld:M::\x7fELF\x02\x01\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:'"$(realpath $CHROOTDIR/qemu-aarch64-static):PF" > /proc/sys/fs/binfmt_misc/register 2> /dev/null || true fi } detach_chroot() { [ ! -d "$CHROOTDIR" ] && { log "Rootdir [$CHROOTDIR] does not exists" ierror return 2 } umount_if_mouted "$CHROOTDIR/sys" umount_if_mouted "$CHROOTDIR/dev/pts" umount_if_mouted "$CHROOTDIR/dev/shm" umount_if_mouted "$CHROOTDIR/dev" umount_if_mouted "$CHROOTDIR/proc" umount_if_mouted "$CHROOTDIR" if [ -f "/proc/sys/fs/binfmt_misc/aarch64" ]; then echo -1 > /proc/sys/fs/binfmt_misc/aarch64 2> /dev/null fi if [ -f "/proc/sys/fs/binfmt_misc/aarch64ld" ]; then echo -1 > /proc/sys/fs/binfmt_misc/aarch64ld 2> /dev/null fi } install_chroot() { [ -d "$CHROOTDIR" ] && { log "Chroot already installed" error exit 1 } mkdir "$CHROOTDIR" [ ! -f "./alpine.tar.gz" ] && { log "Downloading alpine rootfs tarball" wget -q --show-progress "$ALPINE" -O "./alpine.tar.gz" || { ec=$? log "Failed to download rootfs tarball" error exit "$ec" } } log "Extracting alpine rootfs tarball" tar -xzf "./alpine.tar.gz" -C "$CHROOTDIR/" || { log "Failed to extract rootfs" error } setup_inet prepare_chroot || { log "Failed to setup chroot" error exit 1 } log "Updating apk repos" chroot "$CHROOTDIR" apk update || { log "Failed to update apk repos" error exit 1 } log "Installing pakages" chroot "$CHROOTDIR" apk add shadow fish bash git debootstrap pixz losetup rsync pv wget e2fsprogs libarchive-tools coreutils || { log "Failed to install packages" error exit 1 } chroot "$CHROOTDIR" chsh -s /usr/bin/fish root log "Cloning makelni repo" chroot "$CHROOTDIR" git clone "https://git.timoxa0.su/timoxa0/makelni.git" /makelni || { log "Failed to clone makelni repo" error exit 1 } log "Installing qemu-aarch64-static" { wget -q --show-progress -N https://github.com/multiarch/qemu-user-static/releases/download/v7.2.0-1/qemu-aarch64-static -O "$CHROOTDIR/qemu-aarch64-static" && chmod 755 "$CHROOTDIR/qemu-aarch64-static" } || { log "Failed to install qemu-aarch64-static" error exit 1 } detach_chroot || { log "Failed to detach chroot" error exit 1 } log "Done!" exit 0 } remove_chroot() { [ ! -d "$CHROOTDIR" ] && { log "Chroot not installed" error exit 1 } detach_chroot || { log "Failed to umount chroot" error exit 1 } log "Done!" rm -rf "${CHROOTDIR:?}/" } chroot_into() { prepare_chroot || { log "Failed to setup chroot" error exit 1 } chroot "$CHROOTDIR" /usr/bin/fish detach_chroot || { log "Failed to detach chroot" error exit 1 } }