skip to content

On Linux, what does `mount --bind /srv/data /var/www/html` actually create, how does it differ from putting a symlink at that path, and what does `--rbind` add?

level: middleimportance: should knowfreq 50%

answer

  1. same inodes, second mount point
  2. not a link the caller can detect
  3. submounts need the recursive form
  4. options are per-mount, not per-filesystem

basics

~20 s

A bind mount makes an existing directory (or file) appear at a second path as a real mount entry, with both paths referring to the same underlying data. Unlike a symlink it is a genuine mount, not a link the caller can detect or refuse; --rbind also replicates any submounts.

solid answer

~60 s

`mount --bind` attaches a subtree that is already in the filesystem tree at a second mount point. Both paths then resolve to the same inodes — the same files, the same free space, no copying — but the kernel records a real mount entry, which you can see in `findmnt` or `/proc/self/mountinfo`. That is the practical difference from a symlink: a symlink is a special file whose target the caller can inspect, refuse or fail to follow across a chroot, whereas a bind mount is indistinguishable from a normal directory. It also works for a single file, which is the usual way to inject one config file into an isolated tree. `--rbind` does the same but recursively replicates the submounts under the source; a plain `--bind` gives you only the top filesystem and leaves anything mounted beneath it invisible at the new path. To make it persistent I put an fstab line with the `bind` option, and to make just the second path read-only I set `ro` on the bind rather than on the original.

go deeper

for a junior

Know that a bind mount makes the same directory appear at a second path, that the data is not copied, and that it is not a symlink.

for a middle

Explain that both paths reach the same inodes, that the mount is visible in mountinfo with a root field, and that --rbind is needed to carry submounts along.

for a senior

Demonstrate that mount options are per-mount: a read-only bind restricts one path only, and every bind is an extra reference that keeps the filesystem busy at unmount time.

for a principal

Weigh bind mounts against layout changes and application configuration — they are invisible kernel state that a fresh machine will not have unless fstab or the provisioning tooling recreates it.

## What the kernel does `mount --bind src target` issues `mount(2)` with the `MS_BIND` flag. Rather than attaching a block device, the kernel takes the dentry subtree already reachable at `src` and grafts it into the tree at `target`. No data is copied and no second filesystem is created: the two paths lead to the same inodes on the same filesystem, so a file written through one is instantly visible through the other, and `df` reports one set of numbers for both. The new attachment is a first-class mount. `/proc/self/mountinfo` gains a line for it, and that line has a *root* field showing which subdirectory of the source filesystem was bound — this is how you tell a bind mount from an ordinary one when reading the table. ```bash mkdir -p /srv/data /var/www/html mount --bind /srv/data /var/www/html findmnt /var/www/html umount /var/www/html ``` ## Bind mount versus symlink A symlink is a file whose contents are a path. Every resolution of it goes through the link, and that has consequences a bind mount does not have: - **Detectability.** `lstat` reveals a symlink, and security-conscious programs deliberately refuse to follow one, or open with `O_NOFOLLOW`. A bind mount looks exactly like a directory, so nothing refuses it. - **Reachability.** A symlink pointing at `/srv/data` is useless inside a chroot or an isolated mount tree that does not contain `/srv`. A bind mount makes the data genuinely present at the target path. - **Escapes.** A symlink can point anywhere, including outside a subtree an application believed it had confined itself to; a bind mount changes what the path *is* rather than redirecting to somewhere else. - **Files.** You can bind-mount a single regular file over another regular file. There is no symlink equivalent that keeps the original path a real file. The cost is that a bind mount is kernel state, not filesystem content. It disappears on reboot unless it is in fstab, and it does not travel in a backup of the directory tree. ## Recursion: --bind versus --rbind A plain bind attaches only the filesystem that owns the source directory. If something else is mounted *underneath* the source — say `/srv/data/cache` is a tmpfs — that submount is not replicated, and at the target you will see the empty `cache` directory of the underlying filesystem instead of the tmpfs. `--rbind` walks the subtree and replicates each submount, which is what you want when you are re-rooting a whole tree (`mount --rbind /dev /mnt/dev` before a chroot is the canonical example). ## Per-mount options A bind mount initially shares the option set of the filesystem it came from. Options such as `ro`, `nosuid`, `nodev` and `noexec` are properties of the mount, not of the filesystem, so they can differ between the two paths — that is what makes a read-only bind useful. Historically this took two commands, because the bind operation itself ignored other options and you had to follow it with `mount -o remount,bind,ro /var/www/html`. Modern util-linux (2.37 and later) performs that second step for you when you write `mount -o bind,ro`, so on a current distribution a single command is enough. Knowing that the two-step form exists still matters, because it is what you need on older systems and what the fstab entry effectively does. In fstab a bind entry names the source in the first field, uses a placeholder filesystem type and carries the `bind` option: ``` /srv/data /var/www/html none bind 0 0 ``` ## Where they show up Bind mounts are how a directory gets presented under a different path without touching the application: exposing part of a large data volume to a service that insists on a fixed path, giving a chroot or a build environment access to `/proc`, `/sys` and `/dev`, or handing a service a read-only view of a directory it should not modify. They are also the reason `umount` of the original path can fail while the data still appears elsewhere — every bind is an independent reference to the filesystem, and all of them must go before the filesystem is really released. The two things people get wrong are forgetting that the mount vanishes on reboot without an fstab entry, and assuming that binding a directory read-only somehow protects the data — it does not, because the original mount is still writable. A read-only bind restricts *that path*, not the filesystem.

  • You bind-mount a directory read-only for one service. Can that service's data still be changed?
    Yes — through the original mount point, or through any other bind of the same filesystem that is not read-only. Mount options are properties of a mount, not of the filesystem, so a read-only bind only constrains processes reaching the data by that path. If the data must be immutable for everyone, the underlying filesystem itself has to be mounted read-only.
  • Why does mount --bind of a directory sometimes show fewer files at the target than at the source?
    Because something is mounted underneath the source and a plain bind does not replicate submounts. The target then shows the directory as it exists on the underlying filesystem — typically empty — rather than the filesystem mounted over it. `--rbind` replicates the whole subtree including its submounts, which is what re-rooting a tree for a chroot requires.

saying these in an interview costs you the question

  • Calls a bind mount a fancy symlink
  • Expects submounts to appear without --rbind
  • Thinks a read-only bind protects the underlying data
  • Assumes bind mounts survive a reboot without an fstab entry
  • Believes a bind mount duplicates the data or consumes extra space

context