Encrypt hook in mkinitcpio.conf for full system encryption USB drive Arch install

I have installed Arch Linux on a USB drive with full system encryption using LUKS. The Arch wiki as usual walked me through almost everything. The only issue I ran into was using setting up the hooks in mkinitcpio. The Arch wiki says that for a USB install the block hook must come immediately after the udev hook. The wiki also says for encryption that the encrypt hook must come before, but not necessarily immediately, the filesystem hook. Following these rules I first tried:

HOOKS="encrypt base udev block autodetect modconf filesystems keyboard fsck"

but it didn’t work, so I moved encrypt to be later:

HOOKS="base udev block autodetect modconf encrypt filesystems keyboard fsck"

and it works fine. This leads to my question. What are the dependencies for the encrypt hook and where can I find details about hook dependencies?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Your hooks are all here:

% ls /usr/lib/initcpio/{hooks,install}
btrfs        dmraid   keymap  mdadm    mhwd-fb  miso_loop_mnt  net     shutdown  udev  v86d
consolefont  encrypt  lvm2    memdisk  miso     miso_pxe_nbd   resume  sleep     usr

autodetect  consolefont  fw        mdadm_udev  miso_loop_mnt  pata    sd-encrypt   sleep    usbinput
base        dmraid       keyboard  memdisk     miso_pxe_nbd   pcmcia  sd-lvm2      strip    usr
bcache      encrypt      keymap    mhwd-fb     mmc            resume  sd-shutdown  systemd  v86d
block       filesystems  lvm2      miso        modconf        sata    sd-vconsole  udev     virtio
btrfs       fsck         mdadm     miso_kms    net            scsi    shutdown     usb

They’re all shell scripts:

% cat /usr/lib/initcpio/{hooks,install}/encrypt
run_hook() {
    modprobe -a -q dm-crypt >/dev/null 2>&1
    [ "${quiet}" = "y" ] && CSQUIET=">/dev/null"
    # Get keyfile if specified
    if [ -n "$cryptkey" ]; then
        IFS=: read ckdev ckarg1 ckarg2 <<EOF

This is stuff you already know – it’s very familiar.

Basically if you want something to happen in early userspace, you need only load the necessary kernel modules and act accordingly – that’s all any of these hooks are doing.

If you want to know what’s going on in the initramfs image, just take a peek:

% lsinitcpio --help lsinitcpio 17 usage: lsinitcpio [action] [options] 
usage: lsinitcpio [action] [options] <initramfs>

   -a, --analyze        analyze contents of image
   -c, --config         show configuration file image was built with
   -l, --list           list contents of the image (default)
   -x, --extract        extract image to disk

   -h, --help           display this help
   -n, --nocolor        disable colorized output
   -V, --version        display version information
   -v, --verbose        more verbose output

lsinitcpio is handy, but it’s nothing more than a helper shell function – just like the rest of those. When you look into your disk image you’ll notice that it’s really nothing more than that – just a regular linux root image after all:

% mkdir /tmp/init ; cd $_
% lsinitcpio $(printf /boot/*.img | head -n1) | grep -Eo '^./[^/]*' | sort -u

You can extract it:

% lsinitcpio --extract $(printf /boot/*.img | head -n1)
% ls

And poke around:

% cat ./init_functions
default_mount_handler() {
    if [ ! -b "$root" ]; then
        err "Unable to find root device '$root'."
        echo "You are being dropped to a recovery shell"
        echo "    Type 'exit' to try and continue booting"
        msg "Trying to continue (this will most likely fail) ..."
    msg ":: mounting '$root' on real root"
    if ! mount ${fstype:+-t $fstype} -o ${rwopt:-ro}${rootflags:+,$rootflags} "$root" "$1"; then
        echo "You are now being dropped into an emergency shell."
        msg "Trying to continue (this will most likely fail) ..."

Solution 2

Your issue was that the hooks are executed in the order they are listed in the HOOKS line (which is just an array) in /etc/mkinitcpio.conf. Essentially, you were trying to run the encrypt script before the base hook, which provides the runtime necessities for booting1.

You can read about each of the hooks by issuing mkinitcpio -H $hook.

The Arch Wiki mkinitcpio page has a good explanation. You can also read each of the hooks in /usr/lib/initcpio/hooks/ to see what is actually being run.

The mkinitcpio developer for Arch, Dave Reisner, also has a good post on optimising mkinitcpio which has a more detailed explanation of how it all fits together.

1. The Archwiki mkinitcpio page does make clear that you should always include the base hook first, “unless you know what you are doing.” Caveat lector

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply