Mount directory onto root

bind-mountmountunion-mount

I have a folder containing certain files. Is there a way to mount it onto /, so that the contents of a given directory appear in the corresponding locations in /?

In my case, the directories contain the files related to an application — it does not have directories like /dev and /proc.

I tried creating a bind mount in the following manner:

mount --bind ~/applications/firefox /

However, this does not do anything at all. Unlike what has been speculated in the comments, it does not have any adverse effect either.


The motivation for this is that I have a number of custom applications that I want to install cleanly on mission-critical systems. Understandbly, I want to keep the related management to a minimum. I obtain the filesystem layout of the application install with a unionfs-fuse + chroot method, but then I still have to deal with the problem of the applications' files mingling with those of the system. Mounting certain directories onto / would help me to keep the filesystem clean.

While this method of installing software may seem perverted, there is a distro named "Porteus" which installs software in exactly this manner (and for the same reasons), however, they are known to use a patched kernel along with aufs. However, I cannot use a custom kernel on the systems.

Best Answer

What you're asking to do is done at least once on just about every commonly configured Linux system out there. Most use the tool made available by busybox called switch_root:

What switch_root does is delete all the files out of rootfs (to free up the memory) and then chroot into a new filesystem and exec a new init process out of the new filesystem.

This happens during system initialization. When a linux system is booted the kernel brings the system up in stages. At first the kernel is executed in memory by some other system - such as a bootloader or the firmware - and at this point the kernel is kind of just left to fend for itself - with no real frame-of-reference for the system on which it was just executed.

This is what the initramfs image usually appended to its memory space (but possibly also directly compiled into the kernel) is designed to handle. The initramfs is a real linux root (complete w/ /dev and /proc and what-have-you) filesystem image - it is the first root filesystem ever mounted by a linux kernel. It includes a root filesystem archive containing any/all system-specific modules/configuration files that are necessary to get the kernel on its feet - to bootstrap it.

Anyway, the kernel mounts that archive as rootfs (basically a tmpfs) and then does whatever is necessary to find some other / and mount that one over it. It does this every time you boot your system. It can do it again, and without resorting to unnecessary hacks like unionfs or aufs - both of which are likely to engender all kinds of implementation-specific complications and configuration details (which is not to mention instability).

In the quoted switch_root description above you'll probably notice the phrase delete all of the files out of rootfs. Obviously this would not be a desirable behavior when switching out of a disk-based rootfs. But it only happens that way with switch_root to free the memory for the ram-based filesystem anyway - and is completely unnecessary. Here is some more from the earlier quoted article:

The following shell script fragment demonstrates how to use switch_root:

   # First, find and mount the new filesystem.

   mkdir /newroot
   mount /dev/whatever /newroot

   # Unmount everything else you've attached to rootfs.  (Moving the filesystems
   # into newroot is something useful to do with them.)

   mount --move /sys /newroot/sys
   mount --move /proc /newroot/proc
   mount --move /dev /newroot/dev

   # Now switch to the new filesystem, and run /sbin/init out of it.  Don't
   # forget the "exec" here, because you want the new init program to inherit
   # PID 1.

   exec switch_root /newroot /sbin/init

As you can see above, handling the /dev, /proc, and /sys related problems can be very simply accomplished. If you were to layer any of mount --moved mounts, by the way, you would have to deal not only with mtab and mount but also whatever other complications are introduced by your layering system. It is more simple to do just as you describe in the question - mount root from somewhere else.

You'll need to do basically all of the stuff that happens in a typical initramfs configuration and very little else - (which is not meant to include Debian or Redhat's initramfs images - both of which are way over-engineered). The only real issue you might encounter is how to get PID1 to follow suit - if you leave your system's init stranded on some orphaned rootfs very weird stuff could soon start happening on your system. The obvious way to handle this is to prepare from initramfs on. Just make sure that your hard-disk's init process is prepared to exec another later down the road when you want to switch roots. If you're using a systemd init then this complication is already handled for you:

systemctl --help
...
switch-root ROOT [INIT]         Change to a different root file system
...

If you are using a systemd-based init you should study the unit files in /usr/lib/systemd/system/initrd* to get an idea of what the commonly scripted systemd-style switch-root situation is like.

Another way to go about it might be to mimic busybox's switch_root in initramfs - but to leave out the part where you delete all of the initial root's files. Arch Linux systems configured with systemd in initramfs do this. On those, the initramfs root mounts itself into /newroot's /run/initramfs before doing the switch-root and is what the system falls back to at shutdown to cleanly handle sleep/suspend and similar. That may be the best way to go for your case, actually - just a tiny, ram-persistent root-system which you ping-pong off of for your various individually rooted applications.

Related Question