I would like to try to set up a computer so that it has multiple Linux installs all in the same filesystem. For example, the filesytem would have 3 folders: /Ubuntu_Precise, /Ubuntu_Oneiric, and /Ubuntu_Natty.

(I know you can do this with BTRFS and subvolumes, but I would like to use EXT4 for speed).

I once set up multiple installs of different distros using BTRFS, and from getting that working, I know Grub does just fine with booting the vmlinuz and initrd image from 'nonstandard' paths. But when I was doing the BTRFS thing, there was the rootflags=subvol=@<subvolume_name> that told the kernel to mount that subvolume as / in the filesystem. Is there any argument that you could pass the kernel that would make it bind mount a subfolder in a partition as / and then boot?

I think for the other parts, I'm fairly close. I know how to specific a bind mount in /etc/fstab. Also, from when I set up my system with multiple linux installs in BTRFS subvolumes, I'm used to installing a distro in a VM and then migrating it using rsync, so I'm not too worried about what I would need to do to get the right configuration, I'm just trying to find out what the right configuration would be. Once I know that, I should be able to do the migration into the subfolders and file editing easily enough.

I already know about virtualization and partitions, but that's not what I'm looking for. The target computer does not have enough power to do virtualization, and partitions do not share free space. I'm looking to set up a system that dual/triple/quad/etc boots linux distros, but that does it with one filesystem, so that there is no case of "I have free space, but it's in the wrong partition!'

If anyone has suggestions how to edit my question or its title to be clearer, I'm all ears.

  • 1
    There is AFAIK nothing build into the system. What you probably would have to do is to add another bootparameter and modify your initramfs to chroot into the subdirectory before executing init – Ulrich Dangel May 27 '12 at 1:24
  • @UlrichDangel that is what I was going to propose. Make it an answer! – Nils May 27 '12 at 21:31
  • @Nils ok i just provided an answer, tbh. i didn't want to write one at first as i didn't want to provide the patch/script – Ulrich Dangel May 28 '12 at 2:10

Short answer -- there is as far as I know no out of the box working solution for your specific requirements. You will have to adjust each initramfs of each distribution to support your specific needs.

Long answer -- yes it is possible. Nowadays most Linux distributions use an initramfs which will be loaded into memory by the bootloader and then unpacked by the kernel. There it will run /sbin/init which is responsible for setting up the early userspace (running udev, loading modules, starting plymouth, asking for crypto passphrase, setting up the network for network mounts, … you name it). As you can run your own scripts and evaluate custom boot parmaters.

Example for Debian

If you are using Debian (should be the same with Ubuntu) you should be able to place a script in /etc/initramfs-tools/scripts/init-bottom/ which will be executded before init is started. For more information about the script, the different directories and the layout have a look at man initramfs-tools. You will have to adjust rootmnt and add the target directory.

Sample (untested) script which should be installed either as /etc/initramfs-tools/scripts/local-bottom/00-myroot or /usr/share/initramfs-tools/scripts/init-top/00-myroot :

#!/bin/sh -e


prereqs() { echo "$PREREQS"; }

case "$1" in
  exit 0

for opt in $(cat /proc/cmdline); do
  case $opt in

if [ -n "$new_mntdir" ] ; then
  echo rootmnt="$rootmnt/$new_mntdir" >> /conf/param.conf

The idea is to adjust rootmnt which is used in the initramfs init script to start/execute the real init. As the root device is already mounted in the init-bootom stage you can just adjust/alter the target directory.

To use this script just add a new boot parameter, copy the script, make it executable, regenerate your initramfs and add a boot parameter for your Linux distribution, e.g. rootdir=/Ubuntu_Precise.

  • You also probably want to bind mount the real root into a subdir of the os root so you can see the other OS files from the one you boot. – psusi May 28 '12 at 2:32
  • @psusi You can do this via fstab or just directly do mount /dev/rootdevice /mountpoint after the system is running – Ulrich Dangel May 28 '12 at 2:45
  • I wonder when that changed? You used to not be able to mount the same block device again; you'd get an EBUSY. – psusi May 28 '12 at 2:53
  • 1
    @psusi not sure but probably with the introduction of bind mounts – Ulrich Dangel May 28 '12 at 2:58
  • @UlrichDangel Thanks for the (very) detailed answer! – Azendale May 30 '12 at 4:46

Here are two ways which work in ubuntu bionic (and possibly elsewhere). i've not enough rep to comment, but, bionic:/usr/share/initramfs-tools/init looks in /etc/fstab for /usr right after calling mountroot and before calling the *-bottom scripts, so adding an init-bottom script (as suggested in another answer here) is "too late". instead i recommend these:

#!/bin/bash -f
#copyleft 2018 greg mott

#set a subdirectory as root (so multiple installs don't need partitions)
#these work in ubuntu bionic, could be different elsewhere
#1st choice:  tweak initramfs-tools/scripts/local
#   pro:  subdirectory becomes root directly, nothing gets any chance to see the partition root
#   con:  only works if the subdirectory's initramfs/initrd is tweaked and rebuilt
#2nd choice:  specify this script as init= on the kernel commandline
#   pro:  no need to rebuild initramfs
#   con:  if the partition root etc/fstab mounts /usr the initramfs will have already mounted it
#   con:  it's conceivable some initramfs script might still look in the partition root rather than your subdirectory
#   con:  this script requires bin/bash et al in the partition root

