X-Git-Url: https://git.grml.org/?p=grml-debootstrap.git;a=blobdiff_plain;f=grml-debootstrap;h=2d9aa1d24c857a44835e66c6723e04d980865ed1;hp=016daec250184843c81c8ce3e4270e5db3243188;hb=59e75958079096421a679c83e2526c973038ba83;hpb=8b62d45fcb295cc9b0208d097ec6c9768a887540 diff --git a/grml-debootstrap b/grml-debootstrap index 016daec..2d9aa1d 100755 --- a/grml-debootstrap +++ b/grml-debootstrap @@ -72,7 +72,7 @@ MNTPOINT="/mnt/debootstrap.$$" [ -n "$POST_SCRIPTS" ] || POST_SCRIPTS='yes' [ -n "$PRE_SCRIPTS" ] || PRE_SCRIPTS='yes' [ -n "$RECONFIGURE" ] || RECONFIGURE='console-data' -[ -n "$RELEASE" ] || RELEASE='buster' +[ -n "$RELEASE" ] || RELEASE='bullseye' [ -n "$RM_APTCACHE" ] || RM_APTCACHE='yes' [ -n "$SCRIPTS" ] || SCRIPTS='no' # deprecated, replaced by POST_SCRIPTS [ -n "$SECURE" ] || SECURE='yes' @@ -103,7 +103,7 @@ Bootstrap options: -m, --mirror Mirror which should be used for apt-get/aptitude. -i, --iso Mountpoint where a Debian ISO is mounted to, for use instead of fetching packages from a mirror. - -r, --release Release of new Debian system (default: buster). + -r, --release Release of new Debian system (default: bullseye). -t, --target Target partition (/dev/...) or directory where the system should be installed to. -p, --mntpoint Mountpoint used for mounting the target system, @@ -155,6 +155,8 @@ Configuration options: --hostname Hostname of Debian system. --nopassword Do not prompt for the root password. --password Use specified password as password for user root. + --sshcopyauth Use ${HOME}/.ssh/authorized_keys to authorise root login on the target system. + --sshcopyid Use locally available public keys to authorise root login on the target system. --bootappend Add specified appendline to kernel whilst booting. --chroot-scripts Execute chroot scripts from specified directory. --pre-scripts Execute scripts from specified directory (before chroot-scripts). @@ -181,10 +183,18 @@ fi # }}} # early helper functions {{{ -GOOD='' -BAD='' -WARN='' -NORMAL='' +# skip colors when running within a dumb terminal +if [ "${TERM}" = "dumb" ] ; then + GOOD= + BAD= + WARN= + NORMAL= +else + GOOD='' + BAD='' + WARN='' + NORMAL='' +fi einfo() { einfon "$1\\n" @@ -334,10 +344,6 @@ stage() { } # }}} -# make sure we have what we need {{{ -check4progs "${DEBOOTSTRAP}" || bailout 1 -# }}} - # source main configuration file {{{ if [ -r /etc/debootstrap/config ] ; then # shellcheck disable=SC1091 @@ -346,7 +352,7 @@ fi # }}} # cmdline handling {{{ -CMDLINE_OPTS=mirror:,iso:,release:,target:,mntpoint:,debopt:,defaultinterfaces,interactive,nodebootstrap,nointerfaces,nokernel,nopackages,filesystem:,config:,confdir:,packages:,chroot-scripts:,scripts:,post-scripts:,pre-scripts:,debconf:,vm,vmfile,vmsize:,keep_src_list,hostname:,password:,nopassword,grmlrepos,backportrepos,bootappend:,grub:,efi:,arch:,insecure,verbose,help,version,force,debug,contrib,non-free,remove-configs +CMDLINE_OPTS=mirror:,iso:,release:,target:,mntpoint:,debopt:,defaultinterfaces,interactive,nodebootstrap,nointerfaces,nokernel,nopackages,filesystem:,config:,confdir:,packages:,chroot-scripts:,scripts:,post-scripts:,pre-scripts:,debconf:,vm,vmfile,vmsize:,keep_src_list,hostname:,password:,nopassword,grmlrepos,backportrepos,bootappend:,grub:,efi:,arch:,insecure,verbose,help,version,force,debug,contrib,non-free,remove-configs,sshcopyid,sshcopyauth _opt_temp=$(getopt --name grml-debootstrap -o +m:i:r:t:p:c:d:vhV --long \ $CMDLINE_OPTS -- "$@") @@ -388,7 +394,7 @@ while :; do shift; _opt_debopt="$1" ;; --filesystem) # Filesystem that should be used - shift; _opt_filesystem="$1" + shift; _opt_filesystem="$1" ; FILESYSTEM="${_opt_filesystem}" ;; --interactive) # Use interactive mode (frontend) _opt_interactive=T @@ -460,6 +466,12 @@ while :; do --nopassword) # Skip password dialog _opt_nopassword=T ;; + --sshcopyid) # Use locally available public keys to authorise root login on the target system + _opt_sshcopyid=T + ;; + --sshcopyauth) # Use .ssh/authorized_keys to authorise root login on the target system + _opt_sshcopyauth=T + ;; --grmlrepos) # Enable Grml repository _opt_grmlrepos=T ;; @@ -560,6 +572,8 @@ done [ "$_opt_defaultinterfaces" ] && USE_DEFAULT_INTERFACES="true" [ "$_opt_nointerfaces" ] && NOINTERFACES="true" [ "$_opt_nokernel" ] && NOKERNEL="true" +[ "$_opt_sshcopyid" ] && SSHCOPYID="true" +[ "$_opt_sshcopyauth" ] && SSHCOPYAUTH="true" [ "$_opt_bootappend" ] && BOOT_APPEND=$_opt_bootappend [ "$_opt_grub" ] && GRUB=$_opt_grub [ "$_opt_efi" ] && EFI=$_opt_efi @@ -588,6 +602,12 @@ if [ "$_opt_grub" ] && [ "$_opt_vmfile" ] ; then 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." + eend 1 + 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." @@ -621,6 +641,8 @@ fi # }}} # make sure we have what we need {{{ +check4progs "${DEBOOTSTRAP}" || bailout 1 + if [ -n "$VIRTUAL" ] ; then check4progs kpartx parted qemu-img || bailout 1 fi @@ -765,7 +787,7 @@ prompt_for_bootmanager() # ask for Debian release {{{ prompt_for_release() { - [ -n "$RELEASE" ] && DEFAULT_RELEASE="$RELEASE" || DEFAULT_RELEASE='buster' + [ -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 \ @@ -958,7 +980,7 @@ format_efi_partition() { einfo "EFI partition $EFI seems to have a FAT filesystem, not modifying." ; eend 0 else einfo "EFI partition $EFI doesn't seem to be formatted, creating filesystem." - mkfs.fat -F32 -n "EFI System Partition" "$EFI" + mkfs.fat -F32 -n "EFI" "$EFI" RC=$? if [ $RC -eq 0 ] ; then eend 0 @@ -973,14 +995,23 @@ format_efi_partition() { # check for EFI support or try to enable it {{{ efi_support() { - if lsmod | grep -q efivars ; then + 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." ; eend 0 return 0 fi - if modprobe efivars &>/dev/null ; then - einfo "EFI support enabled now." ; eend 0 - return 0 + 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 @@ -1129,6 +1160,12 @@ else 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.' ; eend 1 + bailout 1 +fi # }}} # It is not possible to build amd64 on i686. {{{ @@ -1144,7 +1181,7 @@ 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 stretch or buster." ; eend 1 +Please use specific codenames such as buster or bullseye." ; eend 1 bailout 1 fi # }}} @@ -1487,7 +1524,7 @@ if [[ -z "${GRUB}" ]] || ! dd if="${GRUB}" bs=512 count=1 2>/dev/null | cat -v | if ! chroot "${MNTPOINT}" dpkg --list grub-pc 2>/dev/null | grep -q '^ii' ; then echo "Notice: grub-pc package not present yet, installing it therefore." # shellcheck disable=SC2086 - DEBIAN_FRONTEND=$DEBIAN_FRONTEND chroot "$MNTPOINT" apt-get -y install $DPKG_OPTIONS grub-pc + DEBIAN_FRONTEND=$DEBIAN_FRONTEND chroot "$MNTPOINT" apt-get -y --no-install-recommends install $DPKG_OPTIONS grub-pc fi mkdir -p "${MNTPOINT}/boot/grub" @@ -1505,15 +1542,33 @@ if [[ -z "${GRUB}" ]] || ! dd if="${GRUB}" bs=512 count=1 2>/dev/null | cat -v | ;; esac dd if="${MNTPOINT}/usr/lib/grub/i386-pc/boot.img" of="${ORIG_TARGET}" conv=notrunc bs=440 count=1 - chroot "${MNTPOINT}" grub-mkimage -O i386-pc -p "(hd0,msdos1)/boot/grub" -o /tmp/core.img biosdisk part_msdos ext2 + case "${_opt_filesystem}" in + f2fs) + chroot "${MNTPOINT}" grub-mkimage -O i386-pc -p "(hd0,msdos1)/boot/grub" -o /tmp/core.img biosdisk part_msdos f2fs + ;; + xfs) + chroot "${MNTPOINT}" grub-mkimage -O i386-pc -p "(hd0,msdos1)/boot/grub" -o /tmp/core.img biosdisk part_msdos xfs + ;; + # NOTE - we might need to distinguish between further filesystems + *) + chroot "${MNTPOINT}" grub-mkimage -O i386-pc -p "(hd0,msdos1)/boot/grub" -o /tmp/core.img biosdisk part_msdos ext2 + ;; + esac + dd if="${MNTPOINT}/tmp/core.img" of="${ORIG_TARGET}" conv=notrunc seek=1 rm -f "${MNTPOINT}/tmp/core.img" fi - einfo "Updating grub configuration file." - if [ -n "$BOOT_APPEND" ] ; then - sed -i "/GRUB_CMDLINE_LINUX_DEFAULT/ s#\"\$# ${BOOT_APPEND}\"#" "${MNTPOINT}"/etc/default/grub + # workaround for Debian bug #918590 with lvm + udev: + # WARNING: Device /dev/... not initialized in udev database even after waiting 10000000 microseconds + if [ -d /run/udev ] ; then + einfo "Setting up bind-mount /run/udev" + mkdir -p "${MNTPOINT}"/run/udev + mount --bind /run/udev "${MNTPOINT}"/run/udev + eend $? fi + + einfo "Updating grub configuration file." chroot "${MNTPOINT}" update-grub case "$RELEASE" in @@ -1532,6 +1587,14 @@ fi sed -i "s;root=[^ ]\\+;root=UUID=$TARGET_UUID;" "${MNTPOINT}"/boot/grub/grub.cfg fi + # workaround for Debian bug #918590 with lvm + udev: + # WARNING: Device /dev/... not initialized in udev database even after waiting 10000000 microseconds + if mountpoint "${MNTPOINT}"/run/udev &>/dev/null ; then + einfo "Unmounting bind-mount /run/udev" + umount "${MNTPOINT}"/run/udev + eend $? + fi + umount "${MNTPOINT}"/proc umount "${MNTPOINT}"/sys umount "${MNTPOINT}"/dev/pts @@ -1610,6 +1673,7 @@ preparechroot() { # e.g. not with 4.2.37(1)-release (a.k.a 4.2+dfsg-0.1+deb7u3) of Debian wheezy [ -n "$ARCH" ] && echo "ARCH='$(sed "s,','\\\\'',g" <<<"${ARCH}")'" >> "$CHROOT_VARIABLES" [ -n "$BACKPORTREPOS" ] && echo "BACKPORTREPOS='$(sed "s,','\\\\'',g" <<<"${BACKPORTREPOS}")'" >> "$CHROOT_VARIABLES" + [ -n "$BOOT_APPEND" ] && echo "BOOT_APPEND='$(sed "s,','\\\\'',g" <<<"${BOOT_APPEND}")'" >> "$CHROOT_VARIABLES" [ -n "$CHROOT_SCRIPTS" ] && echo "CHROOT_SCRIPTS='$(sed "s,','\\\\'',g" <<<"${CHROOT_SCRIPTS}")'" >> "$CHROOT_VARIABLES" [ -n "$COMPONENTS" ] && echo "COMPONENTS='$(sed "s,','\\\\'',g" <<<"${COMPONENTS}")'" >> "$CHROOT_VARIABLES" [ -n "$CONFFILES" ] && echo "CONFFILES='$(sed "s,','\\\\'',g" <<<"${CONFFILES}")'" >> "$CHROOT_VARIABLES" @@ -1621,6 +1685,7 @@ preparechroot() { [ -n "$EXTRAPACKAGES" ] && echo "EXTRAPACKAGES='$(sed "s,','\\\\'',g" <<<"${EXTRAPACKAGES}")'" >> "$CHROOT_VARIABLES" [ -n "$EFI" ] && echo "EFI='$(sed "s,','\\\\'',g" <<<"${EFI}")'" >> "$CHROOT_VARIABLES" [ -n "$FALLBACK_MIRROR" ] && echo "FALLBACK_MIRROR='$(sed "s,','\\\\'',g" <<<"${FALLBACK_MIRROR}")'" >> "$CHROOT_VARIABLES" + [ -n "$FILESYSTEM" ] && echo "FILESYSTEM='$(sed "s,','\\\\'',g" <<<"${FILESYSTEM}")'" >> "$CHROOT_VARIABLES" [ -n "$FORCE" ] && echo "FORCE='$(sed "s,','\\\\'',g" <<<"${FORCE}")'" >> "$CHROOT_VARIABLES" [ -n "$GRMLREPOS" ] && echo "GRMLREPOS='$(sed "s,','\\\\'',g" <<<"${GRMLREPOS}")'" >> "$CHROOT_VARIABLES" [ -n "$GRUB" ] && echo "GRUB='$(sed "s,','\\\\'',g" <<<"${GRUB}")'" >> "$CHROOT_VARIABLES" @@ -1725,37 +1790,112 @@ iface eth0 inet dhcp # add dhcp setting for Predictable Network Interface Names if [ -x /bin/udevadm ]; then - for interface in $(udevadm info -e | sed -n -e 's/E: ID_NET_NAME_PATH=\([^$*]\)/\1/p'); do - DEFAULT_INTERFACES="${DEFAULT_INTERFACES} + tmpfile=$(mktemp) + for interface in /sys/class/net/*; do + udevadm info --query=all --path="${interface}" > "${tmpfile}" + # skip virtual devices, like bridges, vboxnet,... + if grep -q 'P: /devices/virtual/net/' "${tmpfile}" ; then + continue + fi + + # iterate over possible naming policies by precedence (see udev/net/link-config.c), + # use and stop on first match to have same behavior as udev's link_config_apply() + for property in ID_NET_NAME_FROM_DATABASE ID_NET_NAME_ONBOARD ID_NET_NAME_SLOT ID_NET_NAME_PATH ID_NET_NAME_MAC ; do + if grep -q "${property}" "${tmpfile}" ; then + interface=$(grep "${property}" "${tmpfile}" | sed -n -e "s/E: ${property}=\([^\$*]\)/\1/p") + DEFAULT_INTERFACES="${DEFAULT_INTERFACES} allow-hotplug ${interface} iface ${interface} inet dhcp " + break + fi + done done + rm -f "${tmpfile}" fi if [ -n "$NOINTERFACES" ] ; then einfo "Not installing /etc/network/interfaces as requested via --nointerfaces option" ; eend 0 elif [ -n "$USE_DEFAULT_INTERFACES" ] ; then einfo "Installing default /etc/network/interfaces as requested via --defaultinterfaces options." + mkdir -p "${MNTPOINT}/etc/network" echo "$DEFAULT_INTERFACES" > "${MNTPOINT}/etc/network/interfaces" eend $? elif [ -n "$VIRTUAL" ] ; then einfo "Setting up Virtual Machine, installing default /etc/network/interfaces" + mkdir -p "${MNTPOINT}/etc/network" echo "$DEFAULT_INTERFACES" > "${MNTPOINT}/etc/network/interfaces" eend $? elif [ -r /etc/network/interfaces ] ; then einfo "Copying /etc/network/interfaces from host to target system" + mkdir -p "${MNTPOINT}/etc/network" cp $VERBOSE /etc/network/interfaces "${MNTPOINT}/etc/network/interfaces" eend $? else ewarn "Couldn't read /etc/network/interfaces, installing default /etc/network/interfaces" + mkdir -p "${MNTPOINT}/etc/network" echo "$DEFAULT_INTERFACES" > "${MNTPOINT}/etc/network/interfaces" eend $? fi # install config file providing some example entries if [ -r /etc/network/interfaces.examples ] && [ ! -r "$MNTPOINT/etc/network/interfaces.examples" ] ; then - cp /etc/network/interfaces.examples "$MNTPOINT/etc/network/interfaces.examples" + mkdir -p "${MNTPOINT}/etc/network" + cp /etc/network/interfaces.examples "$MNTPOINT/etc/network/interfaces.examples" + fi + + if [ -n "${SSHCOPYID}" ] ; then + AUTHORIZED_KEYS_SOURCE=${AUTHORIZED_KEYS_SOURCE:-$HOME/.ssh/authorized_keys} + AUTHORIZED_KEYS_TARGET=${AUTHORIZED_KEYS_TARGET:-$MNTPOINT/root/.ssh/} + if ssh-add -L >/dev/null 2>&1 ; then + einfo "Use locally available public keys to authorise root login on the target system as requested via --sshcopyid option." + mkdir -p "${MNTPOINT}"/root/.ssh + chmod 0700 "${MNTPOINT}"/root/.ssh + if ssh-add -L >> "${MNTPOINT}"/root/.ssh/authorized_keys ; then + eend 0 + else + eerror "Error: executing 'ssh-add -L' failed." + eend 1 + bailout 1 + fi + elif [ -f "$AUTHORIZED_KEYS_SOURCE" ]; then + einfo "copying '$AUTHORIZED_KEYS_SOURCE' to '$AUTHORIZED_KEYS_TARGET' as requested via --sshcopyid option." + mkdir -p "$AUTHORIZED_KEYS_TARGET" + chmod 0700 "$AUTHORIZED_KEYS_TARGET" + if cp "$AUTHORIZED_KEYS_SOURCE" "$AUTHORIZED_KEYS_TARGET" ; then + eend 0 + else + eerror "Error: copying '$AUTHORIZED_KEYS_SOURCE' to '$AUTHORIZED_KEYS_TARGET' failed" + eend 1 + bailout 1 + fi + else + eerror "Error: Could not open a connection to your authentication agent or the agent has no identities." + eend 1 + bailout 1 + fi + fi + + if [ -n "${SSHCOPYAUTH}" ] ; then + AUTHORIZED_KEYS_SOURCE=${AUTHORIZED_KEYS_SOURCE:-${HOME}/.ssh/authorized_keys} + + if ! [ -f "${AUTHORIZED_KEYS_SOURCE}" ]; then + eerror "Error: could not read '${AUTHORIZED_KEYS_SOURCE}' for setting up SSH key login." + eend 1 + bailout 1 + fi + + AUTHORIZED_KEYS_TARGET="${MNTPOINT}/root/.ssh/" + einfo "Copying '${AUTHORIZED_KEYS_SOURCE}' to '${AUTHORIZED_KEYS_TARGET}' as requested via --sshcopyauth option." + mkdir -p "${AUTHORIZED_KEYS_TARGET}" + chmod 0700 "${AUTHORIZED_KEYS_TARGET}" + if cp "${AUTHORIZED_KEYS_SOURCE}" "${AUTHORIZED_KEYS_TARGET}" ; then + eend 0 + else + eerror "Error: copying '${AUTHORIZED_KEYS_SOURCE}' to '${AUTHORIZED_KEYS_TARGET}' failed." + eend 1 + bailout 1 + fi fi if [ -d /run/udev ] ; then