~alpine/devel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
2 2

[PATCH alpine-conf v8] Support encrypted root in setup-disk

Krystian Chachuła <krystian@krystianch.com>
Details
Message ID
<20210814191142.11043-1-krystian@krystianch.com>
DKIM signature
missing
Download raw message
Patch: +106 -29
Co-authored-by: Drew DeVault <sir@cmpwn.com>
---
Major changes since v7 are:
* setup_grub and setup_root: when using EFI and encryption, the boot
  partition is unencrypted and mounted to /boot instead of /boot/efi
  (like current behavior with syslinux); this solves two issues: setting
  up GRUB with luks2 encrypted /boot is difficult, installing GRUB with
  encrypted /boot needs chroot or a workaround (see v7 discussion)
* install_mounted_root: cryptroot kernel param is now set to UUID
  instead of device name
* init_progs: blkid is explicitly installed, because crypt_required
  needs it

I tested sys and cryptsys installation with syslinux/BIOS,
GRUB/BIOS and GRUB/EFI on x86_64.

See
https://git.sr.ht/~krystianch/alpine-conf/commit/70aaffca3d4685f3a8d78deaca7b479521b13ab8
for full diff between v7 and v8.

I'd appreciate a review / feedback.

 setup-disk.in | 135 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 106 insertions(+), 29 deletions(-)

diff --git a/setup-disk.in b/setup-disk.in
index 656b5bc..46c8068 100644
--- a/setup-disk.in
+++ b/setup-disk.in
@@ -82,6 +82,26 @@ enumerate_fstab() {
		done
}

# given an fstab on stdin, determine if any of the mountpoints are encrypted
crypt_required() {
	while read -r devname mountpoint fstype mntops freq passno; do
		if [ -z "$devname" ] || [ "${devname###}" != "$devname" ]; then
			continue
		fi
		uuid="${devname##UUID=}"
		if [ "$uuid" != "$devname" ]; then
			devname="$(blkid --uuid "$uuid")"
		fi
		mapname="${devname##/dev/mapper/}"
		if [ "$mapname" != "$devname" ]; then
			if cryptsetup status "$mapname" >&1 >/dev/null; then
				return 0
			fi
		fi
	done
	return 1
}

is_vmware() {
	grep -q VMware /proc/scsi/scsi 2>/dev/null \
		|| grep -q VMware /proc/ide/hd*/model 2>/dev/null
@@ -283,19 +303,23 @@ setup_grub() {
	# install GRUB efi mode
	if [ -n "$USE_EFI" ]; then
		local target fwa
		local efi_directory="$mnt"/boot/efi
		case "$ARCH" in
			x86_64)		target=x86_64-efi ; fwa=x64 ;;
			x86)		target=i386-efi ; fwa=ia32 ;;
			arm*)		target=arm-efi ; fwa=arm ;;
			aarch64)	target=arm64-efi ; fwa=aa64 ;;
		esac
		if [ -n "$USE_CRYPT" ]; then
			efi_directory="$mnt"/boot
		fi
		# currently disabling nvram so grub doesnt call efibootmgr
		# installing to alpine directory so other distros dont overwrite it
		grub-install --target=$target --efi-directory="$mnt"/boot/efi \
		grub-install --target=$target --efi-directory="$efi_directory" \
			--bootloader-id=alpine --boot-directory="$mnt"/boot --no-nvram
		# fallback mode will use boot/boot${fw arch}.efi
		install -D "$mnt"/boot/efi/EFI/alpine/grub$fwa.efi \
			"$mnt"/boot/efi/EFI/boot/boot$fwa.efi
		install -D "$efi_directory"/EFI/alpine/grub$fwa.efi \
			"$efi_directory"/EFI/boot/boot$fwa.efi
	# install GRUB for ppc64le
	elif [ "$ARCH" = "ppc64le" ]; then
		shift 5
