So I’d like to preface that I am not an expert in OS development and have limited working knowledge when it comes to disk and filesystem maintenance. I am first and foremost a tinkerer and a full stack developer. I’ve been running Umbrel for close to 3 years now, I started with a Raspberry Pi and eventually upgraded to a Dell Poweredge T40, up until release of 1.0.0 I have been running Umbrel on Ubuntu.
I’ve upgraded to 1.1.2 recently but one of the biggest drawbacks has been how it has completely ruined my storage configuration.
I have multiple drives, but as it currently stands Umbrel only has access to one.
One solution would be to utilize LVM to create a volume group and add the physical disk that was selected during installation. This way additional physical disks can be added to the volume group and extended and the file system can be resized.
I did some digging through the source code, it seems this could be done in the build_x86_artifacts()
function.
I’ll post the suggested changes, but I should note I have not tested this. I dont know how I would go about doing so, I assume I would need to fork the repository, make the changes, build the ISO image, flash it, then attempt to install it with the changes to confirm it works as expected. But what I’m not sure about how to do would be building the ISO image. If anyone could explain how to do so, I would gladly test it and submit a PR.
But before going that far, I wanted to post here and start a discussion. Do these changes make sense? Is there a better approach? Security concerns? Please feel free to contribute any thoughts.
Here is the suggested changes to build_x86_artifacts()
# Build the x86 artifacts.
function build_x86_artifacts() {
echo "Creating disk image..."
rootfs_tar_size="$(du --block-size 1M /data/build/umbrelos-amd64.tar | awk '{print $1}')"
rootfs_buffer="1024"
disk_size_mb="$((rootfs_tar_size + rootfs_buffer))"
disk_size_sector=$(expr $disk_size_mb \* 1024 \* 1024 / 512)
disk_image="/tmp/disk.img"
dd if=/dev/zero of="${disk_image}" bs=512 count="${disk_size_sector}"
echo "Creating disk partitions..."
gpt_efi="ef00"
gpt_root_amd64="8e00" # LVM partition type code
sgdisk \
--new 1:2048:+200M \
--typecode 1:"${gpt_efi}" \
--change-name 1:ESP \
--new 2:0:0 \
--typecode 2:"${gpt_root_amd64}" \
--change-name 2:ROOTFS \
"${disk_image}"
disk_layout=$(fdisk -l "${disk_image}")
echo "${disk_layout}"
echo "Attaching partitions to loopback devices..."
efi_start=$(echo "${disk_layout}" | grep EFI | awk '{print $2}')
efi_size=$(echo "${disk_layout}" | grep EFI | awk '{print $4}')
root_start=$(echo "${disk_layout}" | grep ROOTFS | awk '{print $2}')
root_size=$(echo "${disk_layout}" | grep ROOTFS | awk '{print $4}')
efi_device=$(losetup --offset $((512*efi_start)) --sizelimit $((512*efi_size)) --show --find "${disk_image}")
root_device=$(losetup --offset $((512*root_start)) --sizelimit $((512*root_size)) --show --find "${disk_image}")
echo "Formatting partitions..."
mkfs.vfat -n "ESP" "${efi_device}"
# Do not format root_device yet, it will be used for LVM
echo "Creating LVM volume group and logical volume..."
pvcreate "${root_device}"
vgcreate vg0 "${root_device}"
lvcreate -l 100%FREE -n lv_root vg0
echo "Formatting logical volume..."
mkfs.ext4 -L "ROOTFS" /dev/vg0/lv_root
echo "Mounting partitions..."
efi_mount_point="/mnt/efi"
root_mount_point="/mnt/root"
mkdir -p "${efi_mount_point}"
mkdir -p "${root_mount_point}"
mount "${efi_device}" "${efi_mount_point}"
mount /dev/vg0/lv_root "${root_mount_point}"
echo "Extracting rootfs..."
tar -xf /data/build/umbrelos-amd64.tar --directory "${root_mount_point}"
echo "Setup hostname..."
# We need to do this here because if we do it in the Dockerfile it gets
# clobbered when Docker sets a random hostname during `docker run`. If
# you copy any additional files here, please also do so in Rugpi.
overlay_dir="/data/overlay-common"
cp "${overlay_dir}/etc/hostname" "${root_mount_point}/etc/hostname"
cp "${overlay_dir}/etc/hosts" "${root_mount_point}/etc/hosts"
echo "Remove .dockerenv..."
# We also need to remove this to prevent the system from being detected as a container
rm "${root_mount_point}/.dockerenv"
echo "Copying boot directory over to ESP partition..."
cp -r "${root_mount_point}/boot/." "${efi_mount_point}"
tree "${efi_mount_point}"
echo
echo "Unmounting partitions..."
umount "${root_mount_point}"
umount "${efi_mount_point}"
echo "Detaching loopback devices..."
losetup --detach "${efi_device}"
losetup --detach "${root_device}"
echo "Disk image created!"
echo "Running disk image through mender-convert..."
cd /mender
/mender/mender-convert --disk-image "${disk_image}" --config /data/mender.cfg
echo "Copying to ./build/..."
mv /mender/deploy/umbrelos.mender /data/build/umbrelos-amd64.update
mv /mender/deploy/umbrelos.img /data/build/umbrelos-amd64.img
}