Hi folks,

I have Alpine Linux installed in an encrypted LUKS partition. I came across this tutorial which shows how to setup a key in a USB drive and when the drive is inserted and the computer booted, the LUKS partition auto-unlocks with the key on the USB drive.

https://askubuntu.com/questions/1414617/configure-ubuntu-22-04-zfs-for-automatic-luks-unlock-on-boot-via-usb-drive

I would like to setup the same thing but I do not have Alpine linux installed on ZFS, so I’m looking for ways to adapt the instructions.

So far, what I’ve done is:

  1. I’ve setup the key on the usb stick and I can unlock the LUKS partition with that key.
  2. create a /etc/mkinitfs/features.d/usb-unlock.sh script with the following content:

(the echo to /dev/kmesg was to check whether the script did indeed run at boot by trying to print to the kernel messages but I can’t find anything in the kernel messages).

#!/bin/sh

echo "usb-unlock script starting..." > /dev/kmsg

USB_MOUNT="/mnt/my-usb-key" # The USB stick mounting point
LUKS_KEY_FILE="awesome.key"  # The name of your keyfile on the USB stick

# Search for the USB stick with the key
for device in $(ls /dev/disk/by-uuid/*); do
    mount $device $USB_MOUNT 2>/dev/null
    if [ -f "$USB_MOUNT/$LUKS_KEY_FILE" ]; then
        # Unlock the LUKS partition
        cryptsetup luksOpen /dev/sda3 cryptroot \
            --key-file "$USB_MOUNT/$LUKS_KEY_FILE" && exit 0
    fi
    umount $USB_MOUNT
done
echo "No USB key found, falling back to password prompt." # this message never appears, despite not having found the key on the usb stick

echo "usb-unlock script ending." > /dev/kmsg
  1. I added usb-unlock to the features in mkinitfs.conf:
mytestalpine:~# cat /etc/mkinitfs/mkinitfs.conf 
features="ata base ide scsi usb virtio ext4 cryptsetup keymap usb-unlock"
  1. run mkinitfs to rebuild the initramfs. Then reboot to test the implementation, which was unsuccessful.

What am I missing / doing wrong? Thank you for your help!

Edit: forgot to add step 4

5 points

mkinitfs doesn’t support running custom shell hooks. mkinitfs is very, very, very bare-bones custom code and the whole features concept exists only to pull extra files and kernel modules into the initramfs, not for extra logic.

You’d either have to customize the init script itself (not impossible, it’s 1000 lines) and pass -i/set init= in the .conf, or install Dracut/Booster instead (which should “just work” if you apk add them, but I’ve had no need to do so).

permalink
report
reply
3 points

It seems you might be right. There is so little documentation for initramfs in Alpine Linux (the wiki page is very barebones), but I did manage to find this open issue:

https://gitlab.alpinelinux.org/alpine/mkinitfs/-/issues/18

So I guess this confirms that it is not yet possible.

Could you expand on your suggestion with customizing the init script? Where is this file located, and would you have some pointers of how to get started to customize it for my use case?

permalink
report
parent
reply
4 points

You’d be looking for /usr/share/mkinitfs/initramfs-init . I’ve never customized that myself, but it looks like there’s already some support for a keyfile if you look for KOPT_cryptroot and check that block of code. That looks like it’s mostly set up for a keyfile embedded into the initramfs, but I guess it should be possible to replace that code with something that grabs the keyfile off an USB drive.

I suppose you’d make a copy of it, put it somewhere in /etc or whatever and change the mkinitfs.conf to point to it. init="/etc/whatever/myinitramfs-init" should do the trick since the config file just gets sourced in. That said you’re definitively heading into unknown territory here. It might be easier to just use Dracut or the like instead.

permalink
report
parent
reply
1 point
*

Thank you for your help.

I decided to give dracut a shot, see how far I could get.

I created a directory /usr/lib/dracut/modules.d/99usb-mount in which I created two scripts: A first module /usr/lib/dracut/modules.d/99usb-mount/module-setup.sh, executable:

#!/bin/bash

check() {
    return 0
}

depends() {
    echo "crypt"
    return 0
}

install() {
    inst_hook pre-mount 90 "$moddir/usb-mount.sh"
}

And a second script /usr/lib/dracut/modules.d/99usb-mount/usb-mount.sh, also executable:

#!/bin/bash

LUKS_PARTITION=/dev/sda3
USB_NKL=/dev/disk/by-uuid/<MY-UUID>
USB_MOUNT_DIR=/mnt/my-usb/
KEY_FILENAME=mykey.key

# Wait for the USB to be detected and available
for i in {1..10}; do
    if [ -b ${USB_NKL} ]; then
        break
    fi
    sleep 1
done

# Mount the USB stick
mount ${USB_NKL} ${USB_MOUNT_DIR}

# Check if the mount was successful
if [ $? -ne 0 ]; then
    echo "Failed to mount USB stick"
    exit 1
fi

# Unlock the LUKS partition using the keyfile
if [ -e "${USB_MOUNT_DIR}/${KEY_FILENAME}" ]; then
    cryptsetup luksOpen "${LUKS_PARTITION}" cryptroot --key-file "${USB_MOUNT_DIR}/${KEY_FILENAME}"
else
    echo "Keyfile not found!"
    echo "Failed to unlock LUKS partition"
    exit 1
fi

I then fixed some dependencies and got around installing device-mapper, providing dmsetup, required by dm, required by crypt, required by my scripts.

Then I ran: dracut -f, which didn’t seem to have any issue and includes my module:

[...]
dracut[I]: *** Including module: usb-mount ***
[...]
dracut[E]: ldconfig exited ungracefully
[...]
dracut[I]: *** Creating initramfs image file '/boot/initramfs-6.6.54-0-lts.img' done ***

Not sure if this ldconfig error should be of any concern? The end image seems to have been created successfully.

When I check the verbose output, I see my module being included:

dracut[D]: -rwxr-xr-x 0/0       747 2024-10-07 22:30:00 lib/dracut/hooks/pre-mount/90-usb-mount.sh

However, it is here numbered 90 when above I had placed it in 99, no idea what that’s about? (edit: actually I wrote 90 in the module-setup.sh, so this is normal I guess).

Then I rebooted with my key and the prompt for my password to unlock my LUKS partition still appeared.

In the kernel messages I see my usb stick being detected (perhaps not mounted?) prior to the password prompt, so not sure what’s going on. Do you see any issue with my attempt? Or would you happen to have any propositions for debugging this further? I’m a bit lost as to how I can diagnose the issue.

Here are the kernel messages regarding the usb detection and a few seconds later, me unlocking the LUKS partition:

[    1.748076] usb 1-1: new high-speed USB device number 2 using xhci_hcd # usb 1-1 / sdb is my USBkey. It seems to have been detected but not mounted?
[    2.068060] device-mapper: uevent: version 1.0.3
[    2.068190] device-mapper: ioctl: 4.48.0-ioctl (2023-03-01) initialised: dm-devel@redhat.com
[    2.078157] Key type encrypted registered
[    2.153792] usb 1-1: New USB device found, idVendor=067b, idProduct=2517, bcdDevice= 1.00
[    2.153799] usb 1-1: New USB device strings: Mfr=1, Product=4, SerialNumber=6
[    2.153801] usb 1-1: Product: ClipDrive
[    2.153803] usb 1-1: Manufacturer: BUFFALO
[    2.153805] usb 1-1: SerialNumber: A9200502030000221
[    2.155494] usb-storage 1-1:1.0: USB Mass Storage device detected
[    2.157341] scsi host3: usb-storage 1-1:1.0
[    2.159772] usbcore: registered new interface driver uas
[    3.221531] scsi 3:0:0:0: Direct-Access     BUFFALO  ClipDrive        1.00 PQ: 0 ANSI: 0 CCS
[    3.224250] sd 3:0:0:0: [sdb] 507904 512-byte logical blocks: (260 MB/248 MiB)
[    3.227885] sd 3:0:0:0: [sdb] Write Protect is off
[    3.227899] sd 3:0:0:0: [sdb] Mode Sense: 23 00 00 00
[    3.231635] sd 3:0:0:0: [sdb] No Caching mode page found
[    3.231645] sd 3:0:0:0: [sdb] Assuming drive cache: write through
[    3.247551] sd 3:0:0:0: [sdb] Attached SCSI removable disk
[    6.323670] EXT4-fs (dm-0): orphan cleanup on readonly fs   # the 3 seconds gap is me unlocking the LUKS using the keyboard
[    6.323954] EXT4-fs (dm-0): mounted filesystem 33a8b408-37ff-4b8a-98bf-bba8b6f00604 ro with ordered data mode. Quota mode: none.
[    6.324134] Mounting root: ok.
permalink
report
parent
reply
3 points

I think you may want to use for device in /dev/disk/by-uuid/*

That doesn’t explain why you aren’t seeing messages. I see there is a shebang at the start of the script. Can you confirm that the script has the executable bit set for the root user?

permalink
report
reply
1 point
*

Yes it does (have the execution bit).

edit: added paranthesis

permalink
report
parent
reply
3 points
*

More of a debugging step, but have you tried running lsinitrd on the initramfs afterwards to verify your script actually got added?

You theoretically could decompress the entire image to look around as well. I don’t know the specifics for alpine, but presumably there would be a file present somewhere that should be calling your custom script.

EDIT: Could it also be failing because the folder you are trying to mount to does not exist? Don’t you need a mkdir somewhere in your script?

permalink
report
reply
1 point

From my understanding, features always refer to components from within /etc/mkinitfs/features.d/

permalink
report
parent
reply
2 points
*

Seems that the file /etc/mkinitfs/features.d/ is only linux alphine thing so creating it for another linux distro does nothing.

https://wiki.alpinelinux.org/wiki/Initramfs_init

I would create a systemd service instead if your distro is using systemd https://www.slingacademy.com/article/ubuntu-how-to-create-a-custom-systemd-service/#Introduction

Edit: Sorry please ignore my comment. Your entire system is encrypted so that won’t work. I’ll see if there is another solution and post it

Edit2: Maybe you need to place the file here instead /usr/share/initramfs- tools/scripts/ ? https://manpages.ubuntu.com/manpages/bionic/en/man8/initramfs-tools.8.html

permalink
report
reply
1 point

Could it be? I don’t have that directory. Maybe this is Ubuntu specific? Not sure.

permalink
report
parent
reply
0 points

would be easier if you tell us which distro are you running mkinitfs on

permalink
report
parent
reply
2 points
*

This is about Alpine linux, as I wrote in the title and twice in the post.

permalink
report
parent
reply
0 points

@TheHobbyist isn’t it better to find the plugged USB flash drive by parsing the output of dmesg?

permalink
report
reply
1 point

That may be an option, but for the time being, I’m not even sure how to start debugging this. I have no idea where to start looking. I don’t even know if the usb-unlock.sh script is even running at boot. Any thoughts?

permalink
report
parent
reply
2 points

Just a sanity check because I’ve totally done this before: did you make the script file executable?

permalink
report
parent
reply
2 points

Good point. Yes it is.

permalink
report
parent
reply

Linux

!linux@lemmy.ml

Create post

From Wikipedia, the free encyclopedia

Linux is a family of open source Unix-like operating systems based on the Linux kernel, an operating system kernel first released on September 17, 1991 by Linus Torvalds. Linux is typically packaged in a Linux distribution (or distro for short).

Distributions include the Linux kernel and supporting system software and libraries, many of which are provided by the GNU Project. Many Linux distributions use the word “Linux” in their name, but the Free Software Foundation uses the name GNU/Linux to emphasize the importance of GNU software, causing some controversy.

Rules

  • Posts must be relevant to operating systems running the Linux kernel. GNU/Linux or otherwise.
  • No misinformation
  • No NSFW content
  • No hate speech, bigotry, etc

Related Communities

Community icon by Alpár-Etele Méder, licensed under CC BY 3.0

Community stats

  • 7.7K

    Monthly active users

  • 6.5K

    Posts

  • 179K

    Comments