@@ -427,7 +451,7 @@ setup_raspberrypi_bootloader() {
install_mounted_root() {
	local mnt="$1"
	shift 1
	local disks="${@}" mnt_boot= boot_fs= root_fs=
	local disks="${@}" mnt_boot= boot_fs= root_fs= use_crypt=
	local initfs_features="ata base ide scsi usb virtio"
	local pvs= dev= rootdev= bootdev= extlinux_raidopt= root= modules=
	local kernel_opts="$KERNELOPTS"
@@ -490,7 +514,6 @@ install_mounted_root() {
		esac
	done


	if [ -n "$VERBOSE" ]; then
		echo "Root device:     $rootdev"
		echo "Root filesystem: $root_fs"
@@ -513,6 +536,28 @@ install_mounted_root() {
	# we should not try start modloop on sys install
	rm -f "$mnt"/etc/runlevels/*/modloop

	# generate the fstab
	if [ -f "$mnt"/etc/fstab ]; then
		mv "$mnt"/etc/fstab "$mnt"/etc/fstab.old
	fi
	enumerate_fstab "$mnt" >> "$mnt"/etc/fstab
	if [ -n "$SWAP_DEVICES" ]; then
		local swap_dev
		for swap_dev in $SWAP_DEVICES; do
			echo -e "$(uuid_or_device ${swap_dev})\tswap\tswap\tdefaults\t0 0" \
				>> "$mnt"/etc/fstab
		done
	fi
	cat >>"$mnt"/etc/fstab <<-__EOF__
		/dev/cdrom	/media/cdrom	iso9660	noauto,ro 0 0
		/dev/usbdisk	/media/usb	vfat	noauto	0 0
	__EOF__

	if crypt_required <"$mnt"/etc/fstab; then
		use_crypt=1
		initfs_features="$initfs_features cryptsetup"
	fi

	# generate mkinitfs.conf
	mkdir -p "$mnt"/etc/mkinitfs/features.d
	echo "features=\"$initfs_features\"" > "$mnt"/etc/mkinitfs/mkinitfs.conf
@@ -530,24 +575,15 @@ install_mounted_root() {
	if [ -n "$(get_bootopt nomodeset)" ]; then
		kernel_opts="nomodeset $kernel_opts"
	fi
	if [ "$use_crypt" ] && cryptsetup status "$rootdev" 2>&1 >/dev/null; then
		# Boot to encrypted root
		root=$(cryptsetup status "$rootdev" | awk '/device:/ { print $2 }')
		root=$(uuid_or_device $root)
		kernel_opts="cryptroot=$root cryptdm=root"
		root=/dev/mapper/root
	fi
	modules="sd-mod,usb-storage,${root_fs}${raidmod}"

	# generate the fstab
	if [ -f "$mnt"/etc/fstab ]; then
		mv "$mnt"/etc/fstab "$mnt"/etc/fstab.old
	fi
	enumerate_fstab "$mnt" >> "$mnt"/etc/fstab
	if [ -n "$SWAP_DEVICES" ]; then
		local swap_dev
		for swap_dev in $SWAP_DEVICES; do
			echo -e "$(uuid_or_device ${swap_dev})\tswap\tswap\tdefaults\t0 0" \
				>> "$mnt"/etc/fstab
		done
	fi
	cat >>"$mnt"/etc/fstab <<-__EOF__
		/dev/cdrom	/media/cdrom	iso9660	noauto,ro 0 0
		/dev/usbdisk	/media/usb	vfat	noauto	0 0
	__EOF__
	# remove the installed db in case its there so we force re-install
	rm -f "$mnt"/var/lib/apk/installed "$mnt"/lib/apk/db/installed
	echo "Installing system on $rootdev:"
@@ -595,6 +631,10 @@ unmount_partitions() {

	# unmount the partitions
	umount $(awk '{print $2}' /proc/mounts | egrep "^$mnt(/|\$)" | sort -r)

	if [ "$USE_CRYPT" ]; then
		cryptsetup close /dev/mapper/root
	fi
}

# figure out decent default swap size in mega bytes
@@ -697,9 +737,10 @@ select_bootloader_pkg() {

# install needed programs
init_progs() {
	local raidpkg= lvmpkg= fs= fstools= grub=
	local raidpkg= lvmpkg= cryptpkg= fs= fstools= grub=
	[ -n "$USE_RAID" ] && raidpkg="mdadm"
	[ -n "$USE_LVM" ] && lvmpkg="lvm2"
	[ -n "$USE_CRYPT" ] && cryptpkg="cryptsetup blkid"
	for fs in $BOOTFS $ROOTFS $VARFS; do
		# we need load btrfs module early to avoid the error message:
		# 'failed to open /dev/btrfs-control'
@@ -714,7 +755,7 @@ init_progs() {
		vfat) fstools="$fstools dosfstools";;
		esac
	done
	apk add --quiet sfdisk $lvmpkg $raidpkg $fstools $@
	apk add --quiet sfdisk $cryptpkg $lvmpkg $raidpkg $fstools $@
}

show_disk_info() {
@@ -1018,11 +1059,11 @@ setup_root() {
	mkfs.$ROOTFS $MKFS_OPTS_ROOT $mkfs_args "$root_dev"
	mkdir -p "$SYSROOT"
	mount -t $ROOTFS $root_dev "$SYSROOT" || return 1
	if [ -n "$boot_dev" ] && [ -z "$USE_EFI" ]; then
	if [ -n "$boot_dev" ] && ([ -z "$USE_EFI" ] || [ -n "$USE_CRYPT" ]); then
		mkdir -p "$SYSROOT"/boot
		mount -t $BOOTFS $boot_dev "$SYSROOT"/boot || return 1
	fi
	if [ -n "$boot_dev" ] && [ -n "$USE_EFI" ]; then
	if [ -n "$boot_dev" ] && [ -n "$USE_EFI" ] && [ -z "$USE_CRYPT" ]; then
		mkdir -p "$SYSROOT"/boot/efi
		mount -t $BOOTFS $boot_dev "$SYSROOT"/boot/efi || return 1
	fi
@@ -1082,6 +1123,18 @@ native_disk_install_lvm() {
	setup_root $root_dev $BOOT_DEV
}

setup_crypt() {
	local dev="$1" local dmname="$2"
	mkdir -p /run/cryptsetup
	echo "Preparing root partition for encryption." >&2
	echo "You will be prompted for your password at boot." >&2
	echo "If you forget your password, your data will be lost." >&2
	cryptsetup luksFormat --type luks2 "$dev" >&2
	echo "Enter password again to unlock disk for installation." >&2
	cryptsetup open "$dev" "$dmname" >&2
	echo "/dev/mapper/$dmname"
}

native_disk_install() {
	local prep_part_type=$(partition_id prep)
	local root_part_type=$(partition_id linux)
@@ -1156,6 +1209,10 @@ native_disk_install() {
		root_dev=$(find_nth_non_boot_parts $index "$root_part_type" $@)
	fi

	if [ "$USE_CRYPT" ]; then
		root_dev=$(setup_crypt $root_dev root)
	fi

	[ $SWAP_SIZE -gt 0 ] && setup_swap_dev $swap_dev
	setup_root $root_dev $BOOT_DEV $@
}
@@ -1176,7 +1233,7 @@ diskselect_help() {
diskmode_help() {
	cat <<-__EOF__

		You can select between 'sys', 'data', 'lvm', 'lvmsys' or 'lvmdata'.
		You can select between 'sys', 'cryptsys', 'data', 'lvm', 'lvmsys' or 'lvmdata'.

		sys:
		  This mode is a traditional disk install. The following partitions will be
@@ -1184,6 +1241,12 @@ diskmode_help() {

		  This mode may be used for development boxes, desktops, virtual servers, etc.

		cryptsys:
		  This mode is equivalent to sys, except that the root filesystem will be
		  encrypted with cryptsetup. You will be prompted to enter a decryption
		  password, and will need to use this password to boot up the operating
		  system after installation.

		data:
		  This mode uses your disk(s) for data storage, not for the operating system.
		  The system itself will run from tmpfs (RAM).
@@ -1233,7 +1296,7 @@ ask_disk() {

usage() {
	cat <<-__EOF__
		usage: setup-disk [-hLqrv] [-k kernelflavor] [-m MODE] [-o apkovl] [-s SWAPSIZE]
		usage: setup-disk [-hLqrve] [-k kernelflavor] [-m MODE] [-o apkovl] [-s SWAPSIZE]
		                  [MOUNTPOINT | DISKDEV...]

		Install alpine on harddisk.
@@ -1247,6 +1310,7 @@ usage() {

		options:
		 -h  Show this help
		 -e  Encrypt disk
		 -m  Use disk for MODE without asking, where MODE is either 'data' or 'sys'
		 -o  Restore system from given apkovl file
		 -k  Use kernelflavor instead of $KERNEL_FLAVOR
@@ -1286,11 +1350,13 @@ case $kver in
	*) KERNEL_FLAVOR=lts;;
esac

USE_CRYPT=
DISK_MODE=
USE_LVM=
# Parse args
while getopts "hk:Lm:o:qrs:v" opt; do
while getopts "hek:Lm:o:qrs:v" opt; do
	case $opt in
		e) USE_CRYPT=1;;
		m) DISK_MODE="$OPTARG";;
		k) KERNEL_FLAVOR="$OPTARG";;
		L) USE_LVM="_lvm";;
@@ -1319,6 +1385,12 @@ fi
reset_var
swapoff -a

if [ $USE_CRYPT -eq 1 ] && [ -n "$USE_LVM" ]; then
	echo "cryptsys and lvm are currently mutually incompatible."
	echo "Please run $0 again with only one of these options selected."
	exit 1
fi

# stop all volume groups in use
vgchange --ignorelockingfailure -a n >/dev/null 2>&1

@@ -1381,9 +1453,14 @@ if [ -n "$diskdevs" ] && [ -z "$DISK_MODE" ]; then
		echo "The following $disk_is_or_disks_are selected${USE_LVM:+ (with LVM)}:"
		show_disk_info $diskdevs
		_lvm=${USE_LVM:-", 'lvm'"}
		ask "How would you like to use $it_them? ('sys', 'data'${_lvm#_lvm} or '?' for help)" "?"
		ask "How would you like to use $it_them? ('sys', 'cryptsys', 'data'${_lvm#_lvm} or '?' for help)" "?"
		case "$resp" in
		'?') diskmode_help;;
		cryptsys)
			resp=sys
			USE_CRYPT=1
			break
			;;
		sys|data) break;;
		lvm) USE_LVM="_lvm" ;;
		nolvm) USE_LVM="";;
-- 
2.32.0
Details
Message ID
<CEO8ZQHLY4SN.3UPI2TMBB02BQ@taiga>
In-Reply-To
<20210814191142.11043-1-krystian@krystianch.com> (view parent)
DKIM signature
missing
Download raw message
Some feedback from ncopa:

From: Natanael Copa <ncopa@alpinelinux.org>
To: Krystian Chachu*a <krystian@krystianch.com>
Cc: ~alpine/devel@lists.alpinelinux.org, Drew DeVault <sir@cmpwn.com>
Subject: Re: [PATCH alpine-conf v8] Support encrypted root in setup-disk
Date: Fri, 1 Oct 2021 18:40:51 +0200
X-Mailer: Claws Mail 4.0.0 (GTK+ 3.24.30; x86_64-alpine-linux-musl)

Hi!

Thank you for working on this.

On Sat, 14 Aug 2021 21:11:42 +0200
Krystian Chachuła <krystian@krystianch.com> wrote:

> Co-authored-by: Drew DeVault <sir@cmpwn.com>
> ---
> Major changes since v7 are:
> * setup_grub and setup_root: when using EFI and encryption, the boot
>   partition is unencrypted and mounted to /boot instead of /boot/efi
>   (like current behavior with syslinux); this solves two issues: setting
>   up GRUB with luks2 encrypted /boot is difficult, installing GRUB with
>   encrypted /boot needs chroot or a workaround (see v7 discussion)  

I think it would be nice with an explanation in the commit message why
it is done this way.

> * install_mounted_root: cryptroot kernel param is now set to UUID
>   instead of device name
> * init_progs: blkid is explicitly installed, because crypt_required
>   needs it
> 
> I tested sys and cryptsys installation with syslinux/BIOS,
> GRUB/BIOS and GRUB/EFI on x86_64.  

great! thanks!
> 
> See
> https://git.sr.ht/~krystianch/alpine-conf/commit/70aaffca3d4685f3a8d78deaca7b479521b13ab8
> for full diff between v7 and v8.
> 
> I'd appreciate a review / feedback.
> 
>  setup-disk.in | 135 +++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 106 insertions(+), 29 deletions(-)
> 
> diff --git a/setup-disk.in b/setup-disk.in
> index 656b5bc..46c8068 100644
> --- a/setup-disk.in
> +++ b/setup-disk.in
> @@ -82,6 +82,26 @@ enumerate_fstab() {
>  		done
>  }
>  
> +# given an fstab on stdin, determine if any of the mountpoints are encrypted
> +crypt_required() {
> +	while read -r devname mountpoint fstype mntops freq passno; do
> +		if [ -z "$devname" ] || [ "${devname###}" != "$devname" ]; then
> +			continue
> +		fi
> +		uuid="${devname##UUID=}"
> +		if [ "$uuid" != "$devname" ]; then
> +			devname="$(blkid --uuid "$uuid")"
> +		fi
> +		mapname="${devname##/dev/mapper/}"
> +		if [ "$mapname" != "$devname" ]; then
> +			if cryptsetup status "$mapname" >&1 >/dev/null; then
> +				return 0
> +			fi
> +		fi
> +	done
> +	return 1
> +}
> +
>  is_vmware() {
>  	grep -q VMware /proc/scsi/scsi 2>/dev/null \
>  		|| grep -q VMware /proc/ide/hd*/model 2>/dev/null
> @@ -283,19 +303,23 @@ setup_grub() {
>  	# install GRUB efi mode
>  	if [ -n "$USE_EFI" ]; then
>  		local target fwa
> +		local efi_directory="$mnt"/boot/efi
>  		case "$ARCH" in
>  			x86_64)		target=x86_64-efi ; fwa=x64 ;;
>  			x86)		target=i386-efi ; fwa=ia32 ;;
>  			arm*)		target=arm-efi ; fwa=arm ;;
>  			aarch64)	target=arm64-efi ; fwa=aa64 ;;
>  		esac
> +		if [ -n "$USE_CRYPT" ]; then
> +			efi_directory="$mnt"/boot
> +		fi
>  		# currently disabling nvram so grub doesnt call efibootmgr
>  		# installing to alpine directory so other distros dont overwrite it
> -		grub-install --target=$target --efi-directory="$mnt"/boot/efi \
> +		grub-install --target=$target --efi-directory="$efi_directory" \
>  			--bootloader-id=alpine --boot-directory="$mnt"/boot --no-nvram
>  		# fallback mode will use boot/boot${fw arch}.efi
> -		install -D "$mnt"/boot/efi/EFI/alpine/grub$fwa.efi \
> -			"$mnt"/boot/efi/EFI/boot/boot$fwa.efi
> +		install -D "$efi_directory"/EFI/alpine/grub$fwa.efi \
> +			"$efi_directory"/EFI/boot/boot$fwa.efi
>  	# install GRUB for ppc64le
>  	elif [ "$ARCH" = "ppc64le" ]; then
>  		shift 5
> @@ -427,7 +451,7 @@ setup_raspberrypi_bootloader() {
>  install_mounted_root() {
>  	local mnt="$1"
>  	shift 1
> -	local disks="${@}" mnt_boot= boot_fs= root_fs=
> +	local disks="${@}" mnt_boot= boot_fs= root_fs= use_crypt=
>  	local initfs_features="ata base ide scsi usb virtio"
>  	local pvs= dev= rootdev= bootdev= extlinux_raidopt= root= modules=
>  	local kernel_opts="$KERNELOPTS"
> @@ -490,7 +514,6 @@ install_mounted_root() {
>  		esac
>  	done
>  
> -
>  	if [ -n "$VERBOSE" ]; then
>  		echo "Root device:     $rootdev"
>  		echo "Root filesystem: $root_fs"
> @@ -513,6 +536,28 @@ install_mounted_root() {
>  	# we should not try start modloop on sys install
>  	rm -f "$mnt"/etc/runlevels/*/modloop
>  
> +	# generate the fstab
> +	if [ -f "$mnt"/etc/fstab ]; then
> +		mv "$mnt"/etc/fstab "$mnt"/etc/fstab.old
> +	fi
> +	enumerate_fstab "$mnt" >> "$mnt"/etc/fstab
> +	if [ -n "$SWAP_DEVICES" ]; then
> +		local swap_dev
> +		for swap_dev in $SWAP_DEVICES; do
> +			echo -e "$(uuid_or_device ${swap_dev})\tswap\tswap\tdefaults\t0 0" \
> +				>> "$mnt"/etc/fstab
> +		done
> +	fi
> +	cat >>"$mnt"/etc/fstab <<-__EOF__
> +		/dev/cdrom	/media/cdrom	iso9660	noauto,ro 0 0
> +		/dev/usbdisk	/media/usb	vfat	noauto	0 0
> +	__EOF__
> +
> +	if crypt_required <"$mnt"/etc/fstab; then
> +		use_crypt=1
> +		initfs_features="$initfs_features cryptsetup"
> +	fi
> +
>  	# generate mkinitfs.conf
>  	mkdir -p "$mnt"/etc/mkinitfs/features.d
>  	echo "features=\"$initfs_features\"" > "$mnt"/etc/mkinitfs/mkinitfs.conf
> @@ -530,24 +575,15 @@ install_mounted_root() {
>  	if [ -n "$(get_bootopt nomodeset)" ]; then
>  		kernel_opts="nomodeset $kernel_opts"
>  	fi
> +	if [ "$use_crypt" ] && cryptsetup status "$rootdev" 2>&1 >/dev/null; then
> +		# Boot to encrypted root
> +		root=$(cryptsetup status "$rootdev" | awk '/device:/ { print $2 }')
> +		root=$(uuid_or_device $root)
> +		kernel_opts="cryptroot=$root cryptdm=root"
> +		root=/dev/mapper/root
> +	fi
>  	modules="sd-mod,usb-storage,${root_fs}${raidmod}"
>  
> -	# generate the fstab
> -	if [ -f "$mnt"/etc/fstab ]; then
> -		mv "$mnt"/etc/fstab "$mnt"/etc/fstab.old
> -	fi
> -	enumerate_fstab "$mnt" >> "$mnt"/etc/fstab
> -	if [ -n "$SWAP_DEVICES" ]; then
> -		local swap_dev
> -		for swap_dev in $SWAP_DEVICES; do
> -			echo -e "$(uuid_or_device ${swap_dev})\tswap\tswap\tdefaults\t0 0" \  
> -				>> "$mnt"/etc/fstab    
> -		done
> -	fi
> -	cat >>"$mnt"/etc/fstab <<-__EOF__
> -		/dev/cdrom	/media/cdrom	iso9660	noauto,ro 0 0
> -		/dev/usbdisk	/media/usb	vfat	noauto	0 0
> -	__EOF__
>  	# remove the installed db in case its there so we force re-install
>  	rm -f "$mnt"/var/lib/apk/installed "$mnt"/lib/apk/db/installed
>  	echo "Installing system on $rootdev:"
> @@ -595,6 +631,10 @@ unmount_partitions() {
>  
>  	# unmount the partitions
>  	umount $(awk '{print $2}' /proc/mounts | egrep "^$mnt(/|\$)" | sort -r)
> +
> +	if [ "$USE_CRYPT" ]; then
> +		cryptsetup close /dev/mapper/root
> +	fi
>  }
>  
>  # figure out decent default swap size in mega bytes
> @@ -697,9 +737,10 @@ select_bootloader_pkg() {
>  
>  # install needed programs
>  init_progs() {
> -	local raidpkg= lvmpkg= fs= fstools= grub=
> +	local raidpkg= lvmpkg= cryptpkg= fs= fstools= grub=
>  	[ -n "$USE_RAID" ] && raidpkg="mdadm"
>  	[ -n "$USE_LVM" ] && lvmpkg="lvm2"
> +	[ -n "$USE_CRYPT" ] && cryptpkg="cryptsetup blkid"
>  	for fs in $BOOTFS $ROOTFS $VARFS; do
>  		# we need load btrfs module early to avoid the error message:
>  		# 'failed to open /dev/btrfs-control'
> @@ -714,7 +755,7 @@ init_progs() {
>  		vfat) fstools="$fstools dosfstools";;
>  		esac
>  	done
> -	apk add --quiet sfdisk $lvmpkg $raidpkg $fstools $@
> +	apk add --quiet sfdisk $cryptpkg $lvmpkg $raidpkg $fstools $@
>  }
>  
>  show_disk_info() {
> @@ -1018,11 +1059,11 @@ setup_root() {
>  	mkfs.$ROOTFS $MKFS_OPTS_ROOT $mkfs_args "$root_dev"
>  	mkdir -p "$SYSROOT"
>  	mount -t $ROOTFS $root_dev "$SYSROOT" || return 1
> -	if [ -n "$boot_dev" ] && [ -z "$USE_EFI" ]; then
> +	if [ -n "$boot_dev" ] && ([ -z "$USE_EFI" ] || [ -n "$USE_CRYPT" ]); then
>  		mkdir -p "$SYSROOT"/boot
>  		mount -t $BOOTFS $boot_dev "$SYSROOT"/boot || return 1
>  	fi
> -	if [ -n "$boot_dev" ] && [ -n "$USE_EFI" ]; then
> +	if [ -n "$boot_dev" ] && [ -n "$USE_EFI" ] && [ -z "$USE_CRYPT" ]; then
>  		mkdir -p "$SYSROOT"/boot/efi
>  		mount -t $BOOTFS $boot_dev "$SYSROOT"/boot/efi || return 1
>  	fi
> @@ -1082,6 +1123,18 @@ native_disk_install_lvm() {
>  	setup_root $root_dev $BOOT_DEV
>  }
>  
> +setup_crypt() {
> +	local dev="$1" local dmname="$2"
> +	mkdir -p /run/cryptsetup
> +	echo "Preparing root partition for encryption." >&2
> +	echo "You will be prompted for your password at boot." >&2
> +	echo "If you forget your password, your data will be lost." >&2
> +	cryptsetup luksFormat --type luks2 "$dev" >&2
> +	echo "Enter password again to unlock disk for installation." >&2
> +	cryptsetup open "$dev" "$dmname" >&2  

What happens if user provides wrong password to `cryptsetup open` in
setup_crypt? Shouldn't we handle error here?

> +	echo "/dev/mapper/$dmname"
> +}
> +
>  native_disk_install() {
>  	local prep_part_type=$(partition_id prep)
>  	local root_part_type=$(partition_id linux)
> @@ -1156,6 +1209,10 @@ native_disk_install() {
>  		root_dev=$(find_nth_non_boot_parts $index "$root_part_type" $@)
>  	fi
>  
> +	if [ "$USE_CRYPT" ]; then
> +		root_dev=$(setup_crypt $root_dev root)  

What should happen here if `cryptsetup open` failed?

> +	fi
> +
>  	[ $SWAP_SIZE -gt 0 ] && setup_swap_dev $swap_dev
>  	setup_root $root_dev $BOOT_DEV $@
>  }
> @@ -1176,7 +1233,7 @@ diskselect_help() {
>  diskmode_help() {
>  	cat <<-__EOF__
>  
> -		You can select between 'sys', 'data', 'lvm', 'lvmsys' or 'lvmdata'.
> +		You can select between 'sys', 'cryptsys', 'data', 'lvm', 'lvmsys' or 'lvmdata'.
>  
>  		sys:
>  		  This mode is a traditional disk install. The following partitions will be
> @@ -1184,6 +1241,12 @@ diskmode_help() {
>  
>  		  This mode may be used for development boxes, desktops, virtual servers, etc.
>  
> +		cryptsys:
> +		  This mode is equivalent to sys, except that the root filesystem will be
> +		  encrypted with cryptsetup. You will be prompted to enter a decryption
> +		  password, and will need to use this password to boot up the operating
> +		  system after installation.
> +
>  		data:
>  		  This mode uses your disk(s) for data storage, not for the operating system.
>  		  The system itself will run from tmpfs (RAM).
> @@ -1233,7 +1296,7 @@ ask_disk() {
>  
>  usage() {
>  	cat <<-__EOF__
> -		usage: setup-disk [-hLqrv] [-k kernelflavor] [-m MODE] [-o apkovl] [-s SWAPSIZE]
> +		usage: setup-disk [-hLqrve] [-k kernelflavor] [-m MODE] [-o apkovl] [-s SWAPSIZE]
>  		                  [MOUNTPOINT | DISKDEV...]
>  
>  		Install alpine on harddisk.
> @@ -1247,6 +1310,7 @@ usage() {
>  
>  		options:
>  		 -h  Show this help
> +		 -e  Encrypt disk
>  		 -m  Use disk for MODE without asking, where MODE is either 'data' or 'sys'
>  		 -o  Restore system from given apkovl file
>  		 -k  Use kernelflavor instead of $KERNEL_FLAVOR
> @@ -1286,11 +1350,13 @@ case $kver in
>  	*) KERNEL_FLAVOR=lts;;
>  esac
>  
> +USE_CRYPT=
>  DISK_MODE=
>  USE_LVM=
>  # Parse args
> -while getopts "hk:Lm:o:qrs:v" opt; do
> +while getopts "hek:Lm:o:qrs:v" opt; do
>  	case $opt in
> +		e) USE_CRYPT=1;;
>  		m) DISK_MODE="$OPTARG";;
>  		k) KERNEL_FLAVOR="$OPTARG";;
>  		L) USE_LVM="_lvm";;
> @@ -1319,6 +1385,12 @@ fi
>  reset_var
>  swapoff -a
>  
> +if [ $USE_CRYPT -eq 1 ] && [ -n "$USE_LVM" ]; then
> +	echo "cryptsys and lvm are currently mutually incompatible."
> +	echo "Please run $0 again with only one of these options selected."
> +	exit 1
> +fi
> +  

I wonder how much extra work it would be to add support for encrypted
disk under lvm?

>  # stop all volume groups in use
>  vgchange --ignorelockingfailure -a n >/dev/null 2>&1
>  
> @@ -1381,9 +1453,14 @@ if [ -n "$diskdevs" ] && [ -z "$DISK_MODE" ]; then
>  		echo "The following $disk_is_or_disks_are selected${USE_LVM:+ (with LVM)}:"
>  		show_disk_info $diskdevs
>  		_lvm=${USE_LVM:-", 'lvm'"}
> -		ask "How would you like to use $it_them? ('sys', 'data'${_lvm#_lvm} or '?' for help)" "?"
> +		ask "How would you like to use $it_them? ('sys', 'cryptsys', 'data'${_lvm#_lvm} or '?' for help)" "?"
>  		case "$resp" in
>  		'?') diskmode_help;;
> +		cryptsys)
> +			resp=sys
> +			USE_CRYPT=1
> +			break
> +			;;  

What would be needed to be able to select 'crypt' and then select
either 'sys' or 'data'? similar to what we do with lvm. So we could
have data on cryptsetup as well.

>  		sys|data) break;;
>  		lvm) USE_LVM="_lvm" ;;
>  		nolvm) USE_LVM="";;
Krystian Chachuła <krystian@krystianch.com>
Details
Message ID
<CEVX59MUE9QH.342GEHM50UU3N@userpc>
In-Reply-To
<CEO8ZQHLY4SN.3UPI2TMBB02BQ@taiga> (view parent)
DKIM signature
missing
Download raw message
Thank you Natanael for the review.

On Fri Oct 1, 2021 at 6:40 PM CEST, Natanael Copa wrote:
> > * setup_grub and setup_root: when using EFI and encryption, the boot
> >   partition is unencrypted and mounted to /boot instead of /boot/efi
> >   (like current behavior with syslinux); this solves two issues: setting
> >   up GRUB with luks2 encrypted /boot is difficult, installing GRUB with
> >   encrypted /boot needs chroot or a workaround (see v7 discussion)  
>
> I think it would be nice with an explanation in the commit message why
> it is done this way.

Ok, I'll address it in v9.

> What happens if user provides wrong password to `cryptsetup open` in
> setup_crypt? Shouldn't we handle error here?

I'd add `--tries 1` to make `cryptsetup open` exit on wrong password and prompt
user what to do:

Could not unlock disk: [REASON FROM EXIT CODE]. What would you like to do?
('retry', 'reformat', 'skip' or '?' for help)

Help would say:

You can select between 'retry', 'reformat', or 'skip'.

retry:
  Try unlocking disk again.

reformat:
  Discard current password and set a new one.

skip:
  Continue without encrypting the root partition.

> >  native_disk_install() {
> >  	local prep_part_type=$(partition_id prep)
> >  	local root_part_type=$(partition_id linux)
> > @@ -1156,6 +1209,10 @@ native_disk_install() {
> >  		root_dev=$(find_nth_non_boot_parts $index "$root_part_type" $@)
> >  	fi
> >  
> > +	if [ "$USE_CRYPT" ]; then
> > +		root_dev=$(setup_crypt $root_dev root)  
>
> What should happen here if `cryptsetup open` failed?

I'd make `setup_crypt` echo nothing when user skips encryption and, if it
happens, skip overwriting `root_dev` here.

> I wonder how much extra work it would be to add support for encrypted
> disk under lvm?

I'd say not that much. For LVM on LUKS:

(1) `native_disk_install_lvm` would need to call `setup_crypt` to create
	`/dev/mapper/cryptlvm` before `setup_lvm_volume_group` and
(2) `setup_lvm_volume_group` would need to set up LVM on `/dev/mapper/cryptlvm`.

If this looks ok I'll implement this in v9.

> What would be needed to be able to select 'crypt' and then select
> either 'sys' or 'data'? similar to what we do with lvm. So we could
> have data on cryptsetup as well.

I think we need an init script that runs before localmount and opens the
encrypted var partition by asking for password interactively.
Reply to thread Export thread (mbox)