Start Kontakt

Debian Encrypted Partitions with LUKS

Stand: 2020-08-15

Index

Preamble

Main concept found in c't article "Fernverschlüsselt: Verschlüsselte Root-Partition für Linux-Systeme" (c't issue 12/2008, page 188, category "Praxis / Root-Server").
Dropbear InitRD script for Debian 4.0 "Etch" and 5.0 "Lenny" originally from http://gpl.coulmann.de/ssh_luks_unlock.html.
Follow this guide at your own risk.

Goal

Goal is to convert an existing system to have the root and swap partition of Debian encrypted with LUKS.
On power-up/reboot the root partition is unlocked via an SSH session by an administrator and Debian continues to boot normally.
The SSH session and unlock functionality will be provided by the InitRAMFS on boot.
The conversion process is also working on a remote server with SSH access only.

Process overview

First a temporary Mini-Debian is created inside the existing swap partition to have free access onto the root partition.
Then the existing root partition is reduced in size, to generate free space for a temporary partition, which will temporary hold the files of the root partition.
An unencrypted boot partition is needed to hold the InitRAMFS.
If a boot partition is not available or too small (<100MB), then the old root partition is deleted and a new boot plus root partition are created.
The root partition is then encrypted with LUKS and all files are copied back from the temporary exchange. After this the temporary partition is deleted and the root partition is resized to its maximum extend.
To decrypt the root partition via an SSH session the init ramdisk is extended with a DropBear script, which also provides a simple unlock script.
Note that the boot partition has to be (or stay) unencrypted.
After a successful boot with the encrypted root partition the Mini-Debian is removed and an encrypted swap partition is established. The normal init ramdisk is regenerated too, so that kernel and ramdisk updates just work like normal.
A fallback boot option is always during the creation process.
During the setup process Grub's savedefault feature is used to get the system back to it's previous state after another reboot.

Tested with the following Debian releases:

Preparations

A) Planning the new partition scheme

Make up your mind how the new partitioning should look like. This includes partition sizes, positions, mount points and which partitions will be encrypted.
Typical options are separate home (/home) and var (/var) partitions. These can be created after completion of the encrypted root partition. Of course empty space has to be left for them, or handle them when copying data from the temporary file system during the process. Separate partitions for /var, /home, etc. are not part of this guide.
If using MBR partions then use an extended partition to have more than 4 primary partitions.
Additionally re-partioning allows the re-alignment to 1MB for hard disks with physical sectors greater than 512 bytes. Re-aligning existing partitions like /boot are not part of this guide.

If LVM is already used, then thoroughly plan all movements of logical volumes between physical volumes. This scenario is not supported by this guide. An LVM setup can be very complicated (multiple pvs/devs in one vg, multiple vgs on one dev, and normally all with different sizes). Lots of manual steps will be necessary that cannot be explained here.
The main concept is to shrink all filesystems of the logical volumes inside the volume group where the root filesystems resides, then shrink the logical volumes (with some buffer) via lvresize. The swap volume can be disabled and removed (also from /etc/fstab) to get some more free space to work with. After that defrag/rearrange physical volumes via pvdisplay & pvmove before shrinking them (again with some buffer) via pvresize, then shrink the devices of the physical volumes (again with some buffer).
Create a new partition at the end of the drive with roughly 3 GiB for a LVM physical volume to hold the mini Debian system via fdisk/gdisk & pvcreate. Add the physical volume to the existing volume group via vgextend, create a logical volume of 2.5 GiB on the new physical volume. Check it and otherwise pvmove it to the new physical volume.
After Mini-Debian runs shrink all filesystems of the logical volumes on the old physical volume, then defrag/rearrange the old physical volume to finally shrink it and its sub devices.
After that create again a new partition at the end of the drive for a LVM physical volume to hold the logical volumes from the old physical volume via fdisk/gdisk & pvcreate.
Now comes the advantage of LVM: no need to copy the files with cp, just pvmove the logical volumes from the old physical volume to the new temporary one.
Remove the old physical volume via vgreduce & pvremove, create a LUKS volume on its sub devices, create again a physical volume on them, add to the volume group and move logical volumes back again.
Destroy the temporary physical volume and extend the old one as far as possible. Get the old system running, then destroy the Mini-Debian physical volume and extend the old physical volume further.

Take extra caution with the swap partition. The swap partition size is typically 1.3x of the RAM size.
If the machine shall be put to standyby mode S4 (=suspend to disk) then the encryption key for the swap partition has to be static. The swap partition must be able to hold at least the whole RAM, so take planned or possible upcoming RAM enhancements into account.
Otherwise disable resume in GRUB and /etc/initramfs-tools/conf.d/resume, then it is even possible to use a random key for the swap partition.
With a typical LVM on LUKS setup (LUKS+LVM) there are no issues as the swap data itself is not encrypted, just the underlying LVM physical volume.

Note that the keyscript option in /etc/crypttab is not supported with systemd init system which came with Debian 8.0 "Jessie", e.g. for /lib/cryptsetup/scripts/decrypt_* scripts (see Jessie Ugrade Notes 5.6 and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=618862#124). Instead use an explicit key file on the enrypted root partition, e.g. /etc/luks.key created via /lib/cryptsetup/scripts/decrypt_derived md1_crypt >/etc/luks.key, and specify the key file in /etc/crypttab:

md2_crypt UUID=... /etc/luks.key luks

B) Reading and training

Read this guide thoroughly and several times.
Look out for special cases that apply to the actual situation of the target system.

Adopt this guide to the wanted partition scheme and actual devices (/dev/sda or /dev/hda) and create a text file with all necessary commands.
Prepare a Virtual Machine with the current setup of the real target machine, create a snapshot and repeat this process until it is 100% working and documented. Take care about some specialities when using Debian in a Virtual Machine.
On questions checkout the man pages, if still in doubt then search the net, if that fails contact me. Continue to do this on the target system at your own risk.

Notes:
With direct access to the hardware the easiest way to resize, move, delete and create partitions is to use a live boot cd from GParted.
An additional hard disk (e.g. via USB) can be used for the temporary space to avoid extra partioning steps. This allows to directly create the final new partioning scheme without in-between steps.

C) Backup

  1. Do a backup of the root partition of the target system.
  2. Really do a backup of the root partition.
  3. Did you backup the root partition?

Prerequisites

This part will be longer than maybe expected, but a good preparation makes life easier during the process.

A) Special cases

A.1) Special case: Missing swap partition

This is the most critical special case, take care!!!

A.2) Special case: Root partition space (/)

Make sure that the root partition is under 45% used, or otherwise an extra partition is needed to backup the data from the unencrypted root partition and then copy it back to the new encrypted root partition.
df -h /
# example result:
#   Filesystem            Size  Used Avail Use% Mounted on
#   /dev/sda3           140.0G  17G   113G  11% /

A.3) Special case: LVM

If LVM is used, then occupied space (not volume size) in all filesystems of volume group must be under 45%, or otherwise an extra partition is needed to backup the data from the unencrypted root partition and then copy it back to the new encrypted root partition.
lvs --units m
# example result:
#  LV     VG          Attr       LSize     Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
#  rootfs debian-test -wi-ao---- 38144.00m
#  swap_1 debian-test -wi-ao---- 12068.00m
mount | grep -e '^/dev/'
# example result:
#/dev/mapper/debian--test-rootfs on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
df -h /
# example result:
#  Filesystem      Size  Used Avail Use% Mounted on
#  /dev/dm-0        37G  1.1G   34G   3% /

vgs --units m
# example result:
#  VG          #PV #LV #SN Attr   VSize     VFree
#  debian-test   1   2   0 wz--n- 50212.00m    0m
pvs --units m
# example result:
#  PV         VG          Fmt  Attr PSize     PFree
#  /dev/md1   debian-test lvm2 a--  50212.00m    0m

A.4) Special case: Missing boot partition (/boot)

Create during partitioning for new encrypted root partition (after Mini-Debian and copying of the old root partition).

B) lsblk usage

Since Debian 7.0 "Wheezy" with 'lsblk' (from package 'util-linux') you can see the hierarchy of all block devices and their mount points. Fast and convenient way to see software raids, luks partitions and LVM volumes.
On older releases those information have to be collected via several ways, blkid, fdisk/gdisk, etc.

D) fdisk/parted/gdisk usage

E) Root bin folder

Make sure that /root/bin is present and included in the user's path (default profile). If not present, then create and re-login.
[ -d /root/bin ] || { install -v -d /root/bin; echo 'Log out, then back in' ; printf '\a' ; }

echo "${PATH}" | grep -q -F -e '/root/bin' && echo '/root/bin present in PATH' || { echo 'Check that you are root, if so then check .profile, .bash_profile, .bashrc and similar. Maybe adopt/update them from /etc/skel.' ; printf '\a' ; }

F) Bring system up to date

Make sure the target system runs with the latest packages.

DEBVERSION="$( cut -f 1 -d '.' /etc/debian_version )"
echo "Debian version is ${DEBVERSION}"

# check /etc/apt/sources.list and source.list.d/* that all entries are present and complete (e.g. component non-free for firmware)
cat /etc/apt/sources.list /etc/apt/sources.list.d/*

apt-get update

apt-get install debian-archive-keyring ; # especially important for archived releases, e.g. etch, lenny, etc

apt-get update

apt-get safe-upgrade || apt-get upgrade

apt-get dist-upgrade

reboot ; # only necessary if any packages were upgraded

# enable en_US.UTF-8 locale for correct parsing, also most help pages are in English
sed -i -e "s/[[:space:]]*#[[:space:]]*\(en_US\.UTF-8\)/\1/" /etc/locale.gen
locale-gen

G) Determine Debian details

Determine Debian version and release name:
DEBVERSION="$( cut -f 1 -d '.' /etc/debian_version )" ; \
echo "Debian version is ${DEBVERSION}"

[ "${DEBVERSION}" -le 5 ] && {
  pkg='lsb-release'
  apt-get install ${pkg}
}

DEBRELEASE="$( lsb_release -c -s )" ; \
[ -n "${DEBRELEASE}" ] && echo "Debian release is ${DEBRELEASE}" || { echo 'Please set DEBRELEASE manually (e.g. woody, stable, testing, unstable, etc.)' ; printf '\a' ; }

unset DEBLINUX ; \
if [ "${DEBVERSION}" -le 6 ] ; then
  DEBLINUX="linux-image-$( uname -r | sed -e 's#\([^.]*.[^.]*\).*-\([^-]*\)$#\1-\2#' )"
else
  DEBLINUX="linux-image-$( uname -r | grep -o -e '[^-]*$' )"
fi ; \
[ -n "${DEBLINUX}" ] && echo "Debian Linux Image is ${DEBLINUX}" || { echo 'Please set DEBLINUX manually (check dpkg -l | linux-image)' ; printf '\a' ; }

cat > /root/bin/luks_debian.inc << __EOF
echo 'Setting Debian vars...' 1>&2
DEBVERSION='${DEBVERSION}'
DEBRELEASE='${DEBRELEASE}'
DEBLINUX='${DEBLINUX}'
FDISKCPARM='$( [ "${DEBVERSION}" -ge 6 ] && echo '-c' )'
DEBOOTSTRAPOPTS='$( [ "${DEBVERSION}" -ge 5 ] && echo '--components=main,contrib,non-free' )'
CALL_ENV='env LANG=en_US.UTF-8 LANGUAGE=en_US.UTF-8'
__EOF

chmod ug=rw,o= /root/bin/luks_*.inc

H) Install and configure necessary packages

The InitRAMFS tools are necessary to create or update an InitRAMFS.
The small SSH server DropBear allows to log into the system while the InitRAMFS is waiting for the root partition to be unlocked.
Note that DropBear before Debian 5.0 Lenny did not use /dev/urandom, which was an issue when used in an InitRAMFS. So on Debian 4.0 "Etch", 3.1 "Sarge", 3.0 "Woody" or earlier DropBear has to be compiled from modified source.
Busybox provides a small shell environment to run scripts and provide a shell for login.
Cryptsetup provides all tools for managing encrypted partitions and unlocking them from an InitRAMFS.
LVM2 provides all tools for LVM management and MDAdm all tools for software RAID management.
Util-linux provides fdisk for DOS/MBR partioning, while PartEd supports both DOS/MBR and GPT partioning, but PartEd is not recommended (see above). gdisk supports only GPT partitioning.
Psmisc provides some shell tools that are needed for several tasks.
Screen allows to run the shell separately from your direct login, so that a network breakdown will not stop the commands you issued, therefore reducing the risk of creating inconsistent states.
Additionally the tool script from the BSDUtils package logs all the console input and output, so that the complete process is protocolled and helps in solving issues.
Sed is used to change config files via commands to reduce manual errors (typos, etc.).
LSB is used to determine the Debian release.
Last but not least DeBootStrap allows to setup a Debian system in another directory, needed for creating the temporary boot system in the existing swap partition.

Busybox, DropBear and Cryptsetup will trigger an update of the InitRAMFS.
Debian 6.0 "Squeeze" will create new server SSH keys for the InitRAMFS, so the private key of the real system will be on the encrypted root partition only.
Additionally a private and public SSH key is generated for the root user in /etc/dropbear-initramfs (since Debian 9.0 Stretch; previously /etc/initramfs-tools/root/.ssh).
If you want to use this extra key, then copy it to your PC.
Maintain authorized_keys to your liking, e.g. remove the line for that generated root user key and/or add lines for other keys that shall be allowed to access the InitRAMFS.
If authorized_keys is deleted, then updating the InitRAMFS will recreate a new key pair for the root user of the InitRAMFS.
Update the InitRAMFS to include all changes and look for errors.
On Debian 5.0 "Lenny " and earlier we will mimic the same behaviour manually.

# create backup of initramdisk
cp -av /boot/initrd.img-$(uname -r) /boot/initrd.img-$(uname -r).oldroot.org

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

## check /etc/apt/sources.list and source.list.d/* that all entries are present and complete (e.g. component non-free for firmware)
pkg='cryptsetup mdadm lvm2 initramfs-tools os-prober psmisc busybox util-linux parted lsb-base lsb-release screen bsdutils sed debootstrap' ; \
[ "${DEBVERSION}" -ge 5 ] && pkg="${pkg:+${pkg} }dropbear" ; : \ ## before Debian 5.0 "Lenny" DropBear has to be build with a small change ; \
[ "${DEBVERSION}" -ge 7 ] && pkg="${pkg:+${pkg} }gdisk" ; \
echo "${pkg}"

apt-get install ${pkg}

for PACKAGE in ${pkg}
 do
  dpkg-query -s "${PACKAGE}" 1>/dev/null 2>&1
  DOINSTALL=$?
  [ "${DOINSTALL}" -ne 0 ] && break
done ; \
[ "${DOINSTALL}" -ne 0 ] && { echo 'Not all packages got installed. Check APT setup and retry.' ; printf '\a' ; }

## build DropBear for Debian 4.0 or earlier - part 1 "download"
[ "${DEBVERSION}" -le 4 ] && {
  pkg='devscripts build-essential'
  apt-get install ${pkg}
  :
  for PACKAGE in ${pkg}
   do
    dpkg-query -s "${PACKAGE}" 1>/dev/null 2>&1
    DOINSTALL=$?
    [ "${DOINSTALL}" -ne 0 ] && break
  done
  [ "${DOINSTALL}" -ne 0 ] && { echo 'Not all packages got installed. Check APT setup and retry.' ; printf '\a' ; }
}

[ "${DEBVERSION}" -le 4 ] && {
  nano /etc/apt/sources.list
  cd /var/tmp
  apt-get build-dep dropbear
  :
  apt-get source dropbear
  nano /etc/apt/sources.list
}

## build DropBear for Debian 4.0 or earlier - part 2 "build"
[ "${DEBVERSION}" -le 4 ] && {
  cd /var/tmp
  cd dropbear-*/
  grep -n -e '/dev/[u]*random' options.h
: \ ## expected result: ; \
: \ ##  152:/* If you are lacking entropy on the system then using /dev/urandom ; \
: \ ##  157:#define DROPBEAR_RANDOM_DEV "/dev/random" ; \
  sed -i -e 's|#define DROPBEAR_RANDOM_DEV "/dev/random"|#define DROPBEAR_RANDOM_DEV "/dev/urandom"|' options.h
  grep -n -e '/dev/[u]*random' options.h
: \ ## expected result: ; \
: \ ##  152:/* If you are lacking entropy on the system then using /dev/urandom ; \
: \ ##  157:#define DROPBEAR_RANDOM_DEV "/dev/urandom" ; \
  cd ~
}

[ "${DEBVERSION}" -le 4 ] && {
  cd /var/tmp
  cd dropbear-*/
  debuild -us -uc
  cd ~
}

## build DropBear for Debian 4.0 or earlier - part 3 "install"
[ "${DEBVERSION}" -le 4 ] && {
  cd /var/tmp
  dpkg -i /var/tmp/dropbear_*.deb
  cd ~
}

