bind` to give the chroot access to the linux special directories:
for i in /dev /dev/pts /proc /sys /run; do sudo mount --bind $i .$i; done
NOTE: We use a
for
loop here to save ourselves some typing, but the above line is just telling the system to run the commandsudo mount --bind <input-dir> ./<input-dir>
for each of the special directories listed between thein
and the;
. In other words, the single line above is equivalent to running the following:sudo mount --bind /dev ./dev sudo mount --bind /dev/pts ./dev/pts sudo mount --bind /proc ./proc sudo mount --bind /sys ./sys sudo mount --bind /run ./run
If installing in EFI mode we also need to give our chroot access to the EFI partition we mounted earlier. mount --bind
comes to the rescue again here, we simply bind mount the livecd mount point into the /boot/efi
directory inside the chroot (/boot/efi
is where grub expects to find the EFI partition).
cd ~/dest mkdir -p boot/efi mount --bind ~/efi boot/efi
Now that we have access to the Linux special folders (and the EFI partition), we can use the chroot
command to actually use our source installation:
sudo chroot ~/dest
At this point you should have a shell inside the same Linux environment you originally copied. Try running some programs or looking at some files that came from your old machine. GUI programs may not work properly, but other then that you should have a fully functional copy of your old installation. Booting into an Ubuntu livecd and running the above chroot
commands every time you want to use this machine is not very practical though, so in the next step we’ll install the grub bootloader to make it into a full-fledged bootable Linux installation.
Step 8: Run grub-install
from inside the chroot
Grub is the most common Linux bootloader and is what we’ll use here. Grub has an MBR flavor and an EFI flavor. If the machine you cloned from was running Ubuntu it most likely already has grub installed, but may not have the EFI version of grub installed. Run the following to install the EFI version (feel free to skip if you’re doing an MBR clone):
apt install grub-efi-amd64-bin # skip if using MBR mode
If your source distro is not Ubuntu based make sure to fully install grub via your distro’s package manager first.
Once you have grub fully installed then you just need to run grub-install
against the drive you installed to. In my case that’s /dev/sdb
, but this may be different on your machine. If unsure fire up gparted
as we did in Step 4 and check the names listed in the partition column there.
Next we install grub to our drive, thereby making it bootable. Be careful to install grub to a drive and not to a partition. Partitions will usually have a number on the end while a drive will usually end with a letter (e.g. /dev/sdb
, not /dev/sdb1
).
grub-install /dev/sdb update-grub
If all went well you will see messages saying grub was successfully installed. When you see this feel free to reboot and check out your freshly cloned installation.
If you got error messages and are installing in EFI mode it’s possible grub tried to use MBR mode. It might be worth a try running grub-install
this way to force EFI mode:
grub-install --target=x86_64-efi
Wrapping up
That’s it, at this point you should have a fully operational clone of your original system, and hopefully also have a solid understanding of each step in the clone process and why it’s needed. Once you realize that a Linux installation is really just a filesystem and a mechanism for booting it, tools like Docker start to make a bit more sense: a docker image is basically just fancy version of the tar
image we created here, with some changes to handle docker layers and make the image files easier to distribute.
In fact, just as we were able to “run” the system we installed via chroot
before we actually made it bootable, you can convert the tar image we created into a docker container quite easily:
docker import [image-file]
99% of the time you’re better off just using a Dockerfile
and docker’s own tooling to build your images, but if you need a quick and dirty way to “dockerize” an existing server you could do this without even having to shut down the existing server!
Similarly, the docker export
command can export a tarball like the one we created for any docker image. Once you extract it you could use the same mount --bind
and chroot
dance we did above to get a shell inside the “container.” If you wanted to get a bit crazy, you could even use the steps from this guide to restore a tarball exported from a docker image onto a physical machine and run it on bare metal. In real life this won’t work with many/most docker images because (for space conservation reasons) many docker images strip out some of the files needed to support physical booting, so you may be asking for trouble if you try this in real life.
- public document at doc.anagora.org/clone-a-linux-system-install-to-another-computer
- video call at meet.jit.si/clone-a-linux-system-install-to-another-computer