Saturday, December 3, 2011

Booting Debian from a loopback filesystem

It is possible to boot a GNU/Linux system from a loopback filesystem. This is probably similar to the method Wubi uses. If don't want to bother creating and configuring the loopback filesystem by yourself, then just use Wubi instead.

First, you need a loopback filesystem. Create one using the dd command:
dd if=/dev/zero of=/path/to/loopback.img bs=1M count=4000
This will create a 4000MB file on the path you specified with 'of='. The 'bs' parameter means 'block size' - dd will take a block of zeroes that large and write it to the specified path.

Next thing you want to do is to create a filesystem inside the file, the same way you do with regular partitions (remember, "in Unix everything is a file"):
mkfs.ext3 /path/to/loopback.img
It will complain that loopback.img is not a block special device. Just ignore that and press 'y' to proceed.
The next step is to install the operating system on the loopback filesystem. I didn't really install anything, I just copied the files of my existing Debian installation. If you have an already installed system and you want to do the same, just mount the loopback filesystem and copy all its '/' on the loopback filesystem. For example:
mount -t ext3 -o loop /path/to/loopback.img /mnt
cp -a /path/to/already_installed_system_root /mnt

Alternatively you can use debootstrap.
From this step on, I assume that you have your loopback file with working system mounted on /mnt.

Next step is to configure the system in the loopback file to boot. First, you need to make initrd mount the loopback filesystem and run the init script of the installed system. That means that you have to generate a new initrd image that's capable of doing that. Put the following two lines at the end of the file '/mnt/usr/share/initramfs-tools/modules':

Now, open the '/mnt/usr/share/initramfs-tools/scripts/local' file. Find the mountroot() bash function, and change the lines where it should mount the root partition with the following:
 mkdir /root2
mount -n -t ext3 -o nodiratime,noatime /dev/sdaX /root2
mount -n -t ext3 -o loop /root2/path/to/loopback.img /root

Replace /dev/sdaX with the correct partition where you'll keep the loopback.img file. Now chroot into /mnt:
chroot /mnt

Then generate a new initrd image with:

mkinitramfs 2.6.32-5-686 -o /boot/initrd-loopback.img
It's possible that you will need to replace '2.6.32-5-686' with the correct parameter which is the name of the sub-directory in /lib/modules for which you want to generate the image.

The next step is optional. If you want to create a menu entry for grub2 for the system in the loopback device, put this in '/etc/grub.d/40_custom':
menuentry "Loopback Debian" {
loopback loop (hd0,msdos4)/path/to/loopback.img
linux (loop)/boot/vmlinuz-2.6.32-5-686 root=/dev/sdaX
initrd (loop)/boot/initrd-loopback.img

then run update-grub2.
Please note that you need to replace the paths like /path/to/something with the real paths on your system.
I needed this in order to run Debian on a system that I wasn't allowed to change it's partition layout or MBR, so I installed grub on a portable usb drive. You can install it on the MBR of your hdd.