[ "${DEBVERSION}" -le 4 ] && {
  echo 'ATTENTION! Remember these holds when upgrading in the future' ; printf '\a'
  echo "dropbear hold" | dpkg --set-selections
  aptitude hold dropbear
  echo 'ATTENTION! Remember these holds when upgrading in the future' ; printf '\a'
}
Now upload (or copy) files depending on release.
Debian 5.0 and earlier:
Do not forget to check and update IP configuration as necessary in /etc/initramfs-tools/hooks/dropbear (ifconfig) later in this step.
[ "${DEBVERSION}" -le 5 ] && install -v -d /usr/local/share/initramfs-tools/hooks

/usr/local/share/initramfs-tools/hooks/dropbear (v1.0.2 or later, original from http://gpl.coulmann.de/ssh_luks_unlock.html)

/root/cryptroot_remote_fix.debian4.patch
Debian 6.0 and earlier:
The little network script sets the hostname in dhclient.conf, so that when using DHCP the host will be registered with its name and is accessible via DNS. With the above initramfs hook script for DropBear the dhclient.conf is copied to initramfs, so also within the InitRAMFS it will get registered with its hostname.
/etc/network/if-pre-up.d/set-dhclient-hostname
Debian 6.0 to 8.0:
/etc/initramfs-tools/hooks/cryptroot_remote_unlock.sh
/etc/initramfs-tools/scripts/local-bottom/dropbear_kill_clients.sh

/root/cryptroot_remote_fix.debian7.patch
/root/cryptroot_remote_fix.debian8.patch
Debian 6.0 and later (verified up to 9.0):
This little hook sets the hostname in the InitRAMFS, so that when using DHCP the host can be registered with its name and is accessible via DNS. If a static DNS record is used then set the IP configuration in /etc/initramfs-tools/conf.d/network (IP=....), see kernel command line definition for ip=.
/etc/initramfs-tools/conf.d/network
/etc/initramfs-tools/hooks/set_hostname_in_network_config
Then continue on the shell:
which dropbear 1>/dev/null || { echo 'Check that dropbear is installed.' ; printf '\a' ; }

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

if [ "${DEBVERSION}" -le 8 ] ; then
  AUTHKEYDIR='/etc/initramfs-tools/root/.ssh'
else
  AUTHKEYDIR='/etc/dropbear-initramfs'
fi

# add existing SSH public keys for root user to InitRAMFS
[ -d "${AUTHKEYDIR}" ] || install -v -d "${AUTHKEYDIR}" ; \
[ -s /root/.ssh/authorized_keys ] && cat /root/.ssh/authorized_keys > "${AUTHKEYDIR}/authorized_keys"

# mimic Debian 6.0 behaviour for earlier releases
[ "${DEBVERSION}" -le 5 ] && {
  echo 'Creating separate DropBear server keys for initrd, to not expose the real server keys in the unencrypted initrd'
  [ -d /etc/initramfs-tools/etc/dropbear ] || install -v -d /etc/initramfs-tools/etc/dropbear
  [ ! -s /etc/initramfs-tools/etc/dropbear/dropbear_rsa_host_key ] && dropbearkey -t rsa -s 4096 -f /etc/initramfs-tools/etc/dropbear/dropbear_rsa_host_key
  [ ! -s /etc/initramfs-tools/etc/dropbear/dropbear_dss_host_key ] && dropbearkey -t dss -s 1024 -f /etc/initramfs-tools/etc/dropbear/dropbear_dss_host_key
  :
  chmod -R go= /etc/initramfs-tools/root
  [ ! -s "${AUTHKEYDIR}/authorized_keys" ] && {
    echo 'Creating separate dropbear client keys for root in initrd'
    dropbearkey -t rsa -s 4096 -f "${AUTHKEYDIR}/id_rsa.dropbear"
    dropbearkey -y -f "${AUTHKEYDIR}/id_rsa.dropbear" | grep -e '^ssh-rsa ' > "${AUTHKEYDIR}/id_rsa.pub"
    cat "${AUTHKEYDIR}/id_rsa.pub" > "${AUTHKEYDIR}/authorized_keys"
  }
}

# optional: to set/change password of initramfs ssh private key
# Dropbear doesn't support passwords for ssh key files, therefore convert to OpenSSH format, set password and clear/wipe unencrypted Dropbear/OpenSSH key files
[ -s "${AUTHKEYDIR}/id_rsa.dropbear" ] && {
  /usr/lib/dropbear/dropbearconvert dropbear openssh "${AUTHKEYDIR}/id_rsa.dropbear" "${AUTHKEYDIR}/id_rsa"
  ssh-keygen -p -f "${AUTHKEYDIR}/id_rsa" >"${AUTHKEYDIR}/id_rsa.protected" && shred -z -n 0 --remove "${AUTHKEYDIR}/id_rsa"
  shred -z -n 0 --remove "${AUTHKEYDIR}/id_rsa.dropbear"
}

# make scripts executable
if [ "${DEBVERSION}" -le 6 ] ; then
  chmod u=rwx,go=rx /etc/network/if-pre-up.d/set-dhclient-hostname
fi

if [ "${DEBVERSION}" -le 5 ] ; then
  chmod u=rwx,go=rx /usr/local/share/initramfs-tools/hooks/dropbear
  [ -s "/root/cryptroot_remote_fix.debian${DEBVERSION}.patch" ] && {
    cp /usr/share/initramfs-tools/scripts/local-top/cryptroot "/root/cryptroot.debian${DEBVERSION}.org.$(date +%Y%m%d_%H%M%S)"
    patch -d/ -r - -N -p0 -i "/root/cryptroot_remote_fix.debian${DEBVERSION}.patch"
  }
elif [ "${DEBVERSION}" -le 8 ] ; then
  chmod u=rwx,go=rx /etc/initramfs-tools/hooks/cryptroot_remote_unlock.sh
  chmod u=rwx,go=rx /etc/initramfs-tools/scripts/local-bottom/dropbear_kill_clients.sh
  [ -s "/root/cryptroot_remote_fix.debian${DEBVERSION}.patch" ] && {
    cp /usr/share/initramfs-tools/scripts/local-top/cryptroot "/root/cryptroot.debian${DEBVERSION}.org.$(date +%Y%m%d_%H%M%S)"
    patch -d/ -r - -N -p0 -i "/root/cryptroot_remote_fix.debian${DEBVERSION}.patch"
  }
  chmod u=rw,go=r /etc/initramfs-tools/conf.d/network
  chmod u=rwx,go=rx /etc/initramfs-tools/hooks/set_hostname_in_network_config
fi

[ "${DEBVERSION}" -le 5 ] && {
  cp -av /usr/local/share/initramfs-tools/hooks/dropbear /etc/initramfs-tools/hooks/
  chmod u=rwx,go=rx /etc/initramfs-tools/hooks/dropbear
  echo 'DROPBEAR=n' > /etc/initramfs-tools/conf.d/dropbear
  :
: \ ## FIXME: adapt copy root password to InitRAMFS \('CHECK HERE' in line 219\) ; \
: \ ## FIXME: adapt network settings for the system \('CHECK HERE' in line 340\) ; \
: \ ## FIXME: enable strace debugging if wanted \('CHECK HERE' in line 350\) ; \
: \ ## FIXME: disable password logins if wanted \('CHECK HERE' in line 363\) ; \
: \ ## CTRL+- \<line number\> ; \
  nano /etc/initramfs-tools/hooks/dropbear
: \ ## edit ifconfig and route accordingly or use DHCP via dhclient ; \
: \ ##  ifconfig, route, dhclient ; \
: \ ## Example: ; \
: \ ##   ifconfig eth0 10.0.2.15 netmask 255.255.255.0 ; \
: \ ##   route add default gw 10.0.2.2 ; \
}

update-initramfs -u -k all
# if any initrd update fails, just create a new one from scratch
IVERSION="$(uname -r)" ; # FIXME: set to problematic initramfs version
rm -f /boot/initrd.img-${IVERSION} ; update-initramfs -c -k ${IVERSION}

reboot ; # CRITICAL, if boot fails restore backup of initramdisk /boot/initrd.img-$(uname -r).oldroot.org and fix issue

cp -av /boot/initrd.img-$(uname -r) /boot/initrd.img-$(uname -r).oldroot ; \
rm -vf /boot/initrd.img-$(uname -r).oldroot.org

I) Useful scripts

Copy some useful scripts to /root/bin, which are helpful during the process, e.g. preparing chroot.
/root/bin/mount_sys.sh
/root/bin/mount_mini-debian.sh
/root/bin/mount_newroot.sh
/root/bin/mount_oldroot.sh
/root/bin/mount_tempex.sh
/root/bin/umount_sys.sh
/root/bin/umount_mini-debian.sh
/root/bin/umount_newroot.sh
/root/bin/umount_oldroot.sh
/root/bin/umount_tempex.sh
/root/bin/luks_functions_analysis.inc
/root/bin/luks_functions_help.inc
/root/bin/custom_functions.inc
For GRUB 1, Debian 5.0 "Lenny" and earlier:
/root/bin/grub1_mini-debian.sh
For GRUB 2, Debian 6.0 "Squeeze":
/root/bin/grub2_mini-debian.sh
Make them executable:
chmod ug=rwx,o= /root/bin/mount_*.sh ; \
chmod ug=rwx,o= /root/bin/umount_*.sh ; \
chmod ug=rwx,o= /root/bin/grub*_mini-debian.sh ; \
chmod ug=rw,o= /root/bin/luks_*.inc ; \
chmod ug=rw,o= /root/bin/custom_*.inc

J) Determine current partitions

J.1) Check and set size of root file system to hold all data

Re-check that the root partition is still under 45% after installation of the new packages and scripts.
df -BM /
# example result:
#   Filesystem            Size  Used Available Use% Mounted on
#   /dev/sda3            5195M 1099M     3833M  23% /
Set the necessary space to hold all data in MiB, keep a little buffer of at least 100 MB. Remember that ext systems need +5% extra free space. Make sure to stay below 45% of the current partition size and that the size fits the target partioning scheme.
This size is used for the temporary exchange storage to hold all the data, and for the newly created root partition. Additionally needed space for each administration level below the file system will be added by the help functions.
OLDROOTSIZEMIN=5000 ; # FIXME: set to correct value in MiB, see info above

J.2) Determine the root partition

Determine the current root partition: (there can be only one, like /dev/sda2)
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

OLDROOTMOUNT="$( mount | grep -F -e ' / ' | cut -d' ' -f1 )" ; \
echo "count is $( echo "${OLDROOTMOUNT}" | wc -w ): ${OLDROOTMOUNT}"
# FIXME: correct if necessary

determine_subdevs OLDROOT "${OLDROOTMOUNT}" "${OLDROOTSIZEMIN}" > /root/bin/luks_OLDROOT.inc ; \
chmod ug=rw,o= /root/bin/luks_*.inc

# check if already encrypted
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

OLDROOTCHECK="$( print_subdevs_value OLDROOT 'TYPE' 'luks' )" ; \
[ -n "${OLDROOTCHECK}" ] && {
  printf '\a'
  echo "WARNING! ROOT file system is already encrypted via ${OLDROOTCHECK}."
  if [ "${DEBVERSION}" -le 5 ] ; then
    echo 'To enable remote SSH unlock just enable DropBear in /etc/initramfs-tools/conf.d/dropbear.'
    echo 'Then update InitRAMFS.'
    echo '  rm -vf /etc/initramfs-tools/conf.d/dropbear'
    echo '  update-initramfs -u -k all'
    echo '  # if any initrd update fails, just create a new one from scratch'
    echo '   IVERSION="$(uname -r)" ; # FIXME: set to problematic initramfs version'
    echo '   rm -f /boot/initrd.img-${IVERSION} ; update-initramfs -c -k ${IVERSION}'
    echo '  #'
  else
    echo 'Remote SSH unlock should be now enabled.'
  fi
  echo '  reboot'
  echo ''
  echo 'If the file system setup will be rearranged, then this scenario is not supported by this guide.'
  echo 'Thoroughly plan all changes and movements of the devices.'
  echo 'Lots of manual steps will be necessary that cannot be explained here.'
  echo 'Good luck!'
  printf '\a'
} ; \
unset OLDROOTCHECK

J.3) Determine the boot partition

Determine the current boot partition: (there can be only one, like /dev/sda1)
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

OLDBOOTMOUNT="$( mount | grep -F -e ' /boot ' | cut -d' ' -f1 )" ; \
echo "count is $( echo "${OLDBOOTMOUNT}" | wc -w ): ${OLDBOOTMOUNT}"
# FIXME: correct if necessary

determine_subdevs OLDBOOT "${OLDBOOTMOUNT}" > /root/bin/luks_OLDBOOT.inc ; \
chmod ug=rw,o= /root/bin/luks_*.inc

J.4) Determine the swap partition

Determine the current swap partition (type 82/8200) for the Mini-Debian: (there can be only one, like /dev/sda3 - ok, there can be more, then just edit OLDSWAP to your liking)
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

OLDSWAPMOUNT="$( swapon -s | grep -F -e 'partition' | cut -d' ' -f1 )" ; \
echo "count is $( echo "${OLDSWAPMOUNT}" | wc -w ): ${OLDSWAPMOUNT}"
# FIXME: correct if necessary

OLDSWAPSIZEMIN="$(( $( swapon -s | grep -e "${OLDSWAPMOUNT}" | sed -e 's#[[:space:]]\+# #g' | cut -d' ' -f3 ) / 1024 ))" ; \
echo "size is ${OLDSWAPSIZEMIN}"
# FIXME: correct if necessary

determine_subdevs OLDSWAP "${OLDSWAPMOUNT}" "${OLDSWAPSIZEMIN}" > /root/bin/luks_OLDSWAP.inc ; \
chmod ug=rw,o= /root/bin/luks_*.inc

K) Determine GRUB details

Determine GRUB version and its root partition:
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

GRUBVERSION="$( grub-install --version | sed -n -e 's#[^(]*[(]*[^0-9]*\([0-9]*\).*#\1#p' )" ; \
[ "${GRUBVERSION}" -eq 0 ] && GRUBRELEASE=1 || GRUBRELEASE=2 ; \
echo "GRUB version ${GRUBVERSION}.x is release ${GRUBRELEASE}"

OLDGRUB="$( [ -n "${OLDBOOT}" ] && echo 'OLDBOOT' || echo 'OLDROOT' )"

unset OLDGRUBNOWRITE OLDGRUBNOBOOT ; \
OLDGRUBCHECK="$( print_subdevs_value "${OLDGRUB}" 'TYPE' 'mdadm|lvm' )" ; \
[ -n "${OLDGRUBCHECK}" ] && {
  if [ "${GRUBRELEASE}" -eq 1 ] ; then
    for TYPE in ${OLDGRUBCHECK} ; do
      case "${TYPE}" in
       (mdadm) TYPE="$( print_subdevs_value "${OLDGRUB}" 'RLEVEL' 'mdadm' )"
               if [ "${TYPE}" != 'raid1' ] ; then
                 OLDGRUBNOWRITE="${OLDGRUBNOWRITE:+${OLDGRUBNOWRITE}, or }non-level 1 mdadm raid"
                 OLDGRUBNOBOOT="${OLDGRUBNOBOOT:+${OLDGRUBNOBOOT}, or }non-level 1 mdadm raid"
               else
                 TYPE="$( print_subdevs_value "${OLDGRUB}" 'METADATA' 'mdadm' )"
                 [ "${TYPE}" = '0.90' -o "${TYPE}" = '1.0' ] && {
                   OLDGRUBNOBOOT="${OLDGRUBNOBOOT:+${OLDGRUBNOBOOT}, or }level 1 mdadm raid with super block of version ${TYPE} which is located at the end of its subdevices"
                 }
               fi
               ;;
       (lvm) OLDGRUBNOWRITE="${OLDGRUBNOWRITE:+${OLDGRUBNOWRITE}, or }lvm volume"
             OLDGRUBNOBOOT="${OLDGRUBNOBOOT:+${OLDGRUBNOBOOT}, or }lvm volume"
             ;;
      esac
    done
    unset TYPE
  elif [ "${GRUBRELEASE}" -ge 2 ] ; then
    OLDGRUBNOWRITE="${OLDGRUBNOWRITE:+${OLDGRUBNOWRITE}, or }those devices"
  fi
}

