I have an external hard disk enclosure with two disks. I used Logical Volume Manager to create a single logical volume that spanned them, and slowly filled it to about 60% capacity. Lately, I've been trying to be more conscious of using encryption, and this was one area where I hadn't done so. At the time I felt like learning how to do LVM was enough, and LUKS could wait until later. Well, it's later. Here's how I added encryption after the fact (without a spare hard disk).
As these are potentially dangerous commands, you absolutely should back up your files prior to beginning. If you have sufficient spare media, you should consider not trying to do this conversion in-place. Instead just create a new filesystem and copy files over.
In my case, the volume of data was such that I didn't have the resources to do so, and the value of the files was fairly low, so I just went ahead without. The plan is to shrink the existing filesystem and logical volume, create a new logical volume in the freed space, with an encrypted filesystem inside. Then, move files from the old filesystem to the new one, while readjusting the allocation of disk space if needed.
This was reconstructed from my bash history, and typed out by hand. Errors are certainly possible, so don't blindly reuse these exact commands. With that said, let's begin.
First, unmount the filesystem (FS), and shrink it to be as small as possible. Then, shrink the logical volume (LV) to match the FS's size:
umount /dev/vg0/usr-store resize2fs -pM /dev/vg0/usr-store lvreduce -L ? /dev/vg0/usr-store # from resize2fs
resize2fs reports "2000 (4k) blocks" as the new filesystem size, then the size for
lvreduce is in megabytes:
2000 * 4*1024 / 1024*1024.
Now, allocate the space you just freed up by shrinking usr-store to a new LV:
lvcreate -l 100%FREE -n new-store vg0
Now, we'll add the encryption layer:
cryptsetup --verify-passphrase luksFormat /dev/vg0/new-store cryptsetup luksOpen /dev/vg0/new-store new-store
And create a new filesystem. I chose ext4, which has efficiencies when dealing with large files, but your workload might require something different.
mkfs -t ext4 -m2 -O dir_index,filetype,sparse_super -L new-store-fs /dev/mapper/new-store
At this point, you have a new filesystem that's LUKS-encrypted and ready to use. We can now begin transferring files from the old filesystem to the new one.
mkdir /mnt/new-store mount -t ext4 /dev/mapper/new-store /mnt/new-store mount -t ext4 /dev/vg0/usr-store /mnt/usr-store mkdir /mnt/new-store/mike chown mike:mike /mnt/new-store/mike rsync -a --remove-source-files /mnt/usr-store/mike/Files /mnt/new-store/mike # wait... wait... wait... find /mnt/usr-store/mike/Files -type d -empty -delete
If you filled the new filesystem, then you'll need to readjust the disk space allocation by shrinking the old filesystem & LV, and growing the new filesystem & LV.
umount /dev/vg0/usr-store resize2fs -pM /dev/vg0/usr-store lvreduce -L ? /dev/vg0/usr-store mount -t ext4 /dev/vg0/usr-store /mnt/usr-store lvextend -l +100%FREE /dev/vg0/new-store cryptsetup resize new-store resize2fs -p /dev/mapper/new-store
Now you can continue moving files.
Once the old filesystem is empty, simply remove the logical volume that contains it, and rename the new encrypted volume and LV. You can optionally extend the FS & LV to fill the rest of the space now as well. I chose to use the space for a new LV I'll be using for backups instead.
umount /dev/vg0/usr-store lvremove /dev/vg0/usr-store lvrename vg0 new-store usr-store dmsetup rename new-store usr-store rmdir /mnt/new-store mount -t ext4 /dev/mapper/usr-store /mnt/usr-store