Ssh – update-initramfs failing after upgrading to stretch from jessie

debianinitramfsssh

I recently updated one of my Debian boxes to run with stretch, but unfortunately I run in an issue when it comes to the regeneration of the initramfs image.

It seems that it doesn't recognize that I need the /root/.ssh/ directory and its contents to be there at boot time.
I tried to look for a config option to force update-initramfs to take the contents which are in /etc/initramfs-tools/root – which I manually created after it failed to generate the image – but without any luck.
Finally I did a debootstrap install from a sysresccd to ensure it is not a failure from a config on my side, but this failed as well.

What follows, is the output I get when trying to update the initramfs image:

root@sysresccd:/etc/initramfs-tools# update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-4.3.0-1-amd64
/etc/initramfs-tools/hooks/mount_cryptroot: 21: /etc/initramfs-tools/hooks/mount_cryptroot: cannot create /var/tmp/mkinitramfs_uIC6Q0/root/mount_cryptroot.sh: Directory nonexistent
chmod: cannot access /var/tmp/mkinitramfs_uIC6Q0/root/mount_cryptroot.sh: No such file or directory
/etc/initramfs-tools/hooks/mount_cryptroot: 36: /etc/initramfs-tools/hooks/mount_cryptroot: cannot create /var/tmp/mkinitramfs_uIC6Q0/root/.profile: Directory nonexistent
/etc/initramfs-tools/hooks/mount_cryptroot: 21: /etc/initramfs-tools/hooks/mount_cryptroot: cannot create /var/tmp/mkinitramfs_uIC6Q0/root/mount_cryptroot.sh: Directory nonexistent
chmod: cannot access /var/tmp/mkinitramfs_uIC6Q0/root/mount_cryptroot.sh: No such file or directory
/etc/initramfs-tools/hooks/mount_cryptroot: 36: /etc/initramfs-tools/hooks/mount_cryptroot: cannot create /var/tmp/mkinitramfs_uIC6Q0/root/.profile: Directory nonexistent
E: /etc/initramfs-tools/hooks/mount_cryptroot failed with return 2.
update-initramfs: failed for /boot/initrd.img-4.3.0-1-amd64 with 2.

Actually I am out of ideas now and would be really thankful if somebody could help me with this issue.

Some background information:
I use this guide to install my systems and for jessie it works perfectly, but on stretch it fails because of the reason stated above.

Best Answer

The same issue occured to me today and I could only find this question in the web. So I tried to debug it myself...

The script /etc/initramfs-tools/hooks/mount_cryptroot (line 21) is trying to put a file into the /var/tmp/mkinitramfs_uIC6Q0/root/ directory. This directory happens to be missing, according to the error message. The relevant part of the script is:

SCRIPT="${DESTDIR}/root/mount_cryptroot.sh"
cat > "${SCRIPT}" << 'EOF'

The /var/tmp/mkinitramfs_uIC6Q0/ directory is a temporary directory in which the contents of the new initrd are collected. My guess was that the initrd does not have a root subdirectory any more. So I took a look at the contents of the existing initrd image:

# mkdir initrd
# cd initrd
# gunzip -c /boot/initrd.img-4.9.0-3-amd64 | cpio -i
125955 blocks
# ls
bin  conf  etc  init  lib  lib64  root-aBcDeF  run  sbin  scripts
#

The root directory has a suffix with 6 random letters/numbers (changed here to aBcDeF). This is probably for security reasons. I found out that the suffix is different each time the initrd is generated.

So the solution is to extend the /etc/initramfs-tools/hooks/mount_cryptroot script to find out the true name of the root directory including the suffx and to use this instead of just root.

This can be done by inserting

ROOTDIR="$(cd "${DESTDIR}"; echo root-*)"

before the failing lines and changing the failing lines to

SCRIPT="${DESTDIR}/${ROOTDIR}/mount_cryptroot.sh"
cat > "${SCRIPT}" << 'EOF'

. There are two more lines that contain root without the suffix. Those have to be changed to

cat > "${DESTDIR}/${ROOTDIR}/.profile" << EOF

and

/${ROOTDIR}/mount_cryptroot.sh && exit 1 || echo "Run ./mount_cryptroot.sh to try unlocking again"

. This solved the issue for me and

update-initramfs -u -k all

as well as the entering of the password via SSH on bootup worked again.

My entire script /etc/initramfs-tools/hooks/mount_cryptroot after adaption:

#!/bin/sh

# Author: http://www.dont-panic.cc/capi/2012/10/24/fully-encrypted-vserver-with-ubuntu-12-04/
# This script generates two scripts in the initramfs output,
# /root-xxxxxx/mount_cryptroot.sh and /root-xxxxxx/.profile
ALLOW_SHELL=1
# Set this to 1 before running update-initramfs if you want
# to allow authorized users to type Ctrl-C to drop to a
# root shell (useful for debugging, potential for abuse.)
#
# (Note that even with ALLOW_SHELL=0 it may still be possible
# to achieve a root shell.)
#

if [ -z ${DESTDIR} ]; then
exit
fi

ROOTDIR="$(cd "${DESTDIR}"; echo root-*)"

SCRIPT="${DESTDIR}/${ROOTDIR}/mount_cryptroot.sh"
cat > "${SCRIPT}" << 'EOF'
#!/bin/sh
CMD=
while [ -z "$CMD" -o -z "`pidof askpass plymouth`" ]; do
CMD=`ps -o args | grep 'open --type luks' | grep -v grep`
sleep 0.1
done
while [ -n "`pidof askpass plymouth`" ]; do
$CMD && kill -9 `pidof askpass plymouth` && echo "Success"
done
EOF

chmod +x "${SCRIPT}"

# Run mount_cryptroot by default and close the login session afterwards
# If ALLOW_SHELL is set to 1, you can press Ctrl-C to get to an interactive prompt
cat > "${DESTDIR}/${ROOTDIR}/.profile" << EOF
ctrl_c_exit() {
exit 1
}
ctrl_c_shell() {
# Ctrl-C during .profile appears to mangle terminal settings
reset
}
if [ "$ALLOW_SHELL" == "1" ]; then
echo "Unlocking rootfs... Type Ctrl-C for a shell."
trap ctrl_c_shell INT
else
echo "Unlocking rootfs..."
trap ctrl_c_exit INT
fi
/${ROOTDIR}/mount_cryptroot.sh && exit 1 || echo "Run ./mount_cryptroot.sh to try unlocking again"
trap INT
EOF
Related Question