OLDGRUBROOTDEVS="$( print_subdevs_value "${OLDGRUB}" SUBDEVS 'mbr|gpt' )" ; \
echo "GRUB is (or should be) installed on ${OLDGRUBROOTDEVS}"
Create again a simple script to keep the determined details:
cat > /root/bin/luks_OLDGRUB.inc << __EOF
echo 'Setting OLDGRUB vars...' 1>&2
GRUBVERSION='${GRUBVERSION}'
GRUBRELEASE='${GRUBRELEASE}'
OLDGRUBROOTDEVS='${OLDGRUBROOTDEVS}'
OLDGRUB='${OLDGRUB}'
OLDGRUBCHECK='${OLDGRUBCHECK}'
OLDGRUBNOWRITE='${OLDGRUBNOWRITE}'
OLDGRUBNOBOOT='${OLDGRUBNOBOOT}'
__EOF
Determine GRUB 1 default, fallback and saved value: (there can be only one, like 0 - ok, there can be more, then just edit var to the last value)
unset OLDGRUB1DEFAULT OLDGRUB1FALLBACK OLDGRUB1SAVED ; \
[ "${GRUBRELEASE}" -eq 1 ] && {
  OLDGRUB1DEFAULT="$( sed -n -e 's#^[[:space:]]*default[[:space:]]\+\([^[:space:]]*\).*#\1#p' /boot/grub/menu.lst )"
  echo "count default is $( echo "${OLDGRUB1DEFAULT}" | wc -w ): ${OLDGRUB1DEFAULT}"
  OLDGRUB1FALLBACK="$( sed -n -e 's#^[[:space:]]*fallback[[:space:]]\+\([^[:space:]]*\).*#\1#p' /boot/grub/menu.lst )"
  echo "count fallback is $( echo "${OLDGRUB1FALLBACK}" | wc -w ): ${OLDGRUB1FALLBACK}"
  OLDGRUB1SAVED="$( head -n 1 /boot/grub/default )"
  echo "count saved default is $( echo "${OLDGRUB1SAVED}" | wc -l ): ${OLDGRUB1SAVED}"
  [ "${OLDGRUB1DEFAULT}" = 'saved' -a "${OLDGRUB1SAVED}" = 'default' ] && { echo 'ERROR: GRUB 1 default is set to "saved" and saved value is "default"' ; printf '\a' ; }
}

[ "${GRUBRELEASE}" -eq 1 ] && {
  cat > /root/bin/luks_OLDGRUB1.inc << __EOF
echo 'Setting OLDGRUB1 vars...' 1>&2
OLDGRUB1DEV='$( sed -n -e '/^### BEGIN AUTOMAGIC KERNELS LIST/,/^### END DEBIAN AUTOMAGIC KERNELS LIST/ { /^[[:space:]]*root[[:space:]]\+/ { s#^[[:space:]]*root[[:space:]]\+(\([^,)]*\).*#\1#p ; q ; } ; }' /boot/grub/menu.lst )'
OLDGRUB1PART='$( sed -n -e '/^### BEGIN AUTOMAGIC KERNELS LIST/,/^### END DEBIAN AUTOMAGIC KERNELS LIST/ { /^[[:space:]]*root[[:space:]]\+/ { s#^[[:space:]]*root[[:space:]]\+([^,]*,\([^)]*\).*#\1#p ; q ; } ; }' /boot/grub/menu.lst )'
OLDGRUB1DEFAULT='${OLDGRUB1DEFAULT}'
OLDGRUB1FALLBACK='${OLDGRUB1FALLBACK}'
OLDGRUB1SAVED='${OLDGRUB1SAVED}'
OLDGRUB1DEFAULTNUM='$( [ "${OLDGRUB1DEFAULT}" != 'saved' ] && echo "${OLDGRUB1DEFAULT}" || echo "${OLDGRUB1SAVED}" )'
OLDGRUB1FEASC='$(( $( sed -n -e '/^[[:space:]]*title[[:space:]]\+/p' -e '/^# Put static boot stanzas before and\/or after AUTOMAGIC KERNEL LIST/q' /boot/grub/menu.lst | wc -l ) ))'  # First entry *after* STATIC BOOT COMMENT
OLDGRUB1FEAL='$(( $( sed -n -e '/^[[:space:]]*title[[:space:]]\+/p' -e '/^### BEGIN AUTOMAGIC KERNELS LIST/q' /boot/grub/menu.lst | wc -l ) ))'  # First entry of AUTOMAGIC LIST
OLDGRUB1FEAAL='$(( $( sed -n -e '/^[[:space:]]*title[[:space:]]\+/p' -e '/^### END DEBIAN AUTOMAGIC KERNELS LIST/q' /boot/grub/menu.lst | wc -l ) ))'  # First entry *after* AUTOMAGIC LIST
__EOF
}

[ "${GRUBRELEASE}" -eq 1 ] && {
  for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done
  :
  [ "${OLDGRUB1DEFAULT}" = 'saved' -a "${OLDGRUB1SAVED}" = 'default' ] && { echo 'ERROR: GRUB 1 default is set to "saved" and saved value is "default"' ; printf '\a' ; }
  MINIOLDGRUB1DEFAULT="${OLDGRUB1DEFAULTNUM}"
  [ "${MINIOLDGRUB1DEFAULT}" -ge "${OLDGRUB1FEASC}" ] && MINIOLDGRUB1DEFAULT="$(( ${MINIOLDGRUB1DEFAULT} + 1 ))"
  MINIOLDGRUB1FALLBACK="${OLDGRUB1FALLBACK}"
  [ -n "${MINIOLDGRUB1FALLBACK}" ] && [ "${MINIOLDGRUB1FALLBACK}" -ge "${OLDGRUB1FEASC}" ] && MINIOLDGRUB1FALLBACK="$(( ${MINIOLDGRUB1FALLBACK} + 1 ))"
  :
  cat > /root/bin/luks_MINIDEB_grub1.inc << __EOF
echo 'Setting MINIGRUB1 vars...' 1>&2
MINIOLDGRUB1DEFAULT='${MINIOLDGRUB1DEFAULT}'
MINIOLDGRUB1FALLBACK='${MINIOLDGRUB1FALLBACK}'
MINIGRUB1ENTRY='${OLDGRUB1FEASC}'
MINIGRUB1FALLBACK='$( echo "${MINIOLDGRUB1DEFAULT}${MINIOLDGRUB1FALLBACK:+ ${MINIOLDGRUB1FALLBACK}}" )'
__EOF
}

chmod ug=rw,o= /root/bin/luks_*.inc

L) Final prerequisites checks

Check for any special cases that should be known in advanced, which can cause critical issues (e.g. inaccessability of machine).
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

check_fs_subdevs OLDROOT '' '_1'

OLDROOTCHECK="$( print_subdevs_value OLDROOT 'TYPE' 'lvm' )" ; \
[ -n "${OLDROOTCHECK}" ] && {
  printf '\a'
  echo "WARNING! ROOT is installed on block devices that use lvm."
  echo 'An LVM setup can be very complicated (multiple devs in one vg, multiple vgs on one dev, and normally all with different sizes).'
  echo 'This scenario is not supported by this guide.'
  echo 'Thoroughly plan all movements of logical volumes between physical volumes.'
  echo 'Lots of manual steps will be necessary that cannot be explained here.'
  echo 'Good luck!'
  printf '\a'
} ; \
unset OLDROOTCHECK

[ -n "${OLDGRUBNOBOOT}" -o -n "${OLDGRUBNOWRITE}" ] && {
  LIVECD=0
  printf '\a'
  echo "WARNING! GRUB is installed on block devices that use ${OLDGRUBCHECK}."
  :
  [ -n "${OLDGRUBNOBOOT}" ] && {
    echo "GRUB may not be able to boot from ${OLDGRUBNOBOOT}."
    LIVECD=1
  }
  :
  [ -n "${OLDGRUBNOWRITE}" ] && {
    echo "GRUB is not able to change variables during the boot phase on ${OLDGRUBNOWRITE}."
    if [ "${GRUBRELEASE}" -eq 1 ] ; then
      echo 'Therefore the GRUB command "savedefault" will not work.'
    elif [ "${GRUBRELEASE}" -ge 2 ] ; then
      echo 'Therefore the Debian setting GRUB_SAVEDEFAULT and GRUB command "save_env" will not work.'
    fi
    LIVECD=1
  }
  :
  [ "${LIVECD}" -eq 1 ] && {
    echo 'If anything goes wrong in steps 2 and 4, then access to the machine via a live CD is needed.'
    echo 'This will allow to mount the root and boot partition, chroot into the system and fix the GRUB environment and/or boot partition.'
    echo 'TEST NOW!'
  }
  :
  printf '\a'
  unset LIVECD
}

[ -z "${OLDSWAP}" ] && {
  printf '\a'
  echo 'WARNING! No swap partition named to hold temporary Mini-Debian.'
  echo 'Please shrink your root partition first to make place for Mini-Debian, see the following steps.'
  printf '\a'
}

1.) Create Mini-Debian in swap partition

ATTENTION!!! Adopt the following tasks to the wanted target partition scheme, which was planned during the preparation phase.

1a) Prepare partition for Mini-Debian

1a.1) Special case: Direct hardware access

If you have direct access to the system use a GParted Live CD to resize and rearrange the partitions. When LVM is used, then shrink all logical volumes and physical volumes before resizing the partitions.

1a.2) Special case: No swap partition exists

Due to missing space for the Mini-Debian the root partition has to be resized in advance. Normally this is done with the Mini-Debian in step 3a.
Use a live CD with parted/GParted to resize it (e.g. PartedMagic allows to SSH into the live system, PM asks for tiny fee that is donated to the included open source projects, last non-free release was 2013_08_01; or GParted directly). For more details see step 3a. When LVM is used, then shrink all logical volumes and physical volumes before resizing the partitions.

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
echo "${OLDROOTMOUNT}" ; printf '\a' ; # note down the value

# boot from live system

# mount old root within live system (maybe necessary several times during shrink)
OLDROOTMOUNT='<OLDROOTMOUNT>' ; #e.g. mount /dev/sda1 /mnt/oldroot

[ -d /mnt/oldroot ] || install -v -d /mnt/oldroot ; \
mount "${OLDROOTMOUNT}" /mnt/oldroot ; \
for SRC in /mnt/oldroot/root/bin/luks_*.inc ; do . "${SRC}" ; done

umount /mnt/oldroot

OLDROOTCHECK="$( print_subdevs_value OLDROOT 'TYPE' 'lvm' )" ; \
[ -n "${OLDROOTCHECK}" ] && {
  printf '\a'
: \ ## check that sizes are correct when lvm is used ; \
  nano /root/bin/luks_OLDROOT.inc
  for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done
  echo "WARNING! ROOT is installed on block devices that use lvm."
  echo 'An LVM setup can be very complicated (multiple devs in one vg, multiple vgs on one dev, and normally all with different sizes).'
  echo 'This scenario is not supported by this guide.'
  echo 'Thoroughly plan all movements of logical volumes between physical volumes.'
  echo 'Lots of manual steps will be necessary that cannot be explained here.'
  echo 'Maybe looking at shrink_fs_subdevs function helps.'
  echo 'Good luck!'
  printf '\a'
} ; \
unset OLDROOTCHECK

start_fs_subdevs OLDROOT

check_fs_subdevs OLDROOT ; # TAKES TIME!!!

shrink_fs_subdevs OLDROOT

reboot ; # normally necessary as `blockdev --rereadpt` mostly fails due to being busy

# mount old root within live system (once again)
OLDROOTMOUNT='<OLDROOTMOUNT>' ; #e.g. mount /dev/sda1 /mnt/oldroot

[ -d /mnt/oldroot ] || install -v -d /mnt/oldroot ; \
mount "${OLDROOTMOUNT}" /mnt/oldroot ; \
for SRC in /mnt/oldroot/root/bin/luks_*.inc ; do . "${SRC}" ; done

umount /mnt/oldroot

shrink_fs_subdevs OLDROOT

start_fs_subdevs OLDROOT

check_fs_subdevs OLDROOT '_1' ; # TAKES TIME!!!

reboot ; # to normal system again

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

# Mini-Debian until 9.0 does not need more than 2.0G
show_temp_suggestions OLDROOT MINIDEB 7 2000 | sed -e 's#storage#mini-debian#g' ${OLDROOT_1VG:+-e "s#${OLDROOT_1VG}#minideb#g"}
# create Mini-Debian device(s) as suggested without file system, then set MINIDEB variables

# Save vars until next step
cat > /root/bin/luks_MINIDEB.inc << __EOF
echo 'Setting MINIDEB vars...' 1>&2
MINIDEB='${MINIDEB}'
MINIDEB_1TYPE='${MINIDEB_1TYPE}'
MINIDEB_1SUBDEVS='${MINIDEB_1SUBDEVS}'
__EOF

1a.3) Normal case: Swap partition exists

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -z "${OLDSWAP}" ] && { echo 'Please shrink your root partition first to make place for Mini-Debian' ; printf '\a' ; }

# Check what swap partition(s) are used
swapon -s

# Disable swap partition and check that is not used anymore
swapoff "${OLDSWAP_1}" ; \
swapon -s

# Disable old swap in /etc/fstab, necessary to avoid being changed to swap partition again
sed -i -e "s#^[[:space:]]*\(${OLDSWAP}\|${OLDSWAPMOUNT}\|UUID=${OLDSWAPUUID}\)\([[:space:]]\+\|$\)#\#\1\2#" /etc/fstab ; \
cat /etc/fstab

remove_fs_subdevs OLDSWAP
# reduce device(s) as suggested, may need several separate steps to process all sub devices

# Mini-Debian until 9.0 does not need more than 2.0G
show_temp_suggestions OLDSWAP MINIDEB 7 2000 | sed -e 's#storage#mini-debian#g' ${OLDSWAP_1VG:+-e "s#${OLDSWAP_1VG}#minideb#g"}
# create Mini-Debian device(s) as suggested without file system, then set MINIDEB variables

# Save vars until next step
cat > /root/bin/luks_MINIDEB.inc << __EOF
echo 'Setting MINIDEB vars...' 1>&2
MINIDEB='${MINIDEB}'
MINIDEBSIZEMIN='${MINIDEBSIZEMIN}'
MINIDEB_1='${MINIDEB_1}'
MINIDEB_1TYPE='${MINIDEB_1TYPE}'
MINIDEB_1SUBDEVS='${MINIDEB_1SUBDEVS}'
__EOF

1b) Create file system on Mini-Debian partition

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

case "${MINIDEB_1TYPE}" in
  (mbr) fdisk -u ${FDISKCPARM} -l ${MINIDEB_1SUBDEVS} ;;
  (gpt) gdisk -l ${MINIDEB_1SUBDEVS} ;;
  (mdadm) mdadm --detail "${MINIDEB_1}" ;;
  (luks) cryptsetup status "${MINIDEB_1}" ;;
  (lvm) lvs --units m "${MINIDEB_1}" ;;
  (*) echo "ATTENTION: mini-debian via ${MINIDEB_1TYPE}, please handle accordingly" ; printf '\a' ;;
esac ; \
echo "mini-debian on ${MINIDEB} via ${MINIDEB_1TYPE}"

mkfs.${OLDROOTTYPE} "${MINIDEB_1}" ; printf '\a' ; # TAKES TIME!!!

determine_subdevs MINIDEB "${MINIDEB}" "${MINIDEBSIZEMIN}" 'X' > /root/bin/luks_MINIDEB.inc ; \
chmod ug=rw,o= /root/bin/luks_*.inc

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

wait_fs_subdevs MINIDEB ; # TAKES TIME!!!

1c) Install Mini-Debian via debootstrap

# maybe do this step in screen, to avoid issues during debootstrap download and/or install
screen -h 9999 ; # to get back into the session call 'screen -r', e.g. after a network interruption; access scrollback buffer in copy mode via Ctrl+a then ESC scroll through it with page up/down and or j/k (vi style)

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -d /mnt/mini ] || { install -v -d /mnt/mini ; } ; \
start_fs_subdevs MINIDEB ; \
mount "${MINIDEBMOUNT}" /mnt/mini/

# packages on installer dvd #1 and installed via debootstrap
pkg='cryptsetup,mdadm,lvm2,initramfs-tools,psmisc,busybox,util-linux,parted,locales,lsb-base,lsb-release,screen,bsdutils,sed,openssh-server,apt,apt-listchanges,less,man-db' ; \
[ "${DEBVERSION}" -le 5 ] && pkg="${pkg:+${pkg},}grub,console-data" ; : \ ## changed name in Debian 6.0 "Squeeze" ; \
[ "${DEBVERSION}" -ge 6 ] && pkg="${pkg:+${pkg},}grub-pc,acpi,acpid,acpi-support-base,os-prober" ; : \ ## acpi causes hang during debootstrap on Debian 4.0 "Etch" and 5.0 "Lenny" ; \
[ "${DEBVERSION}" -ge 7 ] && pkg="${pkg:+${pkg},}console-setup,kbd" ; : \ ## xkb-data causes failure during debootstrap on Debian 6.0 "Squeeze" ; \
echo "${pkg}"

# packages on installer dvd #1, but separately installed via apt (e.g. kernel package)
extrapkg="${DEBLINUX}" ; \
[ "${DEBVERSION}" -eq 6 ] && extrapkg="${extrapkg:+${extrapkg},}console-setup,kbd" ; : \ ## xkb-data causes failure during debootstrap on Debian 6.0 "Squeeze" ; \
echo "${extrapkg}"

