As mentioned in my previous post, I had wanted to install Debian in a existing encrypted LVM on my hard drive. But I was stymied by a lack of installer support. So I installed on an external drive instead.
It occurred to me that I could just copy the installed system back to where I had originally wanted to install it. So I did. And it worked quite well. In this post, I will describe the steps that I went through.
The first step was to boot into a linux system, but not one of the systems involved in the copying. I could have done this by booting a live system on CD or USB. However, I happened to have Tumbleweed installed in a separate partition on the same computer, so I just booted into that.
The next step was to open the LVM containers for both the source (the external drive where I had installed Debian) and the destination (the existing encrypted LVM where I wanted to copy Debian). The steps for this were:
# cryptsetup luksOpen device-name virtual-name #once for each LVM # vgchange -a y #make LVM volumes visible
The virtual device names were now visible in “/dev/mapper”. The names that contained “root” as part of the name were the relevant ones here.
Next, I needed to mount the partitions from the virtual device names:
# mkdir /mnt/1 /mnt/2 # mount /dev/mapper/sg2-root /mnt/1 # mount -o ro /dev/mapper/deb--vg-root /mnt/2
This mounted the destination on “/mnt/1” and the source on “/mnt/2”. The names given are not the real names. I shortened the first, and I don’t remember what the Debian install used for the second.
You will notice that I mounted the source virtual device as read-only. This was to reduce the risk that I might damage it with a typo in one of the commands I would be using.
Before copying, I needed to be sure that the destination was empty. One way would be to simply reformat (with “mkfs”). The other alternative — the one that I used — was to delete everything other than the “lost+found” directory from the destination.
I then used:
# cd /mnt/1 ## change to the destination # ( cd /mnt/2 && tar cf - .) | tar xpf -
That makes an inline tar archive of the source (the commands in parentheses), and pipes them to a tar command to expand the archive into the current directory (the destination). This took a few minutes. There were a couple of warning messages about ignoring socket files (essentially named pipes). It was safe to ignore those.
Next, I had to copy the “/boot” partitions.
# mount /dev/sdb3 /mnt/1/boot ## mount the destination # mount -o ro /dev/sdc1 /mnt/2/boot
Again, notice that I mounted the source read-only to reduce the risk from an accidental typo.
I then needed to make the destination “/boot” empty. Again, I deleted all but the “lost+found” directory from the “/mnt/1/boot” directory. An alternative would be a reformat. I should add that any “mkfs” formatting needs to be done before mounting.
Then a similar copy command
# cd /mnt/1/boot ## move to destination # ( cd /mnt/2/boot && tar cf - . ) | tar xpf -
This was far quicker, because much less is installed in “/boot”.
Everything was now copied. But the system would not work as copied. I had to do some tweaking.
I edited “/mnt/1/etc/fstab”. And there, I had to change the listed file systems to refer to the new file systems for the destination. Where the “fstab” entry used a UUID, I changed that to the appropriate UUID for the destination. The command “blkid” (done in a different terminal window) gave me the UUIDs that I would need to use.
Where the “fstab” entry was a virtual device name, I changed that to the new virtual device name for the destination. I similarly changed the entry for swap, though there was no need to copy to swap.
I also needed to edit “/mnt/1/etc/crypttab” (the new “/etc/crypttab”) so that it would have the details of the new LUKS encrypted LVM. Changing this was similar to changing “fstab”. Since the entry used a UUID, I changed that to the UUID of the new LUKS container. And I changed the virtual name to the one that I planned to use (“sdb5_crypt”).
With those changes, the system ought to be almost ready, except that I would not be able to boot it. So the next step was to setup booting.
The problem for booting, is that the “initrd” (or “initramfs”) that is used in the early stages of boot, would be referring to the old file systems rather than the new. And, similarly, the grub boot menu would be referring to the old file systems.
The simplest way of fixing this was to boot the old system on the external drive, then mount the new system, chroot into it, and rebuild the “initramfs”.
I started by booting from the external drive, then getting a root shell.
# cryptsetup luksOpen /dev/sdb5 sdb5_crypt # vgchange -a y # mount /dev/mapper/sg2-root /mnt
This mounted the new root file system on “/mnt”.
# mount /dev/sdb3 /mnt/boot
This mounted “/boot”. Since this is a UEFI box, I also needed “/boot/efi” be mounted. That was a problem, because it was already mounted on the system that I was running. So I used a bind mount:
# mount --bind /boot/efi /mnt/boot/efi
And then there are file systems such as “/dev” and “/proc” that will be needed:
# mount --bind /dev /mnt/dev # mount --bind /proc /mnt/proc # mount --bind /sys /mnt/sys
I’m now ready to rebuild the “initramfs”.
# chroot /mnt # move into the mounted system # update-initramfs -k all -u -v
And now I need to reinstall grub.
# grub-install --target=x86_64-efi
and I am done.
Note that the command to rebuld the “initrd” or “initramfs” varies between different flavors of linux. So check what your system needs. The “grub-install” that I used should be “grub2-install” on some systems. And the arguments that I used are for a UEFI system. For a legacy system, I would just give the directory device from which to boot, and possibly a “–force”.
I exited from the “chroot” session, then from the root terminal. I rebooted. And the system booted into the new location as expected.