#for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot:
#menuentry "subroot foo" {
#     echo "subroot foo"
#              sub=/foo
#              uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894        #use your partition's uuid
#     search --no-floppy --fs-uuid --set=root $uuid
#            linux $sub/vmlinuz ro root=UUID=$uuid subroot=$sub                                                                                         
#     echo "initrd $sub/initrd.img"
#           initrd $sub/initrd.img      #works in recent releases where the /initrd.img softlink is relative

#to use this script, in addition to subroot= on the kernel commandline also specify:
#   init=/path/to/script        #pathname from partition root to this script (chmod 744)

#the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace:
#          mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt}
#          mountroot_status="$?"
#          set -x
#          karg=" $(cat<proc/cmdline) " m=${karg#* subroot=}
#          [ "$m" = "$karg" ]||subroot=${m%% *}                                         #extract subroot from kernel commandline
#          [ $subroot ]&&part=part||part=$rootmnt                                       #no subroot, just mount partition as root
#          mkdir part
#          mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&&         #mount partition
#             if [ "$subroot" ]
#             then mount --bind part/$subroot $rootmnt&&                                #mount subroot
#                  umount part                       #&&sleep 15                        #unmount partition root (uncomment sleep for time to look)
#             fi
#          mountroot_status="$?"
#          [ $mountroot_status = 0 ]||sleep 90                                          #if error pause to look
#          set +x
#once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel,
#and it will automatically build into every new kernel installed

subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=}
           [ "$m" = "$karg" ]||subroot=${m%% *}                 #extract subroot from kernel commandline
           [ $subroot ]||return 0                               #no subroot, just proceed in partition root
           while read -r m r m
           do for m in $M x                                     #build list of what's already mounted
              do    [[ $r = $m* ]]&&break                       #exclude subtrees (ie dev/**)
              done||[[ $r = /   ]]||M=$M\ $r                    #exclude /
           (set -x;mount --bind $subroot mnt)||{ set -x         #mount subroot
                                                 sleep 30          #if not found pause to see error
                                                 return 0;}        #then reincarnate as partition root init
           for m in $M
           do (set -x;mount -n --move $m mnt$m)||return         #move listed mounts to subroot
           set -x
           cd           mnt&&
           pivot_root . mnt&&                                   #subroot becomes root
           umount -l    mnt&&                                   #unmount partition root
          #sleep 15        &&                                   #so far so good?  uncomment for time to look
           exec chroot . init "$@"                              #reincarnate as subroot init
subroot "$@"&&exec init "$@"||exec bash                         #land in a shell if moves or pivot fail
  • This worked a treat for me – paultop6 Jul 19 '18 at 8:40

Booting different linux without messing with the partition table is interesting for different purposes, an alternative solution to a shared filesystem is to use loop volumes, here the few changes needed supposing you have a /debian loop file/volume into the /dev/sdb1 filesystem (I'm using current GNU/Debian sid/unstable for both main and loop os).

/etc/grub.d/40_custom: # outside from loop volume
menuentry 'label' --class gnu-linux --class gnu --class os {
    loopback loop (hd2,msdos1)/debian
    linux   (loop)/boot/vmlinuz root=/dev/sdb1 loop=/debian ro
    initrd  (loop)/boot/initrd

Arguments defined into grub as linux command line are set to env by initrd /init, so:


loop allow to mount the volume over "itself", the default script flow do a mount /dev/sdb1 /root we just optionally remount the /dev/sdb1 as rw if it was ro then always append a mount -o loop /root/debian /root.

/etc/initramfs-tools/scripts/local-bottom/loop: # inside the loop volume

[ "$1" = "prereqs" ] && echo && exit 0

if [ -n "${loop}" ]; then
        if [ "${readonly}" = "y" ]; then
                mount -o remount,rw ${ROOT} ${rootmnt}
        mount ${roflag} -o loop ${rootmnt}${loop} ${rootmnt}

Need also to pre-load some module into the initram (then don't forget to run update-initramfs)

/etc/initramfs-tools/modules: # inside the loop volume

Don't know how much using loop influence performances or waste resources, I'm wondering if mounting ext4 over ext4 double the probabilities of a filesystem failure, but guess some tuneup could be done. Maybe there's a better way to use loop, less hackish, if there's please let me know because I haven't found.


This is not an answer but I want to clarify some point about Ulrich's answer and comments (I can't comment above).

The solution Ulrich propose "may" work (untested yet) but then you will get a non-remountable filesystem. As a workaround (IMHO ugly) you can mount the fs as rw before chrooting (as suggested here) but be careful about broken init scripts. I guess this workaround have more side effects (like broken fs trying to remount ro and failing).

I'm using kernel 3.2 with ext4 and mounting an already mounted dev inside the chroot still give EBUSY as psusi commented.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.