# packages not on installer dvd #1 and/or non-free
unset pkgnf ; \
[ "${DEBVERSION}" -eq 5 ] && pkgnf="${pkgnf:+${pkgnf},}os-prober" ; : \ ## Debian 4.0 has issues with os-prober via debootstrap ; \
[ "${DEBVERSION}" -ge 5 ] && pkgnf="${pkgnf:+${pkgnf},}dropbear" ; : \ ## not the build we need on Debian 4.0 "Etch" and also causes hang during debootstrap ; \
[ "${DEBVERSION}" -ge 7 ] && pkgnf="${pkgnf:+${pkgnf},}gdisk" ; \
echo "${pkgnf}"

# packages not on installer dvd #1 and/or non-free, but separately installed (e.g. firmware)
unset extrapkgnf ; \
[ "${DEBVERSION}" -ge 6 ] && extrapkgnf="${extrapkgnf:+${extrapkgnf},}firmware-linux" ; : \ ## get all firmwares ; \
echo "${extrapkgnf}"

# download all Debian packages first, so that following installation does not fail through download issues

### Optional BEGIN: "download" from latest installer DVD to reduce network traffic
url='file:///media/cdrom/debian' ; \
DEBOOTSTRAPEXTRAOPTS="$( [ "${DEBVERSION}" -ge 7 ] && echo '--no-check-gpg' )"

mount -t auto /dev/sr0 /media/cdrom ; # FIXME: substitute cd/dvd device, e.g. /dev/hdc for IDE on Debian 4.0

debootstrap --download-only --include=${pkg}${extrapkg:+,${extrapkg}} ${DEBOOTSTRAPEXTRAOPTS} ${DEBOOTSTRAPOPTS} ${DEBRELEASE} /mnt/mini ${url} ; printf '\a'
### Optional END

# download non-free stuff and latest versions of all packages
# another way to reduce network traffic is to set up a local server via apt-proxy
grep -e '^[[:space:]]*deb[[:space:]]\+' /etc/apt/sources.list ; \
grep -R -i -e 'Proxy' /etc/apt/

# change url to main mirror from /etc/apt/sources.list (e.g. http://archive.debian.org/debian/ for archived releases like 4.0 "Etch", 5.0 "Lenny", 6.0 "Squeeze")
url='http://<proxy>:<port>/ftp.debian.org/debian/' ; # e.g. url='http://192.168.250.1:3142/ftp.debian.org/debian/'
url='http://ftp.debian.org/debian/'

unset DEBOOTSTRAPEXTRAOPTS

debootstrap --download-only --include=${pkg}${pkgnf:+,${pkgnf}}${extrapkg:+,${extrapkg}}${extrapkgnf:+,${extrapkgnf}} ${DEBOOTSTRAPEXTRAOPTS} ${DEBOOTSTRAPOPTS} ${DEBRELEASE} /mnt/mini ${url} ; printf '\a'
# TAKES TIME!!!
# CHECK LOG!!! On warnings(!) and errors just re-try, e.g. on retrieving warnings

# after all packages are downloaded, the Mini-Debian can be installed via debootstrap
debootstrap --include=${pkg}${pkgnf:+,${pkgnf}} ${DEBOOTSTRAPEXTRAOPTS} ${DEBOOTSTRAPOPTS} ${DEBRELEASE} /mnt/mini ${url} ; printf '\a'
# TAKES TIME!!!
# CHECK LOG!!! On warnings(!) and errors just re-try and/or try to fix problems
# (?) "Failure while installing base package":
# (?) mount_sys.sh /mnt/mini
# (?) chroot /mnt/mini
# (?) unset LANG
# (?) dpkg --configure -a
# (?) dpkg-reconfigure sysvinit

umount /media/cdrom*

# if done in screen, then exit
exit

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

start_fs_subdevs MINIDEB ; \
mount "${MINIDEBMOUNT}" /mnt/mini/

# prepare Mini-Debian as far as possible
echo 'Mini-Debian' > /mnt/mini/mini-debian ; \
cp -a /etc/network/interfaces /mnt/mini/etc/network/ ; \
[ "${DEBVERSION}" -le 6 ] && cp -a /etc/network/if-pre-up.d/set-dhclient-hostname /mnt/mini/etc/network/if-pre-up.d/ ; \
cp -a /etc/hosts /etc/hostname /etc/locale.gen /etc/timezone /etc/localtime /mnt/mini/etc/ ; \
if [ -h /etc/resolv.conf ] ; then cp -a "$(readlink /etc/resolv.conf)" /mnt/mini/etc/ ; else cp -a /etc/resolv.conf /mnt/mini/etc/ ; fi ; \
cp -a /etc/default/keyboard /etc/default/console-setup /etc/default/locale /etc/default/mdadm /etc/default/cryptdisks /mnt/mini/etc/default/ ; \
cp -a /etc/ssh/ /mnt/mini/etc/ ; \
cp -a /etc/mdadm/ /mnt/mini/etc/ ; \
cp -a /etc/crypttab /mnt/mini/etc/ ; \
[ -d /mnt/mini/root/bin ] || install -v -d /mnt/mini/root/bin ; \
cp -a /root/bin/grub*.sh /mnt/mini/root/bin/ ; \
cp -a /root/bin/luks_*.inc /mnt/mini/root/bin/ ; \
cp -a /root/bin/custom_*.inc /mnt/mini/root/bin/ ; \
cp -a /root/bin/mount_*.sh /mnt/mini/root/bin/ ; \
cp -a /root/bin/umount_*.sh /mnt/mini/root/bin/ ; \
cp -av /etc/profile.d/ /mnt/mini/etc/ ; \
cp -a /root/.profile /root/.bash_profile /root/.bashrc /mnt/mini/root/ ; \
cp -av /root/.ssh/ /mnt/mini/root/

# if root login via SSH is forbidden, then copy the necessary users and setup su/sudo too (su/sudo is up to you)
user='<USERNAME>' ; \
[ -d "/mnt/mini/home/${user}" ] || install -v -d "/mnt/mini/home/${user}" ; \
cp -a "/home/${user}/.profile" "/home/${user}/.bashrc" "/mnt/mini/home/${user}/" ; \
cp -av "/home/${user}/.ssh/" "/mnt/mini/home/${user}/" ; \
grep -q -e "^${user}:" /mnt/mini/etc/passwd || grep -e "^${user}:" /etc/passwd >> /mnt/mini/etc/passwd ; \
grep -q -e "^${user}:" /mnt/mini/etc/shadow || grep -e "^${user}:" /etc/shadow >> /mnt/mini/etc/shadow ; \
grep -q -e "^${user}:" /mnt/mini/etc/group || grep -e "^${user}:" /etc/group >> /mnt/mini/etc/group

cp -a /etc/fstab /mnt/mini/etc/ ; \
sed -i -e "s#UUID=${OLDROOTUUID}\([[:space:]]\+\|$\)#UUID=${MINIDEBUUID}\1#" -e "s#\(${OLDROOT}\|${OLDROOTMOUNT}\)\([[:space:]]\+\|$\)#${MINIDEBMOUNT}\2#" /mnt/mini/etc/fstab ; \
cat /mnt/mini/etc/fstab

[ -d /mnt/mini/media/cdrom0 ] || install -v -d /mnt/mini/media/cdrom0 ; \
ln -s cdrom0 /mnt/mini/media/cdrom ; \
[ "${DEBVERSION}" -le 5 ] && {
  ln -s media/cdrom /mnt/mini/cdrom
}

echo 'Mini-Debian Boot' > /mnt/mini/boot/mini-debian

# copy APT configuration and cdrom related files
cp -av /etc/apt/ /mnt/mini/etc/ ; \
cp -av /var/lib/apt/cdrom* /mnt/mini/var/lib/apt/ ; \
cp -av /var/lib/apt/lists/. /mnt/mini/var/lib/apt/lists/

# copy INITRAMFS/DROPBEAR configuration and related files
[ "${DEBVERSION}" -le 4 ] && {
  cp -av /var/tmp/dropbear_*.deb /mnt/mini/var/tmp/
}

cp -av /etc/initramfs-tools/ /mnt/mini/etc/ ; \
if [ "${DEBVERSION}" -le 5 ] ; then
  [ -d /mnt/mini/usr/local/share/initramfs-tools/hooks ] || install -v -d /mnt/mini/usr/local/share/initramfs-tools/hooks
  cp -av /usr/local/share/initramfs-tools/hooks/dropbear /mnt/mini/usr/local/share/initramfs-tools/hooks/
  if [ "${DEBVERSION}" -le 4 ] ; then
    cp -av /usr/share/initramfs-tools/scripts/local-top/cryptroot /mnt/mini/usr/share/initramfs-tools/scripts/local-top/
  fi
fi

cp -av /etc/dropbear/ /mnt/mini/etc/ ; \
[ -d /etc/dropbear-initramfs ] && cp -av /etc/dropbear-initramfs/ /mnt/mini/etc/
Check if you need other files in the Mini-Debian and copy them accordingly.

1d) Chroot into Mini-Debian and finalize initialisation

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

umount /media/cdrom*

start_fs_subdevs MINIDEB ; \
mount_mini-debian.sh noboot

chroot /mnt/mini

cd ~

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

if [ "${DEBVERSION}" -le 6 ] ; then
  rm -f /etc/mtab
  mount -a -f ; mount -a -f ; # to re-create /etc/mtab, important to install kernel/initrd
else
  [ ! -e /etc/mtab ] && {
    ln -s /proc/mounts /etc/mtab
  }
fi ; \
cat /etc/mtab

locale-gen

# if wanted to set a password for root access
passwd

# update apt lists
apt-get update

# install missing packages via apt
[ "${DEBVERSION}" -le 4 ] && {
  apt-get install os-prober
} ; \
[ "${DEBVERSION}" -eq 6 ] && {
  apt-get install console-setup kbd
}

# install kernel
apt-get install ${DEBLINUX}
# Etch/Lenny: answer create links with "Yes", answer abort initrd image with "No"
# Squeeze/Wheezy: ignore "cat: /boot/grub/video.lst: No such file or directory"

# install updates (from security, updates/volatile, etc.)
apt-get safe-upgrade || apt-get upgrade

apt-get dist-upgrade
# GRUB/grub-pc: Continue without installing GRUB? → Yes

[ "${DEBVERSION}" -le 4 ] && {
  echo 'ATTENTION! Remember these holds when upgrading in the future' ; printf '\a'
  dpkg -i /var/tmp/dropbear_*.deb
  echo "dropbear hold" | dpkg --set-selections
  aptitude hold dropbear
  echo 'ATTENTION! Remember these holds when upgrading in the future' ; printf '\a'
}
Check if you need other packages in the Mini-Debian and install plus configure them accordingly.
# leave chroot
exit

cp -av /mnt/mini/boot/initrd.img-$(uname -r) /boot/initrd.img-$(uname -r).mini-debian

[ -n "${OLDBOOT}" ] && find /mnt/mini/boot -mindepth 1 -maxdepth 1 -exec rm -rfv '{}' \; ; \
echo 'Mini-Debian Boot' > /mnt/mini/boot/mini-debian

umount_mini-debian.sh

2.) Setup GRUB to boot into Mini-Debian

DO NOT REBOOT BEFORE STEP IS COMPLETED!!!

2a) Check GRUB release

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
echo "GRUB version ${GRUBVERSION}.x is release ${GRUBRELEASE}"

2b) Setup GRUB

2b.1) GRUB 1 (v0.9x), normally up to Debian 5.0 "Lenny"

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -n "${OLDGRUBNOBOOT}" -o -n "${OLDGRUBNOWRITE}" ] && {
  LIVECD=0
  printf '\a'
  echo "WARNING! GRUB is installed on block devices that use ${OLDGRUBCHECK}."
  :
  [ -n "${OLDGRUBNOBOOT}" ] && {
    echo "GRUB may not be able to boot from ${OLDGRUBNOBOOT}."
    LIVECD=1
  }
  :
  [ -n "${OLDGRUBNOWRITE}" ] && {
    echo "GRUB is not able to change variables during the boot phase on ${OLDGRUBNOWRITE}."
    echo 'Therefore the GRUB command "savedefault" will not work.'
    LIVECD=1
  }
  :
  [ "${LIVECD}" -eq 1 ] && {
    echo 'If anything goes wrong, then access to the machine via a live CD is needed.'
    echo 'This will allow to mount the root and boot partition, chroot into the system and fix the GRUB environment and/or boot partition.'
    echo 'Hopefully you have TESTED this BEFORE!'
  }
  :
  printf '\a'
  unset LIVECD
}

cp -av /boot/grub/menu.lst /boot/grub/menu.lst.oldroot

grep -n -e '^[[:space:]]*default[[:space:]]\+' -e '^[[:space:]]*fallback[[:space:]]\+' -e '^#[[:space:]]\+groot=' -e '^#.*[[:space:]]\+AUTOMAGIC[[:space:]]\+' -e '^[[:space:]]*title[[:space:]]\+' -e '^[[:space:]]*savedefault\([[:space:]]\+\|$\)' -e '^[[:space:]]*root[[:space:]]\+' /boot/grub/menu.lst
# Example result:
#   14:default              0
#   46:# Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST
#   48:### BEGIN AUTOMAGIC KERNELS LIST
#   49:## lines between the AUTOMAGIC KERNELS LIST markers will be modified
#   66:# groot=(hd0,0)
#   118:title               Debian GNU/Linux, kernel 2.6.26-2-i386
#   119:root                (hd0,0)
#   122:savedefault
#   124:title               Debian GNU/Linux, kernel 2.6.26-2-i386 (single-user mode)
#   125:root                (hd0,0)
#   128:savedefault
#   130:### END DEBIAN AUTOMAGIC KERNELS LIST

grub1_mini-debian.sh ; \
cat /boot/grub/custom.mini-debian.oldroot.cfg

nano /boot/grub/custom.mini-debian.oldroot.cfg
# Set savedefault to the previous default, normally this is 0 but moved up to 1 due to new boot entry of Mini-Debian as the very first entry
# Set root line to the result of the previous grep, that is the old grub partition, could be even the old root partition
# Example:
#   ### BEGIN grub1_mini-debian.sh ###
#   title           Mini-Debian
#   # FIXME: set to previous default plus 1 (normally 0 plus 1 = 1)
#   savedefault     1
#   # FIXME: set correct value for /dev/hda1, partition is minus 1
#   root            (hd0,0)
#   # FIXME: set correct root value for /dev/hda5, no /boot prefix if separate boot partition
#   kernel          /boot/vmlinuz-2.6.26-2-i386 root=/dev/hda5
#   # FIXME: no /boot prefix if separate boot partition
#   initrd          /boot/initrd.img-2.6.26-2-i386.mini-debian
#   ### END grub1_mini-debian.sh ###

sed -i -e '/^[[:space:]]*default[[:space:]]\+/ { /^[[:space:]]*default[[:space:]]\+saved/! s#^\([[:space:]]*default[[:space:]]\+\)\([^[:space:]]*\)#\# default was: \2\n\1saved# ; }' /boot/grub/menu.lst ; \
sed -i -e '/### BEGIN grub1_mini-debian.sh ###/,/### END grub1_mini-debian.sh ###/d' /boot/grub/menu.lst ; \
sed -i -e '/^# Put static boot stanzas before and\/or after AUTOMAGIC KERNEL LIST/r /boot/grub/custom.mini-debian.oldroot.cfg' /boot/grub/menu.lst ; \
sed -i -e '/### BEGIN grub1_mini-debian.sh ###/,/### END grub1_mini-debian.sh ###/! { /^[[:space:]]*savedefault[[:space:]]\+[0-9]\+/d ; }' /boot/grub/menu.lst ; \
if [ -z "${OLDGRUB1FALLBACK}" ] ; then
  sed -i -e "/^[[:space:]]*default[[:space:]]\+/ { n ; /^# fallback/! { i# fallback added\nfallback\t${MINIGRUB1FALLBACK}`printf '\n ; }'` ; }" /boot/grub/menu.lst
else
  sed -i -e "/^[[:space:]]*fallback[[:space:]]\+/ { /^[[:space:]]*fallback[[:space:]]\+${MINIGRUB1FALLBACK}/! s#^\([[:space:]]*fallback[[:space:]]\+\)\([^[:space:]]*\)#\# fallback was: \2\n\1${MINIGRUB1FALLBACK}# ; }" /boot/grub/menu.lst
fi

nano /boot/grub/menu.lst
# add/set fallback to the previous default entry, normally this is 0 but moved up to 1 due to new boot entry of Mini-Debian, use the savedefault from /boot/grub/custom.mini-debian.oldroot.cfg
# place boot entry of Mini-Debian before all others, normally before DEBIAN AUTOMAGIC KERNELS LIST, so it is boot entry number 0
# the fallback entry will also be set as new default when booting Mini-Debian, so if there are problems then on the next start the old system is booted
# defaults: default 0, fallback does not exist, saved default is "default"
# Example:
#   ~ default		saved
#   + fallback	1
#   (jump to comment to put boot entries before AUTOMAGIC KERNEL LIST, make sure there are no other active boot entries before it)
#   CTRL+- 46
#   (place cursor in the line after "# Put static boot stanzas...", then include the generated sample)
#   CTRL+r /boot/grub/custom.mini-debian.oldroot.cfg
#   CTRL+x

grep -n -e '^[[:space:]]*default[[:space:]]\+' -e '^[[:space:]]*fallback[[:space:]]\+' -e '^#[[:space:]]\+groot=' -e '^#.*[[:space:]]\+AUTOMAGIC[[:space:]]\+' -e '^[[:space:]]*title[[:space:]]\+' -e '^[[:space:]]*savedefault\([[:space:]]\+\|$\)' -e '^[[:space:]]*root[[:space:]]\+' /boot/grub/menu.lst
# check that the root line of Mini-Debian is the same as for the kernels of the AUTOMAGIC KERNELS LIST
# Example:
#   15:default              saved
#   17:fallback     1
#   49:# Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST
#   51:title                Mini-Debian
#   52:savedefault  1
#   55:root         (hd0,0)
#   62:### BEGIN AUTOMAGIC KERNELS LIST
#   63:## lines between the AUTOMAGIC KERNELS LIST markers will be modified
#   80:# groot=(hd0,0)
#   132:title               Debian GNU/Linux, kernel 2.6.26-2-i386
#   133:root                (hd0,0)
#   136:savedefault
#   138:title               Debian GNU/Linux, kernel 2.6.26-2-i386 (single-user mode)
#   139:root                (hd0,0)
#   142:savedefault
#   144:### END DEBIAN AUTOMAGIC KERNELS LIST

cp -av /boot/grub/menu.lst /boot/grub/menu.lst.mini-debian.oldroot

grub-set-default "${MINIOLDGRUB1DEFAULT}" ; \
cat /boot/grub/default

# prepare menu.lst for booting GRUB from Mini-Debian later
[ -z "${OLDBOOT}" ] && mount_mini-debian.sh

[ -z "${OLDBOOT}" ] && {
  [ -d /mnt/mini/boot/grub ] || install -v -d /mnt/mini/boot/grub
  cp -av /boot/initrd* /mnt/mini/boot/
  cp -av /boot/grub/default* /mnt/mini/boot/grub/
  cp -av /boot/grub/device* /mnt/mini/boot/grub/
  cp -av /boot/grub/menu.lst* /mnt/mini/boot/grub/
  grep -e '^#[[:space:]]\+groot=' -e '^[[:space:]]*root[[:space:]]\+' /mnt/mini/boot/grub/menu.lst
  cat /mnt/mini/boot/grub/device.map
}

[ -z "${OLDBOOT}" ] && {
  for MINIGRUBROOTDEV in $( print_subdevs_value MINIDEB 'SUBDEVS' )
   do
    MINIGRUB1DEV="$( sed -n -e "s#^[[:space:]]*(\([^)]*\))[[:space:]]\+${MINIGRUBROOTDEV}.*#\1#p" /mnt/mini/boot/grub/device.map )"
    break
  done
  for MINIGRUB1PART in $( print_subdevs_value MINIDEB 'SUBPART' )
   do
    MINIGRUB1PART="$(( ${MINIGRUB1PART} - 1 ))"
    break
  done
  echo "Mini-Debian GRUB root device ${MINIGRUBROOTDEV} is ${MINIGRUB1DEV} with partition ${MINIGRUB1PART}"
  sed -i -e '/^[[:space:]]*title[[:space:]]\+Mini-Debian$/ s#$# (direct)#' -e 's#OLDROOT#MINIDEB#' -e "s#(${OLDGRUB1DEV},${OLDGRUB1PART})#(${MINIGRUB1DEV},${MINIGRUB1PART})#" /mnt/mini/boot/grub/menu.lst
  cp -av /mnt/mini/boot/grub/menu.lst /mnt/mini/boot/grub/menu.lst.mini-debian.mini
}

[ -z "${OLDBOOT}" ] && umount_mini-debian.sh

# Choose Mini-Debian as default for next boot only
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
grub-set-default "${MINIGRUB1ENTRY}" ; \
cat /boot/grub/default

[ -n "${OLDGRUBNOBOOT}" -o -n "${OLDGRUBNOWRITE}" ] && {
  LIVECD=0
  printf '\a'
  echo "WARNING! GRUB is installed on block devices that use ${OLDGRUBCHECK}."
  :
  [ -n "${OLDGRUBNOBOOT}" ] && {
    echo "GRUB may not be able to boot from ${OLDGRUBNOBOOT}."
    LIVECD=1
  }
  :
  [ -n "${OLDGRUBNOWRITE}" ] && {
    echo "GRUB is not able to change variables during the boot phase on ${OLDGRUBNOWRITE}."
    echo 'Therefore the GRUB command "savedefault" will not work.'
    LIVECD=1
  }
  :
  [ "${LIVECD}" -eq 1 ] && {
    echo 'If anything goes wrong, then access to the machine via a live CD is needed.'
    echo 'This will allow to mount the root and boot partition, chroot into the system and fix the GRUB environment and/or boot partition.'
    echo 'Hopefully you have TESTED this BEFORE!'
  }
  :
  printf '\a'
  unset LIVECD
}

reboot

# After reboot check for successful start of Mini-Debian, otherwise fix the boot problem
[ ! -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this is NOT mini-debian. Please fix/re-try.' ; printf '\a' ; }

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

# Switch to Mini-Debian as default and fallback system
sed -i -e '/^[[:space:]]*savedefault\([[:space:]]\+\|$\)/d' -e "s#^\([[:space:]]*fallback[[:space:]]\+\)[^[:space:]]*#\1${MINIGRUB1ENTRY}#" /boot/grub/menu.lst ; \
sed -i -e "/### BEGIN grub1_mini-debian.sh/,/### END grub1_mini-debian.sh/ { /^# FIXME: set to previous default/ { n ; /^savedefault/! { isavedefault`printf '\n ; }'` ; } ; }" /boot/grub/menu.lst ; \
sed -i -e "/### BEGIN AUTOMAGIC KERNELS LIST/,/### END DEBIAN AUTOMAGIC KERNELS LIST/ { /^[[:space:]]*initrd[[:space:]]\+/ { n ; /^savedefault/! { isavedefault\t${MINIGRUB1ENTRY}`printf '\n ; }'` ; } ; }" /boot/grub/menu.lst ; \
cp -a /boot/grub/menu.lst /boot/grub/menu.lst.mini-debian.mini

[ -z "${OLDBOOT}" ] && {
  for DEV in ${OLDGRUBROOTDEVS} ; do { echo "grub-install ${DEV}" ; grub-install --no-floppy ${DEV} ; } ; done
}

# Choose Mini-Debian as default
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
grub-set-default "${MINIGRUB1ENTRY}" ; \
cat /boot/grub/default

reboot

# After reboot check for successful start of Mini-Debian, otherwise fix the boot problem
[ ! -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this is NOT mini-debian. Please fix/re-try.' ; printf '\a' ; }

reboot ; # try a 2nd time for necessary second check

# After reboot check for successful start of Mini-Debian, otherwise fix the boot problem
[ ! -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this is NOT mini-debian. Please fix/re-try.' ; printf '\a' ; }

2b.2) GRUB 2 (v1.9x), since Debian 6.0 "Squeeze"

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -n "${OLDGRUBNOBOOT}" -o -n "${OLDGRUBNOWRITE}" ] && {
  LIVECD=0
  printf '\a'
  echo "WARNING! GRUB is installed on block devices that use ${OLDGRUBCHECK}."
  :
  [ -n "${OLDGRUBNOBOOT}" ] && {
    echo "GRUB may not be able to boot from ${OLDGRUBNOBOOT}."
    LIVECD=1
  }
  :
  [ -n "${OLDGRUBNOWRITE}" ] && {
    echo 'GRUB is not able to change variables during the boot phase on those devices.'
    echo 'Therefore the Debian setting GRUB_SAVEDEFAULT and GRUB command "save_env" will not work.'
    LIVECD=1
  }
  :
  [ "${LIVECD}" -eq 1 ] && {
    echo 'If anything goes wrong, then access to the machine via a live CD is needed.'
    echo 'This will allow to mount the root and boot partition, chroot into the system and fix the GRUB environment and/or boot partition.'
    echo 'Hopefully you have TESTED this BEFORE!'
  }
  :
  printf '\a'
  unset LIVECD
}

cp -a /etc/default/grub /etc/default/grub.oldroot.org ; \
cp -a /boot/grub/grub.cfg /boot/grub/grub.cfg.oldroot.org ; \
cp -a /boot/grub/grubenv /boot/grub/grubenv.oldroot.org

# in /etc/default/grub check the following...
# ...GRUB_DEFAULT is "saved"
# ...GRUB_SAVEDEFAULT is missing, outcommented or "false"
# ...GRUB_DISABLE_OS_PROBER is "true"
sed -i -e '/^[[:space:]]*GRUB_DEFAULT=/ { /^[[:space:]]*GRUB_DEFAULT=saved/! s#^\([[:space:]]*GRUB_DEFAULT=\)\([^[:space:]]*\)#\# GRUB_DEFAULT was: \2\n\1saved# ; }' /etc/default/grub ; \
grep -q -e '^[[:space:]]*GRUB_DEFAULT=' /etc/default/grub || echo 'GRUB_DEFAULT=saved' >> /etc/default/grub ; \
sed -i -e '/^[[:space:]]*GRUB_SAVEDEFAULT=/ { /^[[:space:]]*GRUB_SAVEDEFAULT=false/! s#^\([[:space:]]*GRUB_SAVEDEFAULT=\)\([^[:space:]]*\)#\# GRUB_SAVEDEFAULT was: \2\n\1false# ; }' /etc/default/grub ; \
sed -i -e '/^[[:space:]]*GRUB_DISABLE_OS_PROBER=/ { /^[[:space:]]*GRUB_DISABLE_OS_PROBER=true/! s#^\([[:space:]]*GRUB_DISABLE_OS_PROBER=\)\([^[:space:]]*\)#\# GRUB_DISABLE_OS_PROBER was: \2\n\1true# ; }' /etc/default/grub ; \
grep -q -e '^[[:space:]]*GRUB_DISABLE_OS_PROBER=' /etc/default/grub || echo 'GRUB_DISABLE_OS_PROBER=true' >> /etc/default/grub

# recreate GRUB2 configuration
update-grub

cp -av /boot/grub/grub.cfg /boot/grub/grub.cfg.oldroot.saved

[ -z "${OLDBOOT}" ] && {
  sed -n -e '/^### BEGIN \/etc\/grub\.d\/10_linux ###/,/^### END \/etc\/grub\.d\/10_linux ###/p' /boot/grub/grub.cfg > /boot/grub/custom.cfg
  sed -i -e "/menuentry/ s#\(menuentry[[:space:]]\+'\)[^',]*#\1old root#" -e "/submenu/ s#\(submenu[[:space:]]\+'\)[^',]*#\1Advanced options for old root#" -e 's#/etc/grub\.d/10_linux#oldroot#' -e "/Loading Linux/ s#\(Loading \)\(Linux\)#\1old root \2#" /boot/grub/custom.cfg
  cat /boot/grub/custom.cfg
  cp -av /boot/grub/custom.cfg /boot/grub/custom.oldroot.mini.cfg
}

# create GRUB custom.cfg for Mini-Debian
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

mount_mini-debian.sh

# a) when booted from Mini-Debian
grub2_mini-debian.sh mini ; \
cp -av /boot/grub/custom.cfg /boot/grub/custom.mini-debian.mini.cfg ; \
cat /boot/grub/custom.cfg

# b) when booted from OLDROOT
grub2_mini-debian.sh oldroot ; \
cp -av /boot/grub/custom.cfg /boot/grub/custom.mini-debian.oldroot.cfg ; \
cat /boot/grub/custom.cfg

cp -av /etc/default/grub* /mnt/mini/etc/default/ ; \
[ -z "${OLDBOOT}" ] && {
  cp -av /boot/grub/custom.*.cfg /mnt/mini/boot/grub/
  cp -av /boot/initrd.img-$(uname -r).* /mnt/mini/boot/
}

umount_mini-debian.sh

# Choose Mini-Debian as default for next boot only:
grub-set-default 0 ; grub-reboot 'Mini-Debian' ; : \ ## WARNING!!! You need to specify "fallback default" before!!! ; \
cat /boot/grub/grubenv

[ -n "${OLDGRUBNOBOOT}" -o -n "${OLDGRUBNOWRITE}" ] && {
  LIVECD=0
  printf '\a'
  echo "WARNING! GRUB is installed on block devices that use ${OLDGRUBCHECK}."
  :
  [ -n "${OLDGRUBNOBOOT}" ] && {
    echo "GRUB may not be able to boot from ${OLDGRUBNOBOOT}."
    LIVECD=1
  }
  :
  [ -n "${OLDGRUBNOWRITE}" ] && {
    echo "GRUB is not able to change variables during the boot phase on ${OLDGRUBNOWRITE}."
    echo 'Therefore the Debian setting GRUB_SAVEDEFAULT and GRUB command "save_env" will not work.'
    LIVECD=1
  }
  :
  [ "${LIVECD}" -eq 1 ] && {
    echo 'If anything goes wrong, then access to the machine via a live CD is needed.'
    echo 'This will allow to mount the root and boot partition, chroot into the system and fix the GRUB environment and/or boot partition.'
    echo 'Hopefully you have TESTED this BEFORE!'
  }
  :
  printf '\a'
  unset LIVECD
}

reboot

# After reboot check for successful start of Mini-Debian, otherwise fix the boot problem (e.g. use first entry of /boot/grub/grub.cfg as reference, except for references to old root partion)
[ ! -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this is NOT mini-debian. Please fix/re-try.' ; printf '\a' ; }

# Re-Install GRUB to always boot from Mini-Debian
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

if [ -z "${OLDBOOT}" ] ; then
  cp -av /boot/grub/custom.oldroot.mini.cfg /boot/grub/custom.cfg
  for DEV in ${OLDGRUBROOTDEVS} ; do { echo "grub-install ${DEV}" ; grub-install --no-floppy ${DEV} ; } ; done
  update-grub
  grub-set-default 0
else
  cp -av /boot/grub/custom.mini-debian.mini.cfg /boot/grub/custom.cfg
  grub-set-default 'Mini-Debian'
fi ; \
cat /boot/grub/custom.cfg
cat /boot/grub/grubenv

reboot

# After reboot check for successful start of Mini-Debian, otherwise fix the boot problem
[ ! -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this is NOT mini-debian. Please fix/re-try.' ; printf '\a' ; }

reboot ; # try a 2nd time for necessary second check

# After reboot check for successful start of Mini-Debian, otherwise fix the boot problem
[ ! -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this is NOT mini-debian. Please fix/re-try.' ; printf '\a' ; }

2z) Revert GRUB

For the case that it is needed to revert back to old root later, e.g. after shrinking old root to rearrange Mini-Debian, so that the new root can occupy space where currently Mini-Debian resides.

2z.1) Revert GRUB 1 (v0.9x), normally up to Debian 5.0 "Lenny"

# Choose old root as default for next boot only
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
grub-set-default "${MINIOLDGRUB1DEFAULT}" ; \
cat /boot/grub/default

reboot

[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

if [ -z "${OLDBOOT}" ] ; then
  for DEV in ${OLDGRUBROOTDEVS} ; do { echo "grub-install ${DEV}" ; grub-install --no-floppy ${DEV} ; } ; done
else
  cp -av /boot/grub/menu.lst.mini-debian.oldroot /boot/grub/menu.lst
fi

# Choose old root as default
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
grub-set-default "${MINIOLDGRUB1DEFAULT}" ; \
cat /boot/grub/default

reboot

[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

2z.2) Revert GRUB 2 (v1.9x), since Debian 6.0 "Squeeze"

# Choose old root as default for next boot only
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
if [ -z "${OLDBOOT}" ] ; then
  grub-reboot 'oldroot'
else
  cp -av /boot/grub/custom.mini-debian.oldroot.cfg /boot/grub/custom.cfg
  grub-set-default 0
fi ; \
cat /boot/grub/custom.cfg ; \
cat /boot/grub/grubenv

reboot

[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -z "${OLDBOOT}" ] && {
  for DEV in ${OLDGRUBROOTDEVS} ; do { echo "grub-install ${DEV}" ; grub-install ${DEV} ; } ; done
  update-grub
} ; \
cat /boot/grub/custom.cfg ; \
cat /boot/grub/grubenv

reboot

[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

3.) Partitioning and Copying

ATTENTION!!! Adopt the following tasks to the wanted target partition scheme, which was planned during the preparation phase.

3a) Shrink old root partition

[ ! -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this is NOT mini-debian. Please fix/re-try.' ; printf '\a' ; }

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

start_fs_subdevs OLDROOT

check_fs_subdevs OLDROOT ; # TAKES TIME!!!

shrink_fs_subdevs OLDROOT

check_fs_subdevs OLDROOT '_1' ; # TAKES TIME!!!

3b) Create temporary partition

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

cp -a /etc/mdadm/mdadm.conf /etc/mdadm/mdadm.conf.oldroot ; \
cp -a /etc/crypttab /etc/crypttab.oldroot

show_temp_suggestions OLDROOT TEMPEX 6 | sed -e 's#storage#exchange#g'
# create tempex device(s) with file system as suggested, then set TEMPEX variables

determine_subdevs TEMPEX "${TEMPEX}" "${TEMPEXSIZEMIN}" 'X' > /root/bin/luks_TEMPEX.inc ; \
chmod ug=rw,o= /root/bin/luks_*.inc

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ "${TEMPEX_1TYPE}" = 'lvm' -a "${OLDROOT_1TYPE}" = 'lvm' ] && {
  [ "${TEMPEX_1VG}" != "${OLDROOT_1VG}" ] && {
    echo "TEMPEX does not share the same volume group as OLDROOT"
    echo "It is recommended to combine both volume groups via vgmerge to gain the"
    echo "possibility to move logical volumes between physical volumes via pvmove."
    echo "  lvm vgchange -a n '${TEMPEX_1VG}'"
    echo "  lvm vgmerge '${OLDROOT_1VG}' '${TEMPEX_1VG}'"
    echo "  lvm vgchange -a y '${OLDROOT_1VG}'"
    echo "  TEMPEX='/dev/${OLDROOT_1VG}/${TEMPEX_1LV}'"
    echo "  determine_subdevs TEMPEX \"\${TEMPEX}\" \"\${TEMPEXSIZEMIN}\" 'X' > /root/bin/luks_TEMPEX.inc"
    echo "  for SRC in /root/bin/luks_*.inc ; do . \"\${SRC}\" ; done"
  }
}

### TODO: lvcreate via 100%PVS via show_temp ??? ; \
# Remove dummy temporary LVM volume of 1 extent if existing
#[ "${TEMPEX_1TYPE}" = 'lvm' -a -e "${TEMPEX_1}" ] && {
#  lvm lvremove "${TEMPEX_1}"
#}

# Check if an LVM move for OLDROOT is possible
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

unset OLDROOTLVMMOVE ; \
[ "${TEMPEX_1TYPE}" = 'lvm' -a "${OLDROOT_1TYPE}" = 'lvm' ] && {
  [ "${TEMPEX_1VG}" = "${OLDROOT_1VG}" ] && {
    OLDROOTLVMMOVE='_1'
    [ -e "${TEMPEX_1}" ] && {
      lvm lvremove "${TEMPEX_1}"
    }
  }
} ; \
echo "OLDROOTLVMMOVE='${OLDROOTLVMMOVE}'" > /root/bin/luks_TEMPEX_OLDROOT.inc ; \
chmod ug=rw,o= /root/bin/luks_*.inc

# Create a big enough temporary LVM volume if necessary
#[ -z "${OLDROOTLVMMOVE}" -a "${TEMPEX_1TYPE}" = 'lvm' -a ! -e "${TEMPEX_1}" ] && {
#  if [ "${DEBVERSION}" -le 4 ]; then
#    lvm lvcreate -n "${TEMPEX_1LV}" -L "${TEMPEX_1SIZEMIN}M" "${TEMPEX_1VG}" ${TEMPEX_1SUBDEVS}
#  else
#    lvm lvcreate -n "${TEMPEX_1LV}" -l 100%PVS "${TEMPEX_1VG}" ${TEMPEX_1SUBDEVS}
#  fi
#  mkfs.${TEMPEXTYPE} "${TEMPEX_1}" ; printf '\a'
#}

3c) Copy data from old root to temporary exchange

# Do the actual copying/moving
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

start_fs_subdevs OLDROOT ; \
start_fs_subdevs TEMPEX

check_fs_subdevs TEMPEX '' "${OLDROOTLVMMOVE}" ; \
printf '\a' ; # TAKES TIME!!!

[ -n "${OLDROOTLVMMOVE}" ] && {
  echo "Use $(if [ "${DEBVERSION}" -le 4 ]; then echo 'lvdisplay'; else echo 'pvdisplay'; fi) -m and pvmove to transfer logical volume '${OLDROOT_1LV}'"
  echo "within volume group '${OLDROOT_1VG}' from physical volume(s) ${OLDROOT_1SUBDEVS}"
  echo "to physical volume(s) ${TEMPEX_1SUBDEVS},"
  echo 'which can also be done in pieces/chunks.'
  if [ "${DEBVERSION}" -le 4 ] ; then
    echo "  lvm lvdisplay -v -m ${OLDROOT_1}"
  fi
  echo "  lvm pvdisplay -v -m ${OLDROOT_1SUBDEVS} ${TEMPEX_1SUBDEVS} || lvm pvs --units m -v --segments ${OLDROOT_1SUBDEVS} ${TEMPEX_1SUBDEVS}"
  echo "  lvm pvmove --alloc anywhere -n '${OLDROOT_1LV}' <olddev>[:<oldstart>+<size>] <tempdev>[:<newstart>+<size>]"
  echo '  ## re-iterate to check and move other pieces/chunks'
  echo "  TEMPEX='${OLDROOT}'"
  echo "  determine_subdevs TEMPEX \"\${TEMPEX}\" \"\${OLDROOTSIZEMIN}\" 'X' > /root/bin/luks_TEMPEX.inc"
  echo "  for SRC in /root/bin/luks_*.inc ; do . \"\${SRC}\" ; done"
}

[ -z "${OLDROOTLVMMOVE}" ] && {
  mount_oldroot.sh
  mount_tempex.sh
}

[ -z "${OLDROOTLVMMOVE}" ] && {
  cp -axv /mnt/oldroot/. /mnt/tempex/ ; printf '\a'
} ; # TAKES TIME!!!

[ -z "${OLDROOTLVMMOVE}" ] && {
  umount_oldroot.sh
  umount_tempex.sh
}

check_fs_subdevs TEMPEX ; \
printf '\a' ; # TAKES TIME!!!

3d) Erase old root partition and create new partitions (for encrypted partition and optionally boot and/or lvm)

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

# ATTENTION!!! Get and prepare suggestions, but they will be executed later
show_newroot_suggestions OLDROOT
# ATTENTION!!! Adopt the suggestions to the wanted target partition scheme, which was planned during the preparation phase.
# determine further info before continuing (e.g. mdadm -D)

start_fs_subdevs OLDROOT

remove_fs_subdevs OLDROOT '' "${OLDROOTLVMMOVE}" "${OLDROOTLVMMOVE:+D}"

[ -z "${OLDBOOT}" -a "${GRUBRELEASE}" -ge 2 ] && rm -v /boot/grub/custom.cfg

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

# ATTENTION!!! create new BOOT and root devices with file system as suggested, then set NEWBOOT and NEWROOT variables

determine_subdevs NEWBOOT "${NEWBOOT}" "${NEWBOOTSIZEMIN}" 'X' > /root/bin/luks_NEWBOOT.inc  ; \
determine_subdevs NEWROOT "${NEWROOT}" "${NEWROOTSIZEMIN}" 'X' > /root/bin/luks_NEWROOT.inc ; \
chmod ug=rw,o= /root/bin/luks_*.inc

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

NEWGRUB="$( [ -n "${NEWBOOT}" ] && echo 'NEWBOOT' || echo 'NEWROOT' )"

unset NEWGRUBNOWRITE NEWGRUBNOBOOT ; \
NEWGRUBCHECK="$( print_subdevs_value "${NEWGRUB}" 'TYPE' 'mdadm|lvm' )" ; \
[ -n "${NEWGRUBCHECK}" ] && {
  if [ "${GRUBRELEASE}" -eq 1 ] ; then
    for TYPE in ${NEWGRUBCHECK} ; do
      case "${TYPE}" in
       (mdadm) TYPE="$( print_subdevs_value "${NEWGRUB}" 'RLEVEL' 'mdadm' )"
               if [ "${TYPE}" != 'raid1' ] ; then
                 NEWGRUBNOWRITE="${NEWGRUBNOWRITE:+${NEWGRUBNOWRITE}, or }non-level 1 mdadm raid"
                 NEWGRUBNOBOOT="${NEWGRUBNOBOOT:+${NEWGRUBNOBOOT}, or }non-level 1 mdadm raid"
               else
                 TYPE="$( print_subdevs_value "${NEWGRUB}" 'METADATA' 'mdadm' )"
                 [ "${TYPE}" = '0.90' -o "${TYPE}" = '1.0' ] && {
                   NEWGRUBNOBOOT="${NEWGRUBNOBOOT:+${NEWGRUBNOBOOT}, or }level 1 mdadm raid with super block of version ${TYPE} which is located at the end of its subdevices"
                 }
               fi
               ;;
       (lvm) NEWGRUBNOWRITE="${NEWGRUBNOWRITE:+${NEWGRUBNOWRITE}, or }lvm volume"
             NEWGRUBNOBOOT="${NEWGRUBNOBOOT:+${NEWGRUBNOBOOT}, or }lvm volume"
             ;;
      esac
    done
    unset TYPE
  elif [ "${GRUBRELEASE}" -ge 2 ] ; then
    NEWGRUBNOWRITE="${NEWGRUBNOWRITE:+${NEWGRUBNOWRITE}, or }those devices"
  fi
}

NEWGRUBROOTDEVS="$( print_subdevs_value "${NEWGRUB}" SUBDEVS 'mbr|gpt' )" ; \
echo "GRUB is (or should be) installed on ${NEWGRUBROOTDEVS}"
Create again a simple script to keep the determined details:
cat > /root/bin/luks_NEWGRUB.inc << __EOF
echo 'Setting NEWGRUB vars...' 1>&2
NEWGRUBROOTDEVS='${NEWGRUBROOTDEVS}'
NEWGRUB='${NEWGRUB}'
NEWGRUBCHECK='${NEWGRUBCHECK}'
NEWGRUBNOWRITE='${NEWGRUBNOWRITE}'
NEWGRUBNOBOOT='${NEWGRUBNOBOOT}'
__EOF

chmod ug=rw,o= /root/bin/luks_*.inc

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ "${TEMPEX_1TYPE}" = 'lvm' -a "${NEWROOT_1TYPE}" = 'lvm' ] && {
  [ "${TEMPEX_1VG}" != "${NEWROOT_1VG}" ] && {
    echo "TEMPEX does not share the same volume group as NEWROOT"
    echo "It is recommended to combine both volume groups via vgmerge to gain the"
    echo "possibility to move logical volumes between physical volumes via pvmove."
    echo "  lvm vgchange -a n '${TEMPEX_1VG}'"
    echo "  lvm vgmerge '${NEWROOT_1VG}' '${TEMPEX_1VG}'"
    echo "  lvm vgchange -a y '${NEWROOT_1VG}'"
    echo "  TEMPEX='/dev/${NEWROOT_1VG}/${TEMPEX_1LV}'"
    echo "  determine_subdevs TEMPEX \"\${TEMPEX}\" \"\${TEMPEXSIZEMIN}\" 'X' > /root/bin/luks_TEMPEX.inc"
    echo "  for SRC in /root/bin/luks_*.inc ; do . \"\${SRC}\" ; done"
  }
}

### TODO: lvcreate via OLDROOTSIZEMIN via show_newroot ??? ; \
# Remove dummy temporary LVM volume of 1 extent if existing
[ "${NEWROOT_1TYPE}" = 'lvm' -a -e "${NEWROOT_1}" ] && {
  dd if=/dev/zero of="${NEWROOT_1}" bs=1024k ; printf '\a'
  lvm lvremove "${NEWROOT_1}"
}

# Check if an LVM move for NEWROOT is possible
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

unset NEWROOTLVMMOVE ; \
[ "${TEMPEX_1TYPE}" = 'lvm' -a "${NEWROOT_1TYPE}" = 'lvm' ] && {
  [ "${TEMPEX_1VG}" = "${NEWROOT_1VG}" ] && {
    NEWROOTLVMMOVE='_1'
  }
} ; \
echo "NEWROOTLVMMOVE='${NEWROOTLVMMOVE}'" > /root/bin/luks_TEMPEX_NEWROOT.inc ; \
chmod ug=rw,o= /root/bin/luks_*.inc

# Create a big enough temporary LVM volume if necessary
[ -z "${NEWROOTLVMMOVE}" -a "${NEWROOT_1TYPE}" = 'lvm' ] && {
: \ ## NOTE: here the LV name could be switched/changed for the new encrypted root system ; \
  NEWROOT_1LV='rootfs'
  NEWROOT_1="/dev/${NEWROOT_1VG}/${NEWROOT_1LV}"
  lvm lvcreate -n "${NEWROOT_1LV}" -L "${NEWROOT_1SIZEMIN}M" "${NEWROOT_1VG}" ${NEWROOT_1SUBDEVS}
  lvm lvchange -a y "${NEWROOT_1}"
  mkfs.${NEWROOTTYPE} "${NEWROOT_1}" ; printf '\a'
  determine_subdevs NEWROOT "${NEWROOT_1}" "${NEWROOTSIZEMIN}" 'X' > /root/bin/luks_NEWROOT.inc
  for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done
}

3e) Copy data from temporary exchange to new root

# Do the actual copying/moving
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

start_fs_subdevs TEMPEX ; \
start_fs_subdevs NEWBOOT ; \
start_fs_subdevs NEWROOT

[ -z "${OLDBOOT}" ] && check_fs_subdevs NEWBOOT ; \
check_fs_subdevs NEWROOT '' "${NEWROOTLVMMOVE}" ; \
printf '\a' ; # TAKES TIME!!!

[ -n "${NEWROOTLVMMOVE}" ] && {
  echo "Use $(if [ "${DEBVERSION}" -le 4 ]; then echo 'lvdisplay'; else echo 'pvdisplay'; fi) -m and pvmove to transfer logical volume '${TEMPEX_1LV}'"
  echo "within volume group '${NEWROOT_1VG}' from physical volume(s) ${TEMPEX_1SUBDEVS}"
  echo "to physical volume(s) ${NEWROOT_1SUBDEVS}"
  if [ "${DEBVERSION}" -le 4 ] ; then
    echo "  lvm lvdisplay -v -m ${TEMPEX_1}"
  fi
  echo "  lvm pvdisplay -v -m ${TEMPEX_1SUBDEVS} ${NEWROOT_1SUBDEVS} || lvm pvs --units m -v --segments ${TEMPEX_1SUBDEVS} ${NEWROOT_1SUBDEVS}"
  echo "  lvm pvmove --alloc anywhere -n '${TEMPEX_1LV}' <tempdev>[:<oldstart>+<size>] <newdev>[:<newstart>+<size>]"
  echo "  ## When '${TEMPEX_1LV}' moved to ${NEWROOT_1SUBDEVS}"
  echo "  ## NOTE: here the LV name could be switched/changed for the new encrypted root system"
  echo "  ## via lvm lvrename '${NEWROOT_1VG}' '${TEMPEX_1LV}' '<newname>'"
  echo "  NEWROOT='/dev/${NEWROOT_1VG}/${TEMPEX_1LV}'"
  echo "  determine_subdevs NEWROOT \"\${NEWROOT}\" '${NEWROOTSIZEMIN}' 'X' > /root/bin/luks_NEWROOT.inc"
}

[ -n "${NEWROOTLVMMOVE}" ] && {
: \ ## Add dummy logical volume for determine_subdevs ; \
  TEMPEX_1LV='TEMPEX'
  TEMPEX_1="/dev/${TEMPEX_1VG}/${TEMPEX_1LV}"
  lvm lvcreate -n "${TEMPEX_1LV}" -L 1024M "${TEMPEX_1VG}" ${TEMPEX_1SUBDEVS}
  lvm lvchange -a y "${TEMPEX_1}"
  mkfs.${TEMPEXTYPE} "${TEMPEX_1}" ; printf '\a'
  determine_subdevs TEMPEX "${TEMPEX_1}" '' 'X' > /root/bin/luks_TEMPEX.inc
  for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done
}

[ -z "${NEWROOTLVMMOVE}" ] && mount_tempex.sh ; \
mount_newroot.sh noboot

[ -z "${NEWROOTLVMMOVE}" ] && {
  cp -axv /mnt/tempex/. /mnt/newroot/ ; printf '\a'
} ; # TAKES TIME!!!
Now handle the new boot partiton:
[ ! -s /root/bin/luks_TEMPEX_NEWBOOT.inc ] && {
  echo 'unset NEWBOOTMVDONE' > /root/bin/luks_TEMPEX_NEWBOOT.inc
}

[ -z "${OLDBOOT}" ] && {
  . /root/bin/luks_TEMPEX_NEWBOOT.inc
  if [ "${NEWBOOTMVDONE}" = 'DONE' ] ; then
    echo "ERROR! Copying to new boot partition was already done (NEWBOOTMVDONE=${NEWBOOTMVDONE})" ; printf '\a'
  elif [ "${NEWBOOTMVDONE}" = 'PREP' ] ; then
    echo "ERROR! Preparation for copying to new boot partition was already done (NEWBOOTMVDONE=${NEWBOOTMVDONE})" ; printf '\a'
  elif [ -n "${NEWBOOTMVDONE}" ] ; then
    echo "ERROR! Something went wrong (NEWBOOTMVDONE=${NEWBOOTMVDONE})" ; printf '\a'
  else
    if [ -n "${NEWROOTLVMMOVE}"  ] ; then
      mount_tempex.sh
      [ -d /mnt/tempex/boot ] || install -v -d /mnt/tempex/boot
      cp -axv /mnt/newroot/boot/. /mnt/tempex/boot/ && {
        NEWBOOTMVDONE='PREP'
        echo "NEWBOOTMVDONE='${NEWBOOTMVDONE}'" > /root/bin/luks_TEMPEX_NEWBOOT.inc
      }
    else
      NEWBOOTMVDONE='PREP'
      echo "NEWBOOTMVDONE='${NEWBOOTMVDONE}'" > /root/bin/luks_TEMPEX_NEWBOOT.inc
    fi
  fi
}

