From 76ea7500b23432399984ccfb41820e205bd31522 Mon Sep 17 00:00:00 2001 From: Michael Aldridge Date: Tue, 19 Apr 2016 01:21:38 -0500 Subject: [PATCH] Add an automatic install option to the initramfs. --- autoinstaller/autoinstall.cfg | 76 +++++++++ autoinstaller/install.sh | 293 ++++++++++++++++++++++++++++++++++ autoinstaller/module-setup.sh | 45 ++++++ mklive.sh.in | 11 +- 4 files changed, 423 insertions(+), 2 deletions(-) create mode 100644 autoinstaller/autoinstall.cfg create mode 100755 autoinstaller/install.sh create mode 100644 autoinstaller/module-setup.sh diff --git a/autoinstaller/autoinstall.cfg b/autoinstaller/autoinstall.cfg new file mode 100644 index 0000000..b50296c --- /dev/null +++ b/autoinstaller/autoinstall.cfg @@ -0,0 +1,76 @@ +#!/bin/sh +# Void Linux Automatic Install Configuration + +# === +# Disk Configuration +# === +# disk: the disk to install to +# default: the first disk that isn't the installer +#disk=/dev/hda + +# bootpartitionsize: controls how large the boot partition will be +# default: 500M +#bootpartitionsize=500M + +# swapsize: how large should the swap partition be +# default: equal to the installed physical memory +#swapsize= + +# === +# XBPS Configuration +# === +# xbpsrepository: which repo should the install pull from +# default: http://repo.voidlinux.eu/current +#xbpsrepository="http://repo.voidlinux.eu/current" + +# pkgs: additional packages to install into the target +# default: none +#pkgs="" + +# === +# Default User +# === +# username: the username of the user to be created +# default: voidlinux +#username="" + +# password: password to set for the new user +# default: unset (will prompt during install) +# Warning: This does not work in musl! +#password="" + +# === +# Misc. Options +# === +# timezone: Timezone in TZ format +# default: America/Chicago +#timezone="America/Chicago" + +# keymap: Keymap to use by default +# default: us +#keymap="us" + +# locale: initial glibc locale +# default: en_US.UTF-8 +#libclocale=en.US.UTF-8 + +# hostname: static hostname for the system +# default: derived from DNS +#hostname=VoidLinux + +# end_action: what to do at the end of the install +# default: shutdown +# alternate values: reboot, script, func +#end_action=shutdown + +# end_script: script to optionally run at end of install +# the user script must reside somewhere xbps-uhelper fetch +# can retrieve it from +# default: not set +#end_script="" + +# end_function: a function to optionally be run at +# the end of the install. +#end_function() { +# +#} diff --git a/autoinstaller/install.sh b/autoinstaller/install.sh new file mode 100755 index 0000000..ff0a70b --- /dev/null +++ b/autoinstaller/install.sh @@ -0,0 +1,293 @@ +#!/bin/sh + +set -e + +# These functions pulled from void's excellent mklive.sh +VAI_info_msg() { + printf "\033[1m%s\n\033[m" "$@" +} + +VAI_print_step() { + CURRENT_STEP=$((CURRENT_STEP+1)) + VAI_info_msg "[${CURRENT_STEP}/${STEP_COUNT}] $*" +} + +# ----------------------- Install Functions ------------------------ + +VAI_welcome() { + clear + printf "=============================================================\n" + printf "================ Void Linux Auto-Installer ==================\n" + printf "=============================================================\n" +} + +VAI_get_address() { + # Enable the hook for resolv.conf + mkdir -p /usr/lib/dhcpcd/dhcpcd-hooks + ln -sf /usr/libexec/dhcpcd-hooks/20-resolv.conf /usr/lib/dhcpcd/dhcpcd-hooks/ + + # Get an IP address + dhcpcd -w -L --timeout 0 +} + +VAI_partition_disk() { + # Paritition Disk + sfdisk "${disk}" < "${target}/etc/sudoers.d/wheel" +} + +VAI_correct_root_permissions() { + chroot "${target}" chown root:root / + chroot "${target}" chmod 755 / +} + +VAI_configure_hostname() { + # Set the hostname + echo "${hostname}" > "${target}/etc/hostname" +} + +VAI_configure_rc_conf() { + # Set the value of various tokens + sed -i "s:Europe/Madrid:${timezone}:" "${target}/etc/rc.conf" + sed -i "s:\"es\":\"${keymap}\":" "${target}/etc/rc.conf" + + # Activate various tokens + sed -i "s:#HARDWARECLOCK:HARDWARECLOCK:" "${target}/etc/rc.conf" + sed -i "s:#TIMEZONE:TIMEZONE:" "${target}/etc/rc.conf" + sed -i "s:#KEYMAP:KEYMAP:" "${target}/etc/rc.conf" +} + +VAI_add_user() { + chroot "${target}" useradd -m -s /bin/bash -U -G wheel,users,audio,video,cdrom,input "${username}" + if [ -z "${password}" ] ; then + chroot "${target}" passwd "${username}" + else + # For reasons that remain unclear, this does not work in musl + echo "${username}:${password}" | chpasswd -c SHA512 -R "${target}" +fi +} + +VAI_configure_grub() { + # Set hostonly + echo "hostonly=yes" > "${target}/etc/dracut.conf.d/hostonly.conf" + + # Choose the newest kernel + kernel_version="$(chroot "${target}" xbps-query linux | awk -F "[-_]" '/pkgver/ {print $2}')" + + # Install grub + chroot "${target}" grub-install "${disk}" + chroot "${target}" xbps-reconfigure -f "linux${kernel_version}" + + # Correct the grub install + chroot "${target}" update-grub +} + +VAI_configure_fstab() { + # Grab UUIDs + uuid1="$(blkid -s UUID -o value "${disk}1")" + uuid2="$(blkid -s UUID -o value "${disk}2")" + uuid3="$(blkid -s UUID -o value "${disk}3")" + + # Installl UUIDs into /etc/fstab + echo "UUID=$uuid3 / ext4 defaults,errors=remount-ro 0 1" >> "${target}/etc/fstab" + echo "UUID=$uuid1 /boot ext4 defaults 0 2" >> "${target}/etc/fstab" + if [ "${swapsize}" -ne 0 ] ; then + echo "UUID=$uuid2 swap swap defaults 0 0" >> "${target}/etc/fstab" + fi +} + +VAI_configure_locale() { + # Set the libc-locale iff glibc + case "${XBPS_ARCH}" in + *-musl) + VAI_info_msg "Glibc locales are not supported on musl" + ;; + *) + sed -i "/${libclocale}/s/#//" "${target}/etc/default/libc-locales" + + chroot "${target}" xbps-reconfigure -f glibc-locales + ;; + esac +} + +VAI_end_action() { + case $end_action in + reboot) + VAI_info_msg "Rebooting the system" + sync + umount -R "${target}" + reboot -f + ;; + shutdown) + VAI_info_msg "Shutting down the system" + sync + umount -R "${target}" + poweroff -f + ;; + script) + VAI_info_msg "Running user provided script" + xbps-uhelper fetch "${end_script}>/script" + chmod +x /script + target=${target} xbpsrepository=${xbpsrepository} /script + ;; + func) + VAI_info_msg "Running user provided function" + end_function + ;; + esac +} + +VAI_configure_autoinstall() { + # -------------------------- Setup defaults --------------------------- + bootpartitionsize="500M" + disk="$(lsblk -ipo NAME,TYPE,MOUNTPOINT | awk '{if ($2=="disk") {disks[$1]=0; last=$1} if ($3=="/") {disks[last]++}} END {for (a in disks) {if(disks[a] == 0){print a; break}}}')" + hostname="$(ip -4 -o -r a | awk -F'[ ./]' '{x=$7} END {print x}')" + swapsize="$(awk -F"\n" '/MemTotal/ {split($0, b, " "); print b[2] }' /proc/meminfo)"; + target="/mnt" + timezone="America/Chicago" + keymap="us" + libclocale="en_US.UTF-8" + username="voidlinux" + end_action="shutdown" + end_script="/bin/true" + + XBPS_ARCH="$(xbps-uhelper arch)" + case $XBPS_ARCH in + *-musl) + xbpsrepository="https://repo.voidlinux.eu/current/musl" + ;; + *) + xbpsrepository="https://repo.voidlinux.eu/current" + ;; + esac + + # --------------- Pull config URL out of kernel cmdline ------------------------- + if getargbool 0 autourl ; then + xbps-uhelper fetch "$(getarg autourl)>/etc/autoinstall.cfg" + + else + mv /etc/autoinstall.default /etc/autoinstall.cfg + fi + + # Read in the resulting config file which we got via some method + if [ -f /etc/autoinstall.cfg ] ; then + VAI_info_msg "Reading configuration file" + . ./etc/autoinstall.cfg + fi + + # Bail out if we didn't get a usable disk + if [ -z "$disk" ] ; then + die "No valid disk!" + fi +} + +VAI_main() { + CURRENT_STEP=0 + STEP_COUNT=16 + + VAI_welcome + + VAI_print_step "Bring up the network" + VAI_get_address + + VAI_print_step "Configuring installer" + VAI_configure_autoinstall + + VAI_print_step "Configuring disk using scheme 'Atomic'" + VAI_partition_disk + VAI_format_disk + + VAI_print_step "Mounting the target filesystems" + VAI_mount_target + + VAI_print_step "Installing XBPS keys" + VAI_install_xbps_keys + + VAI_print_step "Installing the base system" + VAI_install_base_system + + VAI_print_step "Granting sudo to default user" + VAI_configure_sudo + + VAI_print_step "Setting hostname" + VAI_configure_hostname + + VAI_print_step "Configure rc.conf" + VAI_configure_rc_conf + + VAI_print_step "Preparing the chroot" + VAI_prepare_chroot + + VAI_print_step "Fix ownership of /" + VAI_correct_root_permissions + + VAI_print_step "Adding default user" + VAI_add_user + + VAI_print_step "Configuring GRUB" + VAI_configure_grub + + VAI_print_step "Configuring /etc/fstab" + VAI_configure_fstab + + VAI_print_step "Configuring libc-locales" + VAI_configure_locale + + VAI_print_step "Performing end-action" + VAI_end_action +} + +# If we are using the autoinstaller, launch it +if getargbool 0 auto ; then + VAI_main +fi + +# Very important to release this before returning to dracut code +set +e diff --git a/autoinstaller/module-setup.sh b/autoinstaller/module-setup.sh new file mode 100644 index 0000000..0b7e488 --- /dev/null +++ b/autoinstaller/module-setup.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +check() { + return 255 +} + +depends() { + echo network +} + +install() { + inst /usr/bin/awk + inst /usr/bin/chmod + inst /usr/bin/chroot + inst /usr/bin/clear + inst /usr/bin/cp + inst /usr/bin/chpasswd + inst /usr/bin/dhcpcd + inst /usr/bin/halt + inst /usr/bin/install + inst /usr/bin/lsblk + inst /usr/bin/mkdir + inst /usr/bin/mkfs.ext4 + inst /usr/bin/mkswap + inst /usr/bin/mount + inst /usr/bin/sfdisk + inst /usr/bin/sync + inst /usr/bin/xbps-install + inst /usr/bin/xbps-uhelper + inst /usr/bin/xbps-query + + inst /usr/libexec/dhcpcd-hooks/20-resolv.conf + inst /usr/libexec/dhcpcd-run-hooks + + inst_multiple /var/db/xbps/keys/* + inst_multiple /usr/share/xbps.d/* + + inst_multiple /etc/ssl/certs/* + inst /etc/ssl/certs.pem + + inst_hook pre-mount 01 "$moddir/install.sh" + inst "$moddir/autoinstall.cfg" /etc/autoinstall.default +} diff --git a/mklive.sh.in b/mklive.sh.in index 5b5df67..91b3496 100644 --- a/mklive.sh.in +++ b/mklive.sh.in @@ -30,7 +30,7 @@ trap 'error_out $? $LINENO' INT TERM 0 umask 022 readonly REQUIRED_PKGS="base-files libgcc dash coreutils sed tar gawk syslinux grub-i386-efi grub-x86_64-efi squashfs-tools xorriso" -readonly INITRAMFS_PKGS="binutils xz device-mapper" +readonly INITRAMFS_PKGS="binutils xz device-mapper dhclient dracut-network" readonly PROGNAME=$(basename $0) info_msg() { @@ -103,6 +103,11 @@ copy_dracut_files() { cp dracut/* $1/usr/lib/dracut/modules.d/01vmklive/ } +copy_autoinstaller_files() { + mkdir -p $1/usr/lib/dracut/modules.d/01autoinstaller + cp autoinstaller/* $1/usr/lib/dracut/modules.d/01autoinstaller/ +} + install_prereqs() { copy_void_conf $VOIDHOSTDIR XBPS_ARCH=$ARCH $XBPS_INSTALL_CMD -r $VOIDHOSTDIR $XBPS_REPOSITORY \ @@ -149,13 +154,14 @@ generate_initramfs() { local _args copy_dracut_files $ROOTFS + copy_autoinstaller_files $ROOTFS if [ "$BASE_SYSTEM_PKG" = "base-system-systemd" ]; then _args="--add systemd" else _args="--omit systemd" fi chroot $ROOTFS env -i /usr/bin/dracut -N --${INITRAMFS_COMPRESSION} \ - --add-drivers "ahci" --force-add "vmklive" ${_args} "/boot/initrd" $KERNELVERSION + --add-drivers "ahci" --force-add "vmklive autoinstaller" ${_args} "/boot/initrd" $KERNELVERSION [ $? -ne 0 ] && die "Failed to generate the initramfs" mv $ROOTFS/boot/initrd $BOOT_DIR @@ -172,6 +178,7 @@ cleanup_rootfs() { fi done rm -r $ROOTFS/usr/lib/dracut/modules.d/01vmklive + rm -r $ROOTFS/usr/lib/dracut/modules.d/01autoinstaller } generate_isolinux_boot() {