Since forever I run my work computer operating systems on a full-disk-encrypted partition. Currently this is Manjaro Linux. When I set up my current machine I made the following partition scheme:
sda 238,5G disk
├─sda1 260M part /boot/efi
├─sda2 128M part /boot
└─sda3 237G part
└─tank 237G crypt
Somewhere, I can't even remember when, I read that 128M for
/boot would be sufficient. And it was for a few years. But kernel images and/or initram disks grew bigger and bigger until I could not upgrade to a newer kernel anymore. The last kernel I ran was Linux 4.16 and the files in
/boot took around 75M space and so
mhwd-kernel -i linux417 had too little space on the device left.
What I needed to do was to shrink
/dev/sda3, move it to the end of the SSD and grow
/dev/sda2 as necessary.
But I did not know if this was even possible with my setup. Inside the encrypted partition there is an LVM container with 5 logical volumes including
/. I pushed it into the future again and again because most of the time I am working in running projects and can not afford to have a non-functioning machine for <absurd amount of time that you never expect before a hardware near change>.
But in the end it was relatively easy. I had feared that in the worst case I would have to re-setup my whole machine and restore backups for the data and system partitions. Which then maybe would need endless tweaking until it runs again (No, I never had a hard disk failure or similar, so I never had to actually do anything like that).
So, here are the things I needed to do:
List all logcal volumes:
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
docker tank -wi-ao---- 5,00g
home tank -wi-ao---- 100,00g
mongo tank -wi-ao---- 1,00g
root tank -wi-ao---- 25,00g
swap tank -wc-ao---- 32,00g
For each lv do the following:
# lvcreate -s -n <name>snap /dev/tank/<name>
# dd if=/dev/tank/<name>snap of=/path/to/external/storage/<name>.img
<name> must be replaced by the actual names of the lvs. Then I backed up both the
/boot and the
/boot/efi partitions, also with
Finally I made a backup of the LUKS header for the crypto-partition:
# cryptsetup luksHeaderBackup /dev/sda3 --header-backup-file /path/to/external/storage/luks-header.bkp
2. Boot in a live system from an USB stick and decrypt the device
# cryptsetup open /dev/sda3 tank --type luks
3. Resize the physical volume
Note: I have free space inside my LVM container. As you can see from the output of
lvs above I currently use only 143GB out of roughly 238GB. That means I do not have to resize logical volumes before I resize the containing physical volume. If you use all of the available space for logical volumes, look into
lvresize(8) first: For example in the Arch Wiki.
I generously shrank the volume from 238,07G to 236G with:
# pvresize --setphysicalvolumesize 236G /dev/mapper/tank
4. Resize the crypto-device
Find out how many sectors is the current size (note that my crypto-device has the same name like my volume group:
tank. That could be different in your setup):
# cryptsetup status tank
sector size: 512
In the end I want to add about 1G to the
/boot partition. That is
1024 * 1024 * 1024 / 512 = 2097152 sectors.
# cryptsetup -b 497025024 resize tank
5. Resize the GUID partition
You see we go from innermost to outermost: LVM -> crypto -> GUID. I use
parted to resize the partition
(parted) unit s
Number Begin End Size Name Flags
3 3100672s 500115455s 497014784s TANK lvm
These numbers were actually different as I write this blog post in hindsight. The point is that partition number 3 went all the way to the last sector of the disk and I now must calculate where it should end in the future. Because
resizepart takes not the future size but the future end sector of the partition as argument. So I subtract the same sector count as calculated above for cryptsetup (
2097152) from the end sector of partition 3 (
500115455) which gives
(parted) resizepart 3 498018303s
Now we have free space on the SSD after the main partition. But I want to grow partition 2.
6. Reorder partitions and resize partition 2
I did that with GParted instead of a command line tool. Probably there is a way to do it with
parted has removed its command to
move partitions. And because I was in a graphical live system anyway and also read that you could do it with GParted I just went for it.
First I closed the crypto device because GParted would not let me move the partition otherwise:
# vgchange -an tank
# cryptsetup close tank
Then I opened GParted and right-clicked on the crypto partition. I chose "Change size|Move" and moved the free space after the partition before it. Then I opend the same dialog for the
/boot partition and extended it to cover all of the free space. Finally I committed the changes.