[ -z "${OLDBOOT}" ] && {
  . /root/bin/luks_TEMPEX_NEWBOOT.inc
  if [ "${NEWBOOTMVDONE}" = 'DONE' ] ; then
    echo "ERROR! Copying to new boot partition was already done (NEWBOOTMVDONE=${NEWBOOTMVDONE})" ; printf '\a'
  elif [ -z "${NEWBOOTMVDONE}" ] ; then
    echo "ERROR! Preparation for copying to new boot partition went wrong (NEWBOOTMVDONE=${NEWBOOTMVDONE})" ; printf '\a'
  elif [ "${NEWBOOTMVDONE}" != 'PREP' ] ; then
    echo "ERROR! Something went wrong (NEWBOOTMVDONE=${NEWBOOTMVDONE})" ; printf '\a'
  else
    find /mnt/newroot/boot -mindepth 1 -maxdepth 1 -exec rm -rf '{}' \;
    mount_newroot.sh
    cp -axv /mnt/tempex/boot/. /mnt/newroot/boot/ ; printf '\a'
    NEWBOOTMVDONE='DONE'
    echo "NEWBOOTMVDONE='${NEWBOOTMVDONE}'" > /root/bin/luks_TEMPEX_NEWBOOT.inc
  fi
}
Clean-up and checks:
[ -z "${NEWROOTLVMMOVE}" -o -z "${OLDBOOT}" ] && umount_tempex.sh ; \
umount_newroot.sh

[ -z "${OLDBOOT}" ] && check_fs_subdevs NEWBOOT ; \
check_fs_subdevs NEWROOT ; \
printf '\a' ; # TAKES TIME!!!

3f) Erase temporary exchange partition(s)

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

start_fs_subdevs TEMPEX

remove_fs_subdevs TEMPEX

rm -rf /mnt/tempex

3g) Erase unencrypted data in free space

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

show_clear_suggestions TEMPEX
# clear free space on hard disks as suggested

rm -f /root/bin/luks_TEMPEX*.inc

3h) Extend and update file system of new root partition

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

start_fs_subdevs NEWROOT

# ATTENTION!!! Only necessary when using lvm or if it is wanted to already use all available free space for root directly on encrypted partition
maximize_fs_subdevs NEWROOT

wait_fs_subdevs NEWROOT ; # TAKES TIME!!!

mount_newroot.sh
df -h /mnt/newroot/
# Example result:
#   Filesystem            Size  Used Avail Use% Mounted on
#   /dev/mapper/root      5.9G  743M  4.8G  14% /mnt/newroot

cp -av /root/bin/luks_*.inc /mnt/newroot/root/bin/ ; \
cp -av /etc/mdadm/ /mnt/newroot/etc/

sed -i -e "s#\(${OLDROOT}\|${OLDROOTMOUNT}\|UUID=${OLDROOTUUID}\)\([[:space:]]\+\|$\)#${NEWROOTMOUNT}\2#" /mnt/newroot/etc/fstab ; \
cat /mnt/newroot/etc/fstab

cp -av /etc/crypttab /mnt/newroot/etc/ ; \
sed -i -e 's#,noauto##' -e 's/^#[[:space:]]*\(\(md\|sd\|hd\)[^[:space:]]\+_crypt[[:space:]]\+\)/\1/' /mnt/newroot/etc/crypttab ; \
echo 'Activate encrypted device in /mnt/newroot/etc/crypttab' ; \
echo 'by removing the noauto option and/or the comment char at the start of its line' ; \
printf '\a' ; \
cat /mnt/newroot/etc/crypttab

nano /mnt/newroot/etc/crypttab

umount_newroot.sh

# Reboot to be sure that kernel has current device information
reboot

4.) Setup GRUB to boot into new root

DO NOT REBOOT BEFORE STEP IS COMPLETED!!!

4a) Prepare Mini-Debian and new root for new boot partition

[ ! -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this is NOT mini-debian. Please fix/re-try.' ; printf '\a' ; }

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -z "${OLDBOOT}" ] && {
  [ -d /backup-boot ] || install -v -d /backup-boot
: \ ## COPY files to backup, so the Mini-Debian boot installation is still there just in the case something goes wrong or the system shuts down ; \
  cp -axv /boot/. /backup-boot/ ; printf '\a'
  if [ "${DEBVERSION}" -le 5 ] ; then
    echo "${NEWBOOTMOUNT}       /boot           ${NEWBOOTTYPE}    defaults        0       2" >> /etc/fstab
  else
    echo "UUID=${NEWBOOTUUID}       /boot           ${NEWBOOTTYPE}    defaults        0       2" >> /etc/fstab
  fi
  mount -a
  :
  mount_newroot.sh
  if [ "${DEBVERSION}" -le 5 ] ; then
    echo "${NEWBOOTMOUNT}       /boot           ${NEWBOOTTYPE}    defaults        0       2" >> /mnt/newroot/etc/fstab
  else
    echo "UUID=${NEWBOOTUUID}       /boot           ${NEWBOOTTYPE}    defaults        0       2" >> /mnt/newroot/etc/fstab
  fi
  umount_newroot.sh
}

4b) Setup GRUB

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
echo "GRUB version ${GRUBVERSION}.x is release ${GRUBRELEASE}"

4b.1) GRUB 1 (v0.9x), normally up to Debian 5.0 "Lenny"

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -n "${NEWGRUBNOBOOT}" -o -n "${NEWGRUBNOWRITE}" ] && {
  LIVECD=0
  printf '\a'
  echo "WARNING! GRUB is installed on block devices that use ${NEWGRUBCHECK}."
  :
  [ -n "${NEWGRUBNOBOOT}" ] && {
    echo "GRUB may not be able to boot from ${NEWGRUBNOBOOT}."
    LIVECD=1
  }
  :
  [ -n "${NEWGRUBNOWRITE}" ] && {
    echo "GRUB is not able to change variables during the boot phase on ${NEWGRUBNOWRITE}."
    echo 'Therefore the GRUB command "savedefault" will not work.'
    LIVECD=1
  }
  :
  [ "${LIVECD}" -eq 1 ] && {
    echo 'If anything goes wrong, then access to the machine via a live CD is needed.'
    echo 'This will allow to mount the root and boot partition, chroot into the system and fix the GRUB environment and/or boot partition.'
    echo 'Hopefully you have TESTED this BEFORE!'
  }
  :
  printf '\a'
  unset LIVECD
}

# prepare menu.lst for booting Mini-Debian via new boot partition
[ -z "${OLDBOOT}" ] && grep -n -e '^[[:space:]]*default[[:space:]]\+' -e '^[[:space:]]*fallback[[:space:]]\+' -e '^#[[:space:]]\+groot=' -e '^#.*[[:space:]]\+AUTOMAGIC[[:space:]]\+' -e '^[[:space:]]*title[[:space:]]\+' -e '^[[:space:]]*savedefault\([[:space:]]\+\|$\)' -e '^[[:space:]]*root[[:space:]]\+' /boot/grub/menu.lst
#  15:default              saved
#  17:fallback     1
#  49:# Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST
#  51:title                Mini-Debian
#  53:savedefault  1
#  55:root         (hd0,0)
#  62:### BEGIN AUTOMAGIC KERNELS LIST
#  63:## lines between the AUTOMAGIC KERNELS LIST markers will be modified
#  80:# groot=(hd0,0)
#  132:title               Debian GNU/Linux, kernel 2.6.18-6-686
#  133:root                (hd0,0)
#  136:savedefault
#  138:title               Debian GNU/Linux, kernel 2.6.18-6-686 (single-user mode)
#  139:root                (hd0,0)
#  142:savedefault
#  144:### END DEBIAN AUTOMAGIC KERNELS LIST

[ -z "${OLDBOOT}" ] && {
  for NEWGRUBROOTDEV in ${NEWGRUBROOTDEVS}
   do
    NEWGRUB1DEV="$( sed -n -e "s#^[[:space:]]*(\([^)]*\))[[:space:]]\+${NEWGRUBROOTDEV}.*#\1#p" /boot/grub/device.map )"
    break
  done
  for NEWGRUB1PART in $( print_subdevs_value "${NEWGRUB}" 'SUBPART' 'mbr|gpt' )
   do
    NEWGRUB1PART="$(( ${NEWGRUB1PART} - 1 ))"
    break
  done
  echo "New GRUB boot device ${NEWGRUBROOTDEV} is ${NEWGRUB1DEV} with partition ${NEWGRUB1PART}"
  sed -i -e '/^[[:space:]]*title[[:space:]]\+Mini-Debian$/ s#$# (via boot)#' -e 's#/boot/#/#' -e 's#OLDROOT#NEWBOOT#' -e "s#(${OLDGRUB1DEV},${OLDGRUB1PART})#(${NEWGRUB1DEV},${NEWGRUB1PART})#" /boot/grub/menu.lst
  sed -i -e '/^[[:space:]]*savedefault\([[:space:]]\+\|$\)/d' -e "s#^\([[:space:]]*fallback[[:space:]]\+\)[^[:space:]]*#\1${MINIGRUB1ENTRY}#" /boot/grub/menu.lst
  sed -i -e "/### BEGIN grub1_mini-debian.sh/,/### END grub1_mini-debian.sh/ { /^# FIXME: set to previous default/ { n ; /^savedefault/! { isavedefault`printf '\n ; }'` ; } ; }" /boot/grub/menu.lst
  sed -i -e "/### BEGIN AUTOMAGIC KERNELS LIST/,/### END DEBIAN AUTOMAGIC KERNELS LIST/ { /^[[:space:]]*initrd[[:space:]]\+/ { n ; /^savedefault/! { isavedefault\t${MINIGRUB1ENTRY}`printf '\n ; }'` ; } ; }" /boot/grub/menu.lst
  cp -av /boot/grub/menu.lst /boot/grub/menu.lst.mini-debian.newboot
}

[ -z "${OLDBOOT}" ] && {
  for DEV in ${NEWGRUBROOTDEVS} ; do { echo "grub-install ${DEV}" ; grub-install --no-floppy ${DEV} ; } ; done
: \ ## Choose Mini-Debian as default ; \
  grub-set-default "${MINIGRUB1ENTRY}"
  cat /boot/grub/default
  :
  [ -n "${NEWGRUBNOBOOT}" -o -n "${NEWGRUBNOWRITE}" ] && {
    LIVECD=0
    printf '\a'
    echo "WARNING! GRUB is installed on block devices that use ${NEWGRUBCHECK}."
    :
    [ -n "${NEWGRUBNOBOOT}" ] && {
      echo "GRUB may not be able to boot from ${NEWGRUBNOBOOT}."
      LIVECD=1
    }
    :
    [ -n "${NEWGRUBNOWRITE}" ] && {
      echo "GRUB is not able to change variables during the boot phase on ${NEWGRUBNOWRITE}."
      echo 'Therefore the GRUB command "savedefault" will not work.'
      LIVECD=1
    }
    :
    [ "${LIVECD}" -eq 1 ] && {
      echo 'If anything goes wrong, then access to the machine via a live CD is needed.'
      echo 'This will allow to mount the root and boot partition, chroot into the system and fix the GRUB environment and/or boot partition.'
      echo 'Hopefully you have TESTED this BEFORE!'
    }
    :
    printf '\a'
    unset LIVECD
  }
}

[ -z "${OLDBOOT}" ] && reboot

