linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Simulator
  • Knowledge base
  • Interview prep
Index
Categories
All entries
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
home/linux/kb/File system/bind-mount

kb/filesystem ── File system ── intermediate

bind mount: making a directory appear in another place

bind mount is `mount --bind <src> <target>`. It makes a directory (or file) visible at a second path. Not a copy, not a symlink: the same inodes through VFS. A basic building block of chroots, containers, and systemd sandboxes.

view as markdownaka: mount-bind, rbind, bind-mount-propagation

What it is and how it differs from a symlink

A bind mount makes the same set of inodes reachable through two paths. It does not duplicate data and it is not a link at the filesystem level. It is an operation in the kernel's VFS layer.

bash
sudo mount --bind /var/log /home/serge/logs
ls /var/log/syslog
ls /home/serge/logs/syslog        # same file, same inode

How it differs from a symbolic-link:

Propertysymlinkbind mount
What it isinode pointer in the FSVFS mount
After rebootsurvivesgone (needs fstab)
chroot seesbroken if the target is outsideworks, the target is already "inside"
realpathresolvesdoes NOT resolve (shows as the target path)
Needs rootnoYES (mount(2))
Can be read-onlynoyes (-o ro)

The main strength of a bind mount: inside a chroot or namespaces, only the real path is visible. A symlink to a path outside would be broken.

Basic use

bash
# 1. Directory onto a directory
sudo mount --bind /var/log /mnt/logs
# 2. File over a file (a powerful trick)
sudo mount --bind /tmp/my-fake-resolv.conf /etc/resolv.conf

▸now /etc/resolv.conf points to our file, the original is still there

# 3. Unmount
sudo umount /mnt/logs

Overriding a file by binding another file on top of it is a common feature in containers and hot fixes: do not edit the original, lay a bind on top of it on the fly.

Read-only bind: a two-step move

The -o ro option on the initial mount is ignored by the kernel during the first bind. You need a separate remount step:

bash
sudo mount --bind /opt/data /srv/ro-data
sudo mount -o remount,ro,bind /srv/ro-data       # now it is really RO

Or in one command with --mkdir plus -o:

bash
sudo mount --bind -o ro /opt/data /srv/ro-data   # works directly on util-linux >= 2.27

Check it:

bash
findmnt /srv/ro-data
# TARGET        SOURCE          FSTYPE OPTIONS
# /srv/ro-data  /dev/sda1[/opt/data] ext4 ro,relatime

The SOURCE column with [/...] in brackets is the sign of a bind mount.

--bind vs --rbind

bash
sudo mount --bind  /  /mnt/host       # bind: does NOT carry submounts
sudo mount --rbind /  /mnt/host       # rbind: recursive, with /proc, /sys, /dev, and so on

--rbind matters when the source directory contains nested mount points (the classic example is bind-mounting the whole root filesystem for a chroot). Without the r, you get empty /proc, /sys, and /dev inside.

Mount propagation: what it is about

When a new mount is made inside a bind mount, should it be visible outside? That is controlled by the propagation flag:

FlagBehavior
sharednew mounts are visible both ways (default on systemd systems)
slavemounts from the master are visible to us, but not the reverse
privatemounts are invisible both ways
unbindablecannot be bound at all

Setting it:

bash
sudo mount --make-private /srv/jail
sudo mount --make-rslave /                    # recursive, for the whole tree

Why know this: Docker and systemd lean on propagation heavily. If something with bind in your /etc/fstab behaves oddly across a reboot, check findmnt -o TARGET,PROPAGATION.

Example: mount --bind / for a chroot inherits the same propagation as /. If you then unmount something inside the chroot, it also unmounts outside (when propagation is shared). That is not obvious. The fix is --make-rprivate on the bind copy.

fstab: a persistent bind

# /etc/fstab
/var/log    /home/serge/logs    none    bind                  0 0
/opt/data   /srv/ro-data        none    bind,ro               0 0
/home       /chroot/home        none    rbind                 0 0
/tmp/conf   /etc/myapp.conf     none    bind                  0 0

The FS type is none (it does not apply to a bind). The options go through bind or rbind. To make systemd-fstab-generator pick it up without a reboot:

bash
sudo systemctl daemon-reload
sudo mount -a

In practice

chroot and rescue

bash
for fs in proc sys dev dev/pts run; do
    sudo mount --bind /$fs /mnt/$fs
done
sudo chroot /mnt

Without binds for /proc and /dev, many commands inside a chroot will fail.

Moving data without changing the path

Say /var/lib/postgres is filling up the root filesystem and you need to move it to a separate disk without editing the Postgres config:

bash
sudo systemctl stop postgresql
sudo rsync -aHAX /var/lib/postgres/ /data/postgres/
sudo mv /var/lib/postgres /var/lib/postgres.old
sudo mkdir /var/lib/postgres
echo '/data/postgres /var/lib/postgres none bind 0 0' | sudo tee -a /etc/fstab
sudo mount -a
sudo systemctl start postgresql

Postgres keeps reading /var/lib/postgres, but the data physically lives on /data.

Read-only layer in a container

bash
sudo mount --bind /etc /run/jail/etc
sudo mount -o remount,ro,bind /run/jail/etc

systemd PrivateTmp

When a service has PrivateTmp=yes, systemd does a bind plus namespace under the hood: it creates an empty directory and bind-mounts it over /tmp for that service. The service does not see the host's /tmp.

Limits

  1. You cannot bind a file onto a directory or the reverse. Only file to file, directory to directory.
  2. The target must exist. For a file, create it empty; for a directory, mkdir.
  3. umount removes only the bind, the original stays:
    bash
    sudo umount /mnt/logs       # /var/log is still there
  4. du counts twice if both paths fall into the walk:
    bash
    du -sh /var/log /mnt/logs   # totals up to 2× the size

Debugging

bash
findmnt --types=none                      # all bind/rbind mounts
findmnt -o TARGET,SOURCE,OPTIONS,PROPAGATION /srv/jail
cat /proc/self/mountinfo                  # raw dump of all mounts
mount | grep bind                         # the old-school way

Bind mounts in mountinfo have the form <src-fs>[/sub/path] in SOURCE. That is exactly how findmnt knows it is a bind.

§ команды

bash
sudo mount --bind /var/log /mnt/logs

Make a directory visible at a second path: the same inodes, not a copy

bash
sudo mount -o remount,ro,bind /srv/ro-data

Make an existing bind read-only with a separate remount step, otherwise ro is ignored

bash
sudo mount --rbind / /mnt/host

Recursive bind of the root with all submounts /proc, /sys, /dev, for chroots

bash
findmnt --types=none

List all bind mounts on the host: they all have type none

bash
sudo mount --make-rprivate /mnt/jail

Isolate propagation inside a chroot, otherwise an umount inside drags the host along

§ см. также

  • mount-and-fstabmount and /etc/fstab: attaching filesystems`mount` attaches a block device or filesystem to a mount point in the tree. `/etc/fstab` is the list of what to mount at boot.
  • namespacesLinux namespacesNamespaces are a kernel mechanism that gives a process its own isolated view of a resource (network, mount points, PID, UID, IPC, hostname, time). Every container is built on them.
  • symbolic-linkSymbolic linkA symlink is a separate shortcut file that stores a path to its target. Unlike a [[hard-link]], it has its own [[inode]], and a symlink can point at anything, including something that does not exist.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies