No general provision seems to exist to boot a Linux system and loop mount as root a file containing a file system, albeit even more complex scenarii, involving the device mapper and its implementations, are supported. It can be useful to have that facility, if repartitioning or using a live CD is not practical. Of course, this makes sense mostly if you don't already run Linux on the target host. So in the example below, I will suppose you want to mount a root file system contained in a NTFS file. This NTFS file is part of an underlying Windows machine. Except for the creation of that NTFS file, the rule of the game is to not have to use Windows for the installation step and to not mess with the Windows setup, especially not it's boot process. Booting will happen through an external device (network, CD or USB stick). # Similar approaches The above constraint obviously rules out approaches such as [CoLinux](http://www.colinux.org/) and [friends](http://www.topologilinux.com). Other methods which run the installer on Windows such as [Wubi](http://wubi.sourceforge.net) or the [Debian Windows installer](http://en.wikipedia.org/wiki/Win32-loader_(Debian\)) are also out, even if they probably use the same kind of tricks which I will describe below. So this was actually a way for me to learn these! # Booting principles The current standard way of booting Debian is recalled briefly: 1. the boot loader (GRUB) loads the kernel image and an initramfs file (line initrd in the GRUB configuration) 1. the boot loader uncompresses the kernel and pass control to it 1. the initramfs file (a cpio gzipped archive) is uncompressed and mounted as the root file system 1. /sbin/init is run and does it's job: essentially loading needed kernel modules which have been prepared inside the initramfs and which are needed for mounting the real root file system, which name is given by kernel options root= 1. the real root file system is mounted, presence of initramfs is cleaned up and control is passed to the /sbin/init there More information about initramfs and it's predecessor initrd can be found on [Wikipedia](http://en.wikipedia.org/wiki/Initrd). Our strategy will be to modify the initramfs file system content to be able to loop mount an NTFS file. But first, you will have to create and populate that file. # Installing a Linux root file system in a NTFS file The Debian installer has no direct option for that. You could proceed as follows, in case you have only one file system and no swap: 1. create some big NTFS file, say /somedir/myownrootfs; this is the only step requiring running Windows 1. boot a Debian installer CD, and start a shell when asked to define the root partition 1. mount the NTFS partition, and create a file system on /somedir/myownrootfs 1. exit the shell and continue the installation as normal, naming /somedir/myownrootfs as the root partition and giving the loop option 1. at the end of the installation, don't let GRUB write on your NTFS partition If you want swap or separate file systems for /usr, /home..., you will have to adapt the above procedure. # Booting in a Linux system whose root file system is a NTFS file At that point, your only option to boot in the previously installed system is to run the CD installer in rescue mode, loop mount the NTFS file and pivot_root in it. You will have to do that at least once, as the following procedure requires modifications to some files inside /somedir/myownrootfs, and running a command to generate a new initramfs while the system is live. So from now on, I will suppose you have booted in your system as explained just above. # initramfs-tools The Debian specific package initramfs-tools contains all that is necessary to manipulate and build the initramfs file. The man page of initramfs-tools explains the organization of the Debian initramfs. In particular, /etc/initramfs-tools is where to put host specific scripts to run inside initramfs, while /usr/share/initramfs-tools contains generic stuff. You are encouraged to explore the initramfs file created by the installation process (called like /boot/initrd.img-2.6...) to understand fully how the following works. # Modifying initramfs content The root file system is to be given as the root= option for the kernel, normally a partition name. In our case, we need 2 pieces of information: the name of the file containing the root file system and it's NTFS partition name. So we need to add an additional kernel option providing that file name; I will use loop=/somedir/myownrootfs, while the NTFS partition will be called /dev/sdb5. This implies editing the GRUB configuration file, for instance the kernel line would be like:
    kernel ... root=/dev/sdb5 loop=/somedir/myownrootfs ...
    
Now the modifications to /etc/initramfs-tools: * File /etc/initramfs-tools/modules:
    loop
    ntfs
    
This ensures loop.ko and ntfs.ko are included in initrd. * File /etc/initramfs-tools/scripts/init-top/loopboot:
     #!/bin/sh     
     PREREQ=""
     prereqs()
     {
       	 echo "$PREREQ"
     }
     case $1 in
     # get pre-requisites
     prereqs)
       	 prereqs
       	 exit 0
       	 ;;
     esac       
     [ -d ${rootmnt}2 ] || mkdir --mode=0700 ${rootmnt}2
     
This ensures some intermediate mounting point /root2 is created (rootmnt having value /root from /sbin/init). * File /etc/initramfs-tools/scripts/local-premount/loopboot:
     #!/bin/sh      
     PREREQ=""
     prereqs()
     {
         echo "$PREREQ"
     }
     case $1 in
     # get pre-requisites
     prereqs)
         prereqs
         exit 0
         ;;
     esac      
     modprobe -k ntfs
     mount -n -t ntfs -o nodiratime,noatime ${ROOT} ${rootmnt}2      
     modprobe -k loop
     mount -n -t ext2 -o loop ${rootmnt}2${loop} ${rootmnt}
     
This loop mounts effectively the file from loop= option at the expected point. Notice that I have here hardcoded the file system types. It's certainly possible to autodetect them, but then a larger set of file systems modules are to be included in /etc/initramfs-tools/modules # Creating a bootable device Now you have to run update-initramfs to get the new initrd.img-2.6... file in place. At that point, if you want to reboot without the installer CD, you have these choices: * create a bootable device: USB stick, CD-ROM... including the kernel image and initramfs file; GRUB on that device has to be configured to load it from there * in case of network booting, upload kernel image and initramfs file to another host configured as a bootp or dhcp server. For how to do that, see for instance [[booting_linux_through_the_network]] Notice how the /boot directory content on /somedir/myownrootfs will never be used when booting; it is only there to feed the booting method just chosen. For the sake of completeness, here is how to create an iso for a bootable CD-ROM: 1. install package grub-rescue; it contains an iso file /usr/lib/grub-rescue/grub-rescue-cdrom.iso 1. mount that iso as e.g. /media/cdrom 1. copy all the content of /media/cdrom to a temporary place, e.g. /tmp/newiso, while keeping the permissions of the files and directories 1. you can now unmount /media/cdrom 1. in /tmp/newiso, you can remove boot.catalog, but add to it kernel image and initramfs file 1. in /tmp/newiso/boot/grub, edit grub.cfg to boot from the 2 files just added above, which would look like:
    menuentry "GNU/Linux" {
	   set root=(cd)
	   linux /vmlinuz root=/dev/sdb5 loop=/somedir/myownrootfs
	   initrd /initrd.img
    }
    
1. create a bootable iso with a command like:
    genisoimage -o /tmp/new.iso /tmp/newiso
    
1. burn the iso:
    wodim /tmp/new.iso
    
# The moment of truth Then, you can reboot with the just burned CD. In case of problems, [use the break= or debug kernel options](http://wiki.debian.org/InitramfsDebug). # Several partitions inside NTFS If you have separate /var, /usr or /home partitions as loop filesystems inside the NTFS partition, you will certainly not get a full boot at the first trial. Let's see why. When you initramfs has run pivot_root to switch to the final / partition inside the NTFS partition, the new /sbin/init loses all knowledge that the NTFS partition is actually mounted and must rely on information in /etc/fstab to mount the remaining /var, /usr or /home. Obviously, the entry for these partitions will be some loop file mount from the NTFS partition, which must be mounted **first**. Because the order of mounting the filesystems in /etc/fstab is random, you have to force mounting the NTFS partition first (which was already mounted inside initramfs, remember; doesn't you head spin now?). Here is a diff from a Squeeze installation which shows my hackish solution:
$ diff -C 2 /etc/init.d/checkfs.sh /etc/init.d/checkfs.sh-O 
*** /etc/init.d/checkfs.sh	2012-02-09 18:19:55.000000000 +0100
--- /etc/init.d/checkfs.sh-O	2011-01-01 06:55:27.000000000 +0100
***************
*** 140,145 ****
  }
  
- mount -a -t ntfs
- 
  case "$1" in
    start|"")
--- 140,143 ----
$ diff -C 2 /etc/init.d/mountall.sh /etc/init.d/mountall.sh-O 
*** /etc/init.d/mountall.sh	2012-02-09 18:17:40.000000000 +0100
--- /etc/init.d/mountall.sh-O	2011-01-01 06:55:27.000000000 +0100
***************
*** 28,32 ****
  	#
  	mount_all_local() {
! 	    mount -a -t nontfs,nfs,nfs4,smbfs,cifs,ncp,ncpfs,coda,ocfs2,gfs,gfs2 \
  		-O no_netdev
  	}
--- 28,32 ----
  	#
  	mount_all_local() {
! 	    mount -a -t nonfs,nfs4,smbfs,cifs,ncp,ncpfs,coda,ocfs2,gfs,gfs2 \
  		-O no_netdev
  	}
# Related links * comparing initramfs with an [alternative](http://wiki.debian.org/InitrdReplacementOptions) * what is said about initramfs by the [Debian competition](http://en.gentoo-wiki.com/wiki/Initramfs) * as noted at the beginning, there is support in initramfs-tools for the [device mapper](http://linuxgazette.net/114/kapil.html), so a more generic solution to the problem solved here may involve some work on top of that, such as [dm-loop](http://sources.redhat.com/lvm2/wiki/DMLoop)