diff --git a/kas/opt/expand-on-first-boot.yml b/kas/opt/expand-on-first-boot.yml
index 03d666b2..f5be6992 100644
--- a/kas/opt/expand-on-first-boot.yml
+++ b/kas/opt/expand-on-first-boot.yml
@@ -15,3 +15,6 @@ header:
 local_conf_header:
   package-expand-on-first-boot: |
     IMAGE_INSTALL:append = " expand-on-first-boot"
+  expand-before-encrypt: |
+    IMAGE_INSTALL:remove:encrypt-partitions = "expand-on-first-boot"
+    CRYPT_PARTITIONS:append:encrypt-partitions = ":expand"
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index 28548502..834dea22 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -95,6 +95,64 @@ EOF
 		/usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "$reduce_device_size"k "$1" < "$2"
 	fi
 }
+
+expand_partition() {
+	boot_device="$(echo "${part_device}" | sed 's/p\?[0-9]*$//')"
+	last_part="$(sfdisk -d "${boot_device}" 2>/dev/null | \
+		     tail -1 | cut -d ' ' -f 1)"
+	if [ "$last_part" != "$1" ]; then
+		log_warning_msg "To be expanded partition is not last - skipping expansion"
+		return
+	fi
+
+	buffer_size=32768
+	boot_device_name=${boot_device##*/}
+	disk_size="$(cat /sys/class/block/"${boot_device_name}"/size)"
+	all_parts_size=0
+	for partition in /sys/class/block/"${boot_device_name}"/"${boot_device_name}"*; do
+		part_size=$(cat "${partition}"/size)
+		all_parts_size=$((all_parts_size + part_size))
+	done
+
+	minimal_size=$((all_parts_size + buffer_size))
+	if [ "$disk_size" -lt "$minimal_size" ]; then
+		return
+	fi
+
+	log_begin_msg "Expanding partition $last_part"
+
+	is_gpt="$(sfdisk -d "${boot_device}" 2>/dev/null | grep -q "label: gpt" \
+		  && echo 1 || echo 0)"
+	if [ "$is_gpt" = "1" ]; then
+		dd if="${boot_device}" of=/tmp/__mbr__.bak count=1 >/dev/null 2>&1
+	fi
+
+	# Transform the partition table as follows:
+	#
+	# - Remove any 'last-lba' header so sfdisk uses the entire available
+	#   space.
+	# - If this partition table is MBR and an extended partition container
+	#   (EBR) exists, we assume this needs to be expanded as well; remove
+	#   its size field so sfdisk expands it.
+	# - For the previously fetched last partition, also remove the size
+	#   field so sfdisk expands it.
+	sfdisk -d "${boot_device}" 2>/dev/null | \
+		grep -v last-lba | \
+		sed 's|^\(.*, \)size=[^,]*, \(type=[f5]\)$|\1\2|' | \
+		sed 's|^\('"${last_part}"' .*, \)size=[^,]*, |\1|' | \
+		sfdisk --force "${boot_device}" >/dev/null 2>&1
+
+	if [ "$is_gpt" = "1" ]; then
+		dd if=/tmp/__mbr__.bak of="${boot_device}" >/dev/null 2>&1
+		rm /tmp/__mbr__.bak
+	fi
+
+	# Inform the kernel about the partitioning change
+	partx -u "${last_part}"
+
+	log_end_msg
+}
+
 for candidate in /dev/tpm*; do
 	if [ -x /usr/bin/tpm2_pcrread ]; then
 		if ! tpm2_pcrread -T device:"$candidate" "$pcr_bank_hash_type":7 --quiet ; then
@@ -129,6 +187,7 @@ for partition_set in $partition_sets; do
 	partition="$(awk -v var="$partition_set" 'BEGIN{split(var,a,":"); print a[1]}')"
 	partition_mountpoint="$(awk -v var="$partition_set" 'BEGIN{split(var,a,":"); print a[2]}')"
 	partition_format="$(awk -v var="$partition_set" 'BEGIN{split(var,a,":"); print a[3]}')"
+	partition_expand="$(awk -v var="$partition_set" 'BEGIN{split(var,a,":"); print a[4]}')"
 	case "$partition" in
 		/*)
 			part_device=$(readlink -f "$partition")
@@ -153,6 +212,10 @@ for partition_set in $partition_sets; do
 		echo "ROOT=$decrypted_part" >/conf/param.conf
 	fi
 
+	if [ "$partition_expand" = "expand" ]; then
+		expand_partition $part_device
+	fi
+
 	if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \
 			| grep -q "luks2"; then
 		open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device"
diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.5.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.5.bb
index 6ff315ed..71ee44db 100644
--- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.5.bb
+++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.5.bb
@@ -69,7 +69,7 @@ SRC_URI += "file://encrypt_partition.env.tmpl \
             file://hook \
             file://pwquality.conf"
 
-# CRYPT_PARTITIONS elements are <partition-label>:<mountpoint>:<reencrypt or format>
+# CRYPT_PARTITIONS elements are <partition-label>:<mountpoint>:<reencrypt or format>[:expand]
 CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt"
 # CRYPT_CREATE_FILE_SYSTEM_CMD contains the shell command to create the filesystem
 # in a newly formatted LUKS Partition
@@ -88,6 +88,10 @@ TEMPLATE_VARS += "CRYPT_PARTITIONS CRYPT_CREATE_FILE_SYSTEM_CMD \
     CRYPT_KEY_ALGORITHM CRYPT_ENCRYPTION_OPTIONAL"
 TEMPLATE_FILES += "encrypt_partition.env.tmpl"
 
+OVERRIDES .= "${@':expand-on-crypt' if ':expand' in d.getVar('CRYPT_PARTITIONS') else ''}"
+DEBIAN_DEPENDS:append:expand-on-crypt = ", fdisk, util-linux"
+HOOK_COPY_EXECS:append:expand-on-crypt = " sed sfdisk tail cut dd partx rm"
+
 do_install[cleandirs] += "${D}/usr/share/encrypt_partition"
 do_install:prepend() {
     install -m 0600 "${WORKDIR}/encrypt_partition.env" "${D}/usr/share/encrypt_partition/encrypt_partition.env"