# preparing the initrd for the encrypted root
[ ! -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this is NOT mini-debian. Please fix/re-try.' ; printf '\a' ; }

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

mount_newroot.sh

chroot /mnt/newroot

cd ~

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

if [ "${DEBVERSION}" -le 6 ] ; then
  rm -f /etc/mtab
  mount -a -f ; mount -a -f ; : \ ## to re-create /etc/mtab, important to re-install/update GRUB again ; \
else
  [ ! -e /etc/mtab ] && {
    ln -s /proc/mounts /etc/mtab
  }
fi ; \
cat /etc/mtab

[ "${DEBVERSION}" -le 5 ] && {
: \ ## ATTENTION: make sure you have to correct network settings in /etc/initramfs-tools/hooks/dropbear ; \
  rm -vf /etc/initramfs-tools/conf.d/dropbear
}

update-initramfs -u -k all
# if any initrd update fails, just create a new one from scratch
IVERSION="$(uname -r)" ; # FIXME: set to problematic initramfs version
rm -f /boot/initrd.img-${IVERSION} ; update-initramfs -c -k ${IVERSION}

# leave chroot
exit

# preparing GRUB to boot the encrypted root

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

grep -n -e '^#.*[[:space:]]\+AUTOMAGIC[[:space:]]\+' -e "\(${OLDROOT}\|${OLDROOTMOUNT}\|UUID=${OLDROOTUUID}\)" -e '[^g]\+root=' /boot/grub/menu.lst
#  45:# kernel     /vmlinuz root=/dev/hda2 ro
#  49:# Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST
#  57:kernel               /vmlinuz-2.6.18-4-amd64 root=/dev/sda3
#  62:### BEGIN AUTOMAGIC KERNELS LIST
#  63:## lines between the AUTOMAGIC KERNELS LIST markers will be modified
#  73:## e.g. kopt=root=/dev/hda1 ro
#  74:##      kopt_2_6_8=root=/dev/hdc1 ro
#  75:##      kopt_2_6_8_2_686=root=/dev/hdc2 ro
#  76:# kopt=root=/dev/sda2 ro
#  134:kernel              /vmlinuz-2.6.18-4-amd64 root=/dev/sda2 ro
#  140:kernel              /vmlinuz-2.6.18-4-amd64 root=/dev/sda2 ro single
#  144:### END DEBIAN AUTOMAGIC KERNELS LIST

sed -i -e "s#\(${OLDROOT}\|${OLDROOTMOUNT}\|UUID=${OLDROOTUUID}\)\([[:space:]]\+\|$\)#${NEWROOTMOUNT}\2#" /boot/grub/menu.lst ; \
cp -av /boot/grub/menu.lst /boot/grub/menu.lst.mini-debian.newroot

# Choose new root as default for next boot only
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
grub-set-default "${MINIOLDGRUB1DEFAULT}" ; \
cat /boot/grub/default

[ -n "${NEWGRUBNOBOOT}" -o -n "${NEWGRUBNOWRITE}" ] && {
  LIVECD=0
  printf '\a'
  echo "WARNING! GRUB is installed on block devices that use ${NEWGRUBCHECK}."
  :
  [ -n "${NEWGRUBNOBOOT}" ] && {
    echo "GRUB may not be able to boot from ${NEWGRUBNOBOOT}."
    LIVECD=1
  }
  :
  [ -n "${NEWGRUBNOWRITE}" ] && {
    echo "GRUB is not able to change variables during the boot phase on ${NEWGRUBNOWRITE}."
    echo 'Therefore the GRUB command "savedefault" will not work.'
    LIVECD=1
  }
  :
  [ "${LIVECD}" -eq 1 ] && {
    echo 'If anything goes wrong, then access to the machine via a live CD is needed.'
    echo 'This will allow to mount the root and boot partition, chroot into the system and fix the GRUB environment and/or boot partition.'
    echo 'Hopefully you have TESTED this BEFORE!'
  }
  :
  printf '\a'
  unset LIVECD
}

reboot

# After reboot check for successful start of new root, otherwise fix the boot problem
[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

# Choose new root as default for next boot only
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
grub-set-default "${MINIOLDGRUB1DEFAULT}" ; \
cat /boot/grub/default

reboot ; # try a 2nd time for necessary second check

# After reboot check for successful start of new root, otherwise fix the boot problem
[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

# Switch to new root as default and fallback system
sed -i -e '/### BEGIN grub1_mini-debian.sh ###/,/### END grub1_mini-debian.sh ###/d' /boot/grub/menu.lst ; \
sed -i -e "/^# default was: ${OLDGRUB1DEFAULT}/d" -e "s#^\([[:space:]]*default[[:space:]]\+\)saved#\1${OLDGRUB1DEFAULT}#" /boot/grub/menu.lst ; \
if [ -z "${OLDGRUB1FALLBACK}" ] ; then
  sed -i -e '/^# fallback added/d' -e '/^[[:space:]]*fallback\([[:space:]]\+\|$\)/d' /boot/grub/menu.lst
else
  sed -i -e "/^# fallback was: ${OLDGRUB1FALLBACK}/d" -e "s#^\([[:space:]]*fallback[[:space:]]\+\)${MINIGRUB1ENTRY}#\1${OLDGRUB1FALLBACK}#" /boot/grub/menu.lst
fi

update-grub

cp -av /boot/grub/menu.lst /boot/grub/menu.lst.newroot

# Choose new root as default
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
grub-set-default "${OLDGRUB1SAVED}" ; \
cat /boot/grub/default

reboot

# After reboot check for successful start of new root, otherwise fix the boot problem
[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

reboot ; # try a 2nd time for necessary second check

# After reboot check for successful start of new root, otherwise fix the boot problem
[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

4b.2) GRUB 2 (v1.9x), since Debian 6.0 "Squeeze"

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -n "${NEWGRUBCHECK}" ] && {
  printf '\a'
  echo "WARNING! GRUB is installed on block devices that use ${NEWGRUBCHECK}."
  echo 'GRUB is not able to change variables during the boot phase on those devices.'
  echo 'Therefore the Debian setting GRUB_SAVEDEFAULT and GRUB command "save_env" will not work.'
  echo 'If anything goes wrong then access to the machine via a live CD is needed.'
  echo 'This will allow to mount the root and boot partition, chroot into the system and fix the GRUB environment variables.'
  echo 'Hopefully you have TESTED this BEFORE!'
  printf '\a'
}

mount_newroot.sh

chroot /mnt/newroot

cd ~
for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

if [ "${DEBVERSION}" -le 6 ] ; then
  rm -f /etc/mtab
  mount -a -f ; mount -a -f ; # to re-create /etc/mtab, important to re-install/update GRUB again
else
  [ ! -e /etc/mtab ] && {
    ln -s /proc/mounts /etc/mtab
  }
fi
cat /etc/mtab

[ -z "${OLDBOOT}" ] && for DEV in ${NEWGRUBROOTDEVS} ; do { echo "grub-install ${DEV}" ; grub-install --no-floppy ${DEV} ; } ; done
update-grub
cp -av /boot/grub/grub.cfg /boot/grub/grub.cfg.newroot

update-initramfs -u -k all
# if any initrd update fails, just create a new one from scratch
IVERSION="$(uname -r)" ; # FIXME: set to problematic initramfs version
rm -f /boot/initrd.img-${IVERSION} ; update-initramfs -c -k ${IVERSION}

# leave chroot
exit

umount_newroot.sh

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -z "${OLDBOOT}" ] && {
  cp -a /boot/grub/custom.mini-debian.mini.cfg /boot/grub/custom.cfg
  sed -i -e 's#/boot/#/#' -e "/^[[:space:]]*\(set[[:space:]]\+root=\|search[[:space:]]\+\)/ s#${MINIDEBUUID}#${NEWBOOTUUID}#" /boot/grub/custom.cfg
  NEWGRUB2ROOT="$(sed -n -e '/^### BEGIN \/etc\/grub\.d\/00_header/,/^### END \/etc\/grub\.d\/00_header/ { /^[[:space:]]*set[[:space:]]\+root=/ { s#^[[:space:]]*##p ; } ; }' /boot/grub/grub.cfg | sort -u)"
  NEWGRUB2SEARCHHINT="$(sed -n -e '/^### BEGIN \/etc\/grub\.d\/00_header/,/^### END \/etc\/grub\.d\/00_header/ { /^[[:space:]]*search[[:space:]]\+.*--set=root[[:space:]]\+.*--hint/ { s#^[[:space:]]*##p ; } ; }' /boot/grub/grub.cfg | sort -u)"
  sed -i -e "/^[[:space:]]*set[[:space:]]\+root=/ { s#^\([[:space:]]*\).*#\1${NEWGRUB2ROOT}#; }" -e "/^[[:space:]]*search[[:space:]]\+.*--set=root[[:space:]]\+.*--hint/ { s#^\([[:space:]]*\).*#\1${NEWGRUB2SEARCHHINT}#; }" /boot/grub/custom.cfg
# check that "set root" is the same as in /boot/grub/grub.cfg
  grep -e '^[[:space:]]*set[[:space:]]\+root=' -e '^[[:space:]]*search[[:space:]]\+.*--set' /boot/grub/custom.cfg /boot/grub/grub.cfg
# otherwise fix manually: nano /boot/grub/custom.cfg
}

# Choose new root as default for next boot only
grub-set-default 'Mini-Debian' ; grub-reboot 0 ; : \ ## WARNING!!! You need to specify "fallback default" before!!! ; \
cat /boot/grub/grubenv

reboot
# Remember that you have to unlock the root device now before Debian starts

# After reboot check for successful start of new root, otherwise fix the boot problem
[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

# try a 2nd time for necessary second check
grub-set-default 'Mini-Debian' ; grub-reboot 0 ; : \ ## WARNING!!! You need to specify "fallback default" before!!! ; \
cat /boot/grub/grubenv

reboot

# After reboot check for successful start of new root, otherwise fix the boot problem
[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

cp -a /etc/default/grub.oldroot.org /etc/default/grub
cp -a /boot/grub/grubenv.oldroot.org /boot/grub/grubenv
update-grub
cat /boot/grub/grubenv

reboot
# Remember that you have to unlock the root device now before Debian starts

# After reboot check for successful start of new root, otherwise fix the boot problem
[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

reboot ; # try a 2nd time for necessary second check

# After reboot check for successful start of new root, otherwise fix the boot problem
[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

4c) GRUB/Boot Cleanup

rm -fv /boot/grub/custom*.cfg ; \
rm -fv /boot/grub/grub.cfg.* ; \
rm -fv /boot/grub/grubenv.* ; \
rm -fv /boot/grub/menu.lst.* ; \
rm -fv /boot/initrd.img-*.mini-debian ; \
rm -fv /etc/default/grub.*

rm -fv /boot/initrd.img-*.oldroot ; \
rm -fv /root/bin/grub*_mini-debian.sh ; \
rm -fv /root/bin/luks_*_grub*.inc ; \
rm -fv /root/bin/*mount_mini-debian.sh ; \
rm -fv /root/bin/*mount_newroot.sh ; \
rm -fv /root/bin/*mount_oldroot.sh ; \
rm -fv /root/bin/*mount_tempex.sh

5.) Remove Mini-Debian and re-create swap

5a) Remove Mini-Debian

[ -e /mini-debian ] && { echo 'ERROR!!! Unexpected system, this IS mini-debian. Please fix/re-try.' ; printf '\a' ; }

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

cp -av /etc/fstab /etc/fstab.newroot.noswap

case "${NEWROOT_1TYPE}" in
  (lvm) start_fs_subdevs MINIDEB
        remove_fs_subdevs MINIDEB
        ;;
  (*) echo "ATTENTION: new root via ${NEWROOT_1TYPE}, please handle accordingly, e.g. see 99)" ; printf '\a'
      ;;
esac

update-initramfs -u -k all ; # update InitRD with removed raids, etc.
# if any initrd update fails, just create a new one from scratch
IVERSION="$(uname -r)" ; # FIXME: set to problematic initramfs version
rm -f /boot/initrd.img-${IVERSION} ; update-initramfs -c -k ${IVERSION}

5b) Clear free space and add to LVM

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

show_clear_suggestions MINIDEB
# clear free space on hard disks as suggested

rm -f /root/bin/luks_MINIDEB.inc

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

start_fs_subdevs NEWROOT ; # only necessary when working from Live CD

case "${NEWROOT_1TYPE}" in
  (lvm) maximize_fs_subdevs NEWROOT
        ;;
  (*) echo "ATTENTION: new root via ${NEWROOT_1TYPE}, please handle accordingly, e.g. see 99)" ; printf '\a'
      ;;
esac

5c) Setup swap partition via LVM

unset NEWSWAP
NEWSWAPSIZEMIN=2048 ; # FIXME: set to wanted size in MiB, should be at least as big as 1.3x RAM size (e.g. for hibernation)
NEWSWAP_1TYPE="${NEWROOT_1TYPE}"
NEWSWAP_1VG="${NEWROOT_1VG}"
NEWSWAP_1LV='swap_1' ; # FIXME: set to wanted name

case "${NEWROOT_1TYPE}" in
  (lvm) lvm lvcreate -n "${NEWSWAP_1LV}" -L ${NEWSWAPSIZEMIN}M ${NEWSWAP_1VG}
        NEWSWAP_1="/dev/${NEWSWAP_1VG}/${NEWSWAP_1LV}"
        ;;
  (*) echo "ATTENTION: new swap via ${NEWSWAP_1TYPE}, please handle accordingly, e.g. see 99)" ; printf '\a'
      ;;
esac

mkswap "${NEWSWAP_1}"

determine_subdevs NEWSWAP "${NEWSWAP_1}" "${NEWSWAPSIZEMIN}" 'X' > /root/bin/luks_NEWSWAP.inc ; \
chmod ug=rw,o= /root/bin/luks_*.inc

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -n "${OLDSWAP}" ] && sed -i -e "s#^[[:space:]]*[#]*[[:space:]]*\(${OLDSWAP}\|${OLDSWAPMOUNT}\|UUID=${OLDSWAPTUUID}\)\([[:space:]]\+\|$\)#${NEWSWAPMOUNT}\2#" /etc/fstab ; \
grep -q -F -e "${NEWSWAPMOUNT}" /etc/fstab || echo "${NEWSWAPMOUNT} none            swap    sw              0       0" >> /etc/fstab ; \
cat /etc/fstab

swapon -a

swapon -s ; # additionally may check with top

update-initramfs -u -k all ; # already update InitRD to make it work for an accidential reboot
# if any initrd update fails, just create a new one from scratch
IVERSION="$(uname -r)" ; # FIXME: set to problematic initramfs version
rm -f /boot/initrd.img-${IVERSION} ; update-initramfs -c -k ${IVERSION}

5d) Handle hibernation

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

NEWSWAPUSEFORRESUME=1 ; # FIXME: want to use this swap partition for suspend/hibernate

echo "swap resume is ${NEWSWAPUSEFORRESUME}" ; \
[ "${NEWSWAPUSEFORRESUME:-0}" -eq 1 ] && {
  case "${NEWSWAP_1TYPE}" in
    (lvm) ;;
    (luks) echo 'WARNING!!! For using an encrypted swap partition for hibernation it has to have a static key, not a random one. Please check.' ; printf '\a'
           echo "Current key is ${NEWSWAPCRYPTKEY}"
           ;;
    (*) echo "ATTENTION: new swap via ${NEWSWAP_1TYPE}, please handle accordingly, e.g. see 99)" ; printf '\a'
        ;;
  esac
}

cat > /root/bin/luks_NEWSWAP_resume.inc << __EOF
echo 'Setting NEWSWAP RESUME vars...' 1>&2
NEWSWAPUSEFORRESUME=${NEWSWAPUSEFORRESUME:-0}
#
NEWSWAPRESUME='$( [ "${NEWSWAPUSEFORRESUME:-0}" -eq 1 ] && echo "${NEWSWAPMOUNT}" )'
OLDSWAPRESUME='$( [ -e /etc/initramfs-tools/conf.d/resume ] && sed -n -e 's#^[[:space:]]*RESUME=##p' /etc/initramfs-tools/conf.d/resume )'
#
GRUBVERSION='$( grub-install --version | sed -n -e 's#[^(]*[(]*[^0-9]*\([0-9]*\).*#\1#p' )'
[ \${GRUBVERSION} -eq 0 ] && GRUBRELEASE=1 || GRUBRELEASE=2
__EOF

chmod ug=rw,o= /root/bin/luks_*.inc

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

if [ -s /etc/initramfs-tools/conf.d/resume ] ; then
  [ -n "${OLDSWAP}" ] && sed -i -e "s#RESUME=UUID=${OLDSWAPUUID}#RESUME=${NEWSWAPRESUME}#" -e "s#RESUME=${OLDSWAP}#RESUME=${NEWSWAPRESUME}#" /etc/initramfs-tools/conf.d/resume
  nano /etc/initramfs-tools/conf.d/resume
else
  echo "RESUME=${NEWSWAPRESUME}" > /etc/initramfs-tools/conf.d/resume
fi ; \n
cat /etc/initramfs-tools/conf.d/resume

if [ "${NEWSWAPUSEFORRESUME:-0}" -eq 1 ] ; then
  echo "Make sure resume is enabled in boot loader." ; printf '\a'
  if [ "${GRUBRELEASE}" -eq 1 ] ; then
    echo 'Enable resume in GRUB 1 (v0.x), by removing noresume from defoptions in /boot/grub/menu.lst if present'
  elif [ "${GRUBRELEASE}" -ge 2 ] ; then
    echo 'Enable resume in GRUB 2 (v1.x), by removing noresume from GRUB_CMDLINE_LINUX in /etc/default/grub if present'
  fi
else
  echo "If partition for hibernation (currently ${NEWSWAPRESUME:-none}) does not exist, then disable resume in boot loader." ; printf '\a'
  if [ "${GRUBRELEASE}" -eq 1 ] ; then
    echo 'Disable resume in GRUB 1 (v0.x), by adding noresume to defoptions in /boot/grub/menu.lst when missing'
  elif [ "${GRUBRELEASE}" -ge 2 ] ; then
    echo 'Disable resume in GRUB 2 (v1.x), by adding noresume to GRUB_CMDLINE_LINUX in /etc/default/grub when missing'
  fi
fi

update-initramfs -u -k all
# if any initrd update fails, just create a new one from scratch
IVERSION="$(uname -r)" ; # FIXME: set to problematic initramfs version
rm -f /boot/initrd.img-${IVERSION} ; update-initramfs -c -k ${IVERSION}

update-grub ; # to remove old entries from Mini-Debian if still present (normally GRUB2 only) and to add changes to GRUB configuration

reboot

5e) Test

swapon -s ; # additionally may check with top

# Testing hibernation/suspend
screen ; # open a virtual console by hitting space

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done ; \
[ "${NEWSWAPUSEFORRESUME:-0}" -eq 1 ] && {
  echo 'disk' > /sys/power/state
  # reboot machine after it went to sleep
}

# restart machine

screen -r ; # reconnect to virtual console, the previous content should be displayed

exit ; # leave screen

5f) Cleanup

rm -fv /etc/fstab.newroot.* ; \
rm -fv /root/bin/luks_*.inc

rm -fv /root/bin/custom_functions.inc ; \
rm -fv /root/bin/*mount_sys.sh

Change LUKS passphrase

Be careful with this. Test it inside a Virtual Machine first.
cryptsetup luksDump /dev/sda3
cryptsetup luksAddKey /dev/sda3 [<key file>]
cryptsetup luksRemoveKey /dev/sda3
cryptsetup luksDump /dev/sda3

Additional ideas

There are several guides to protect and/or monitor the unencrypted boot partition:


99.) OUTDATED - Create Crypt-Swap on separate LUKS partition

It is recommended to also use LVM for the swap partition, there are no extra steps to take care for keeping UUID and/or supporting hibernation. Plus all advantages of LVM can be used.
The following steps haven't been checked against the latest versions of my scripts.

99a) Setup encrypted swap

# ATTENTION!!! execute 5a before this step to release hard disk space occupied by Mini-Debian

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

show_clear_suggestions MINIDEB
# clear free space on hard disks as suggested

# FIXME: choose if swap partition is encrypted with a random key or unlocked with a passphrase or the root partition key
NEWSWAPCRYPTKEY='/dev/urandom' ; # random key, no resume possible
NEWSWAPCRYPTKEY='/dev/random' ; # random key, no resume possible
NEWSWAPCRYPTKEY='none' ; # static passphrase
NEWSWAPCRYPTKEY='md1_crypt' ; # key from existing encrypted device (normally root on luks partition)
echo "swap key is ${NEWSWAPCRYPTKEY}" ; printf '\a'

show_newswap_suggestions MINIDEB "${NEWSWAPCRYPTKEY}"
# ATTENTION!!! create new swap devices as suggested, then set NEWSWAP variables and create info script

chmod ug=rw,o= /root/bin/luks_*.inc

for SRC in /root/bin/luks_*.inc ; do . "${SRC}" ; done

[ -n "${OLDSWAP}" ] && sed -i -e "s#^[[:space:]]*[#]*[[:space:]]*\(${OLDSWAP}\|${OLDSWAPMOUNT}\|UUID=${OLDSWAPTUUID}\)\([[:space:]]\+\|$\)#${NEWSWAPMOUNT}\2#" /etc/fstab ; \
grep -q -F -e "${NEWSWAPMOUNT}" /etc/fstab || {
   echo "${NEWSWAPMOUNT} none            swap    sw              0       0" >> /etc/fstab
} ; \
cat /etc/fstab

swapon -a

swapon -s ; # additionally may check with top

update-initramfs -u -k all ; # already update InitRD to make it work for an accidential reboot
# if any initrd update fails, just create a new one from scratch
IVERSION="$(uname -r)" ; # FIXME: set to problematic initramfs version
rm -f /boot/initrd.img-${IVERSION} ; update-initramfs -c -k ${IVERSION}
Continue with step 5d for hibernation and final clean up.


Top Start Kontakt