+# make sure main is always included
+[ -z "$COMPONENTS" ] && COMPONENTS="main"
+[ "$_opt_contrib" ] && COMPONENTS="$COMPONENTS contrib"
+
+case "${RELEASE}" in
+ jessie|stretch|buster|bullseye)
+ [ "$_opt_non_free" ] && COMPONENTS="$COMPONENTS non-free"
+ ;;
+ *)
+ [ "$_opt_non_free" ] && COMPONENTS="$COMPONENTS non-free-firmware non-free"
+ ;;
+esac
+
+# command line option checks
+if [ "$_opt_scripts_set" ] ; then
+ ewarn "Deprecation NOTE: --scripts option is deprecated, please switch to --post-scripts instead."
+ SCRIPTS='yes' # deprecated since grml-debootstrap >=0.71
+fi
+
+if [ "$_opt_grub" ] && [ "$_opt_vmfile" ] ; then
+ eerror "The --grub option is incompatible with --vmfile, please drop it from your command line."
+ eerror "The --grub option is unneeded as GRUB will be installed automatically (unless GRUB_INSTALL='no')."
+ bailout 1
+fi
+
+if [ "${_opt_sshcopyid}" ] && [ "${_opt_sshcopyauth}" ] ; then
+ eerror "The --sshcopyid option is incompatible with --sshcopyauth, please drop either of them from your command line."
+ bailout 1
+fi
+
+if [ -n "$ISO" ] && [[ "$DEBOOTSTRAP" =~ mmdebstrap$ ]] ; then
+ eerror "The ISO option is incompatible with usage of mmdebstrap for bootstrapping."
+ eerror "Either drop the --iso ... option or use plain debootstrap instead."
+ bailout 1
+fi
+
+if [ "$DEBUG" = "true" ] ; then
+ set -x
+fi
+
+[ "$_opt_help" ] && {
+ usage
+ exit 0
+}
+
+[ "$_opt_version" ] && {
+ einfo "$PN - version $VERSION"
+ einfo "Report bugs via https://github.com/grml/grml-debootstrap/ or https://grml.org/bugs/"
+ exit 0
+}
+# }}}
+
+# check for root permissions {{{
+if ! check4root ; then
+ echo "For usage instructions please execute '$PN --help'."
+ bailout 1
+fi
+# }}}
+
+# make sure we have what we need {{{
+check4progs "${DEBOOTSTRAP}" || bailout 1
+
+if [ -n "$VIRTUAL" ] ; then
+ check4progs kpartx parted qemu-img || bailout 1
+fi
+# }}}
+
+# source specified configuration file {{{
+if [ -n "$CONFIGFILE" ] ; then
+ einfo "Reading specified config file $CONFIGFILE."
+ bash -n "$CONFIGFILE"
+ # shellcheck disable=SC1091 source=config
+ if ! . "$CONFIGFILE" ; then
+ eerror "Error reading config file $CONFIGFILE" ; bailout 1
+ fi
+fi
+# }}}
+
+# backwards compatibility checks {{{
+if [ -n "$GROOT" ] ; then
+ eerror "Error: you seem to have \$GROOT configured."
+ eerror "This variable is no longer supported, please visit the"
+ eerror "grml-debootstrap documentation for details."
+ bailout 1
+fi
+
+if echo "$GRUB" | grep -q '^hd' ; then
+ eerror "Error: this syntax for the grub configuration variable is no longer supported."
+ eerror "Please do not use hd... any longer but /dev/sdX instead."
+ bailout 1
+fi
+# }}}
+
+# welcome screen {{{
+welcome_dialog()
+{
+ dialog --title "$PN" --yesno "Welcome to the interactive configuration of ${PN}.
+Do you want to continue installing Debian using this frontend?" 0 0 || bailout 0
+}
+# }}}
+
+# ask for target {{{
+prompt_for_target()
+{
+ AVAILABLE_PARTITIONS=$(LANG=C fdisk -l 2>/dev/null | \
+ sed 's/*//' | \
+ grep -v 'Extended$' | \
+ gawk -v num=0 -v ORS=' ' '/^\/dev\// {print $1}'; ls /dev/md[0-9]* 2>/dev/null || true);
+
+ if [ -z "$AVAILABLE_PARTITIONS" ] ; then
+ dialog --title "$PN" --trim \
+ --msgbox "Sorry, no partitions found. Please configure your
+ harddisks (see /proc/partitions) using a tool like fdisk,
+ cfdisk, gpart, gparted,..." 0 0 || bailout 1
+ fi
+
+ PARTITION_LIST=$(for i in $AVAILABLE_PARTITIONS ; do
+ fs="$(blkid -s TYPE -o value "$i" 2>/dev/null)"
+ [ -n "$fs" ] || fs='[no_filesystem_yet]'
+ echo "$i" "$fs"
+ unset fs
+ done)
+
+ # shellcheck disable=SC2086
+ TARGET=$(dialog --title "$PN" --single-quoted --stdout \
+ --menu "Please select the target partition:" 0 0 0 \
+ $PARTITION_LIST) || bailout 1
+}
+# }}}
+
+# ask for bootmanager {{{
+prompt_for_bootmanager()
+{
+ ADDITIONAL_PARAMS=""
+
+ if echo "$TARGET" | grep -q "/dev/md" ; then
+ MBRPART="all disks of Software RAID $TARGET"
+ else
+ # figure out whole disk device
+ found=
+ for device in /dev/disk/by-id/*
+ do
+ [ "$(readlink -f "$device")" = "${TARGET}" ] || continue
+ found=1
+ break
+ done
+ # shellcheck disable=SC2001
+ [ -n "$found" ] && MBRDISK=$(echo "${device}" | sed -e 's/-part[0-9][0-9]*$//')
+ if [ -e "$MBRDISK" ]; then
+ MBRDISK=$(readlink -f "$MBRDISK")
+ else
+ # fall back to old behaviour
+ # shellcheck disable=SC2001
+ MBRDISK=$(echo "${TARGET}" | sed -e 's/[0-9][0-9]*$//')
+ fi
+
+ MBRPART="MBR of $MBRDISK"
+ fi
+
+ for device in cciss/c0d0 sda hda; do
+ if [ "/dev/$device" != "${MBRDISK}" ]; then
+ grep -q $device /proc/partitions && \
+ ADDITIONAL_PARAMS="$ADDITIONAL_PARAMS:$device:install bootmanager grub into MBR of /dev/$device"
+ fi
+ done
+ ADDITIONAL_PARAMS=${ADDITIONAL_PARAMS#:}
+
+ OIFS="$IFS"; IFS=:
+
+ # shellcheck disable=SC2086
+ GETMBR=$(dialog --stdout --title "$PN" --default-item mbr \
+ --menu "Where do you want to install the bootmanager grub?" 0 0 0 \
+ mbr "install bootmanager into $MBRPART" \
+ nowhere "do not install bootmanager at all" \
+ ${ADDITIONAL_PARAMS}) || bailout 3
+ IFS="$OIFS"
+
+ case "$GETMBR" in
+ mbr)
+ # /dev/md0: has to be installed in MBR of /dev/md0 and not in /dev/md:
+ if echo "$TARGET" | grep -q "/dev/md" ; then
+ GRUB="$TARGET"
+ else
+ GRUB="$MBRDISK"
+ fi
+ ;;
+ hda)
+ GRUB="/dev/hda"
+ ;;
+ sda)
+ GRUB="/dev/sda"
+ ;;
+ nowhere)
+ GRUB=''
+ ;;
+ esac
+}
+# }}}
+
+# ask for Debian release {{{
+prompt_for_release()
+{
+ [ -n "$RELEASE" ] && DEFAULT_RELEASE="$RELEASE" || DEFAULT_RELEASE='bullseye'
+ RELEASE="$(dialog --stdout --title "${PN}" --default-item $DEFAULT_RELEASE --menu \
+ "Please enter the Debian release you would like to use for installation:" \
+ 0 50 8 \
+ buster Debian/10 \
+ bullseye Debian/11 \
+ bookworm Debian/12 \
+ sid Debian/unstable)" \
+ || bailout
+}
+# }}}
+
+# ask for hostname {{{
+prompt_for_hostname()
+{
+ HOSTNAME="$(dialog --stdout --title "${PN}" --inputbox \
+ "Please enter the hostname you would like to use for installation:" \
+ 0 0 "$HOSTNAME")" || bailout
+}
+# }}}
+
+# ask for password {{{
+prompt_for_password()
+{
+ if [ "$_opt_nopassword" ] ; then
+ einfo "Skip asking for root password as requested."
+ return 0
+ fi
+
+ ROOTPW1='PW1'
+ ROOTPW2='PW2'
+ while [ "$ROOTPW1" != "$ROOTPW2" ]; do
+ ROOTPW1=$(dialog --insecure --stdout --title "${PN}" --passwordbox \
+ "Please enter the password for the root account:" 10 60) || bailout
+
+ ROOTPW2=$(dialog --insecure --stdout --title "${PN}" --passwordbox \
+ "Please enter the password for the root account again for \
+ confirmation:" 10 60) || bailout
+
+ if [ "$ROOTPW1" != "$ROOTPW2" ]; then
+ dialog --stdout --title "${PN}" --ok-label \
+ "Retry" --msgbox "Passwords do not match!" 10 60
+ fi
+ done
+ ROOTPASSWORD="$ROOTPW1"
+}
+# }}}
+
+# ask for Debian mirror {{{
+prompt_for_mirror()
+{
+ [ -n "$ISO" ] && DEFAULT_MIRROR='local' || DEFAULT_MIRROR='net'
+
+ CHOOSE_MIRROR=$(dialog --stdout --title "$PN" --default-item $DEFAULT_MIRROR \
+ --menu "Where do you want to install from?" 0 0 0 \
+ net "install via network (downloading from mirror)" \
+ local "install from local directory/mirror"
+ )
+
+ if [ "$CHOOSE_MIRROR" = 'net' ] ; then
+ [ -n "$MIRROR" ] || MIRROR='http://deb.debian.org/debian'
+ MIRROR="$(dialog --stdout --title "${PN}" --inputbox \
+ "Please enter Debian mirror you would like to use for installing packages." \
+ 0 0 $MIRROR)" || bailout
+
+ else # CHOOSE_MIRROR == local
+ [ -n "$ISO" ] || ISO='/mnt/mirror'
+ ISO="$(dialog --stdout --title "${PN}" --inputbox \
+ "Please enter directory name you would like to use for installing packages." \
+ 0 0 $ISO)" || bailout
+ fi
+}
+# }}}
+
+# software raid setup {{{
+config_swraid_setup()
+{
+TMPFILE=$(mktemp)
+
+# Currently we support only raid1:
+RAIDLEVEL='raid1'
+
+MD_LIST=$(for i in $(seq 0 9) ; do
+ awk '{print $4}' /proc/partitions | grep -q "md$i" || \
+ echo "/dev/md$i /dev/md$i"
+ done)
+
+# shellcheck disable=SC2086
+TARGET=$(dialog --stdout --title "$PN" --default-item /dev/md0 \
+--menu "Which device do you want to use for ${RAIDLEVEL}?
+
+Notice: activated devices will not be listed for security reasons. Anyway, please make sure the selected device is not in use already!" 0 0 0 \
+$MD_LIST) || bailout 20
+
+AVAILABLE_PARTITIONS=$(LANG=C fdisk -l 2>/dev/null | \
+ sed 's/*//' | \
+ grep -v 'Extended$' | \
+ gawk -v num=0 -v ORS=' ' '/^\/dev\// {print $1}')
+[ -n "$AVAILABLE_PARTITIONS" ] || echo "Fatal error: no partitions available?"
+PARTITION_LIST=$(for i in $AVAILABLE_PARTITIONS ; do
+ echo "$i $(blkid -s TYPE -o value "$i" 2>/dev/null || echo '[no_filesystem_yet]') off"
+ done)
+
+# shellcheck disable=SC2086
+dialog --title "$PN" --separate-output \
+ --checklist "Please select the partitions you would like to use for your $RAIDLEVEL on ${TARGET}:" 0 0 0 \
+ $PARTITION_LIST 2>"$TMPFILE" || bailout
+
+SELECTED_PARTITIONS="$(cat "$TMPFILE")"
+
+NUM_PARTITIONS=0
+while IFS= read -r i; do
+ NUM_PARTITIONS=$(( NUM_PARTITIONS + 1 ))
+done < "$TMPFILE"
+
+ERRORFILE=$(mktemp)
+
+local RC=0
+# shellcheck disable=SC2086
+yes | mdadm --create "${TARGET}" --level="${RAIDLEVEL}" \
+ --raid-devices="${NUM_PARTITIONS}" ${SELECTED_PARTITIONS} >/dev/null 2>$ERRORFILE || RC=$?
+
+if [ "$RC" = 0 ] ; then
+ dialog --title "$PN" --msgbox \
+ "Creating $TARGET was successful." 0 0
+ rm -f "$TMPFILE" "$ERRORFILE"
+else
+ dialog --title "$PN" --msgbox \
+ "There was an error setting up $TARGET:
+
+$(cat "$ERRORFILE")
+
+Exiting." 0 0
+ rm -f "$TMPFILE" "$ERRORFILE"
+ bailout 1
+fi
+
+}
+
+prompt_for_swraid()
+{
+if dialog --stdout --title "$PN" \
+ --defaultno --yesno "Do you want to configure Software RAID?
+
+Please notice that only RAID level 1 is supported by ${PN} currently. Configuration will take place using mdadm." 0 0 ; then
+ config_swraid_setup
+fi
+}
+# }}}
+
+# user should recheck his configuration {{{
+# support full automatic installation:
+checkforrun() {
+ dialog --timeout 10 --title "$PN" \
+ --yesno "Do you want to stop at this stage?
+
+Notice: you are running ${PN} in non-interactive mode.
+${PN} will install Debian ${RELEASE} on ${TARGET}.
+Last chance to quit. Timeout of 10 seconds running....
+
+Do you want to stop now?" 0 0 2>/dev/null
+}
+# }}}
+
+# format efi partition {{{
+format_efi_partition() {
+ if [ -z "$EFI" ] ; then
+ return 0
+ fi
+
+ if ! [ -b "$EFI" ] ; then
+ eerror "Specified efi argument [$EFI] not a valid block device."
+ bailout 1
+ fi
+
+ if fsck.vfat -bn "$EFI" >/dev/null; then
+ einfo "EFI partition $EFI seems to have a FAT filesystem, not modifying."
+ else
+ einfo "EFI partition $EFI doesn't seem to be formatted, creating filesystem."
+ if ! mkfs.fat -F32 -n "EFI" "$EFI" ; then
+ eerror "Error while creating filesystem on ${EFI}."
+ bailout 1
+ fi
+ fi
+}
+# }}}
+
+# check for EFI support or try to enable it {{{
+efi_support() {
+ local efivars_loaded=false
+ # this is for kernels versions before v3.10, which didn't provide efivarfs yet
+ if modprobe efivars &>/dev/null ; then
+ efivars_loaded=true
+ fi
+ # kernel versions v3.10 and newer usually provide efivarfs
+ if modprobe efivarfs &>/dev/null ; then
+ efivars_loaded=true
+ fi
+
+ if [ -d /sys/firmware/efi ] ; then
+ einfo "EFI support detected."
+ return 0
+ fi
+
+ if ! [ -d /sys/firmware/efi ] && [ "${efivars_loaded:-}" = "true" ] ; then
+ einfo "EFI support detected, but system seems to be running in BIOS mode."
+ fi
+
+ return 1
+}
+# }}}
+
+# make sure the user is aware of the used configuration {{{
+checkconfiguration()
+{
+
+if [ -z "$VIRTUAL" ] ; then
+ if efi_support ; then
+ if [ -z "$_opt_efi" ] ; then
+ ewarn "EFI support detected but no --efi option given, please consider enabling it."
+ fi
+ else
+ if [ -n "$_opt_efi" ] ; then
+ eerror "EFI option used but no EFI support detected."
+ bailout 1
+ fi
+ fi
+fi
+
+if [ -n "$AUTOINSTALL" ] ; then
+ if checkforrun ; then
+ eerror "Exiting as requested"
+ bailout 1
+ fi
+elif [ -n "$INTERACTIVE" ] ; then
+
+ INFOTEXT="Please recheck configuration before execution:
+ "
+ [ -n "$TARGET" ] && INFOTEXT="$INFOTEXT
+ Target: $TARGET"
+ [ -n "$GRUB" ] && INFOTEXT="$INFOTEXT
+ Install grub: $GRUB"
+ [ -n "$EFI" ] && INFOTEXT="$INFOTEXT
+ Install efi: $EFI"
+ [ -n "$RELEASE" ] && INFOTEXT="$INFOTEXT
+ Using release: $RELEASE"
+ [ -n "$HOSTNAME" ] && INFOTEXT="$INFOTEXT
+ Using hostname: $HOSTNAME"
+ [ -n "$MIRROR" ] && INFOTEXT="$INFOTEXT
+ Using mirror: $MIRROR"
+ [ -n "$ISO" ] && INFOTEXT="$INFOTEXT
+ Using ISO: $ISO"
+ [ -n "$ARCH" ] && INFOTEXT="$INFOTEXT
+ Using arch: $ARCH"
+ [ -n "$CONFFILES" ] && INFOTEXT="$INFOTEXT
+ Config files: $CONFFILES"
+
+ INFOTEXT="$INFOTEXT
+
+Is this ok for you? Notice: selecting 'No' will exit ${PN}."
+
+ dialog --title "$PN" --no-collapse \
+ --yesno "$INFOTEXT" 0 0 || bailout 0
+
+else # if not running automatic installation display configuration and prompt for execution:
+ einfo "$PN [${VERSION}] - Please recheck configuration before execution:"
+ echo
+ echo " Target: $TARGET"
+
+ # do not display if MNTPOINT is the default one
+ case "$MNTPOINT" in /mnt/debootstrap*) ;; *) echo " Mount point: $MNTPOINT" ;; esac
+
+ if [ -n "$VIRTUAL" ] && [ "$GRUB_INSTALL" = 'yes' ] ; then
+ echo " Install grub: yes"
+ [ -n "$VMEFI" ] && echo " Install efi: yes" || echo " Install efi: no"
+ else
+ [ -n "$GRUB" ] && echo " Install grub: $GRUB" || echo " Install grub: no"
+ [ -n "$EFI" ] && echo " Install efi: $EFI" || echo " Install efi: no"
+ fi
+
+ [ -n "$RELEASE" ] && echo " Using release: $RELEASE"
+ [ -n "$HOSTNAME" ] && echo " Using hostname: $HOSTNAME"
+ [ -n "$MIRROR" ] && echo " Using mirror: $MIRROR"
+ [ -n "$ISO" ] && echo " Using ISO: $ISO"
+ [ -n "$ARCH" ] && echo " Using arch: $ARCH"
+ [ -n "$CONFFILES" ] && echo " Config files: $CONFFILES"
+ if [ -n "$VIRTUAL" ] ; then
+ echo " Deploying as Virtual Machine."
+ if [ -n "$VMSIZE" ] && [ -n "$VMFILE" ]; then
+ echo " Using Virtual Disk file with size of ${VMSIZE}."
+ fi
+ fi
+
+ if [ ! -t 0 ] && [ -z "$ROOTPASSWORD" ] && [ -z "$NOPASSWORD" ] ; then
+ echo
+ echo " You do not have a TTY allocated, your password will be shown in"
+ echo " plaintext on the terminal! If you are using SSH, try its -t option!"
+ fi
+
+ echo
+ echo " Important! Continuing will delete all data from ${TARGET}!"
+
+ if [ -n "$FORCE" ] ; then
+ einfo "Skip user acknowledgement as requested via --force option."
+ else
+ echo
+ einfon "Is this ok for you? [y/N] "
+ read -r a
+ if ! [ "$a" = 'y' ] || [ "$a" = 'Y' ] ; then
+ eerror "Exiting as requested."
+ bailout 1
+ fi
+ fi
+fi
+}
+# }}}
+
+# interactive mode {{{
+interactive_mode()
+{
+ check4progs dialog || bailout 1
+
+ welcome_dialog
+
+ prompt_for_release
+
+ prompt_for_swraid
+
+ prompt_for_target
+
+ prompt_for_bootmanager
+
+ prompt_for_hostname
+
+ prompt_for_password
+
+ prompt_for_mirror
+}
+
+# run interactive mode if we didn't get the according configuration yet
+if [ -z "$TARGET" ] || [ -n "$INTERACTIVE" ] ; then
+ # only target might be unset, so make sure the INTERACTIVE flag is set as well
+ INTERACTIVE=1
+ interactive_mode
+fi
+# }}}
+
+# architecture setup {{{
+if [ -n "$ARCH" ] ; then
+ ARCHCMD="--arch $ARCH"
+ ARCHINFO=" (${ARCH})"
+else
+ ARCH="$(dpkg --print-architecture)"
+ ARCHCMD="--arch $ARCH"
+ ARCHINFO=" (${ARCH})"
+fi
+
+if [ -z "${ARCH:-}" ] ; then
+ eerror 'Architecture neither set (environment variable ARCH), nor could be automatically identified (using dpkg).'
+ eerror 'Consider setting the --arch ... option.'
+ bailout 1
+fi
+# }}}
+
+# It is not possible to build amd64 on i686. {{{
+CURRENT_ARCH="$(uname -m)"
+if [ "$CURRENT_ARCH" != "x86_64" ] ; then
+ if [ "$ARCH" = "amd64" ] ; then
+ eerror "It is not possible to build amd64 on $CURRENT_ARCH. Consider installing and booting the 'linux-image-amd64' kernel or using '--arch i386' instead."
+ bailout 1
+ fi
+fi
+# }}}
+
+# Support for generic release codenames is unavailable. {{{
+if [ "$RELEASE" = "stable" ] || [ "$RELEASE" = "testing" ] ; then
+ eerror "Generic release codenames (stable, testing) are unsupported. \
+Please use specific codenames such as bullseye or bookworm."
+ bailout 1
+fi
+# }}}
+
+checkconfiguration
+
+# finally make sure at least $TARGET is set [the partition for the new system] {{{
+if [ -n "$TARGET" ] ; then
+ SHORT_TARGET="${TARGET##*/}"
+else
+ eerror "Please adjust $CONFFILES/config or..."
+ eerror "... use the interactive version for configuration before running ${0}"
+ bailout 1
+fi
+# }}}