Proxmox: fix "cannot migrate local bind mount point"

In short. pct migrate refuses a container with a bind mount because it has no way to know that the host directory behind mp0 exists on the other node. The fix is not a flag. Mount the same CephFS path on every node with a systemd mount unit, verify it is there, and only then mark the mount point shared=1 so Proxmox stops asking. The flag is a promise; the mount units are what make it true.

"ERROR: migration aborted: cannot migrate local bind mount point 'mp0'"

You run pct migrate 101 pve02 or the HA manager tries to move a container during node maintenance, and the task log ends with:

2026-07-23 14:02:11 ERROR: migration aborted (duration 00:00:00): cannot migrate local bind mount point 'mp0'

For a disk on shared storage, Proxmox knows the target can see it because the storage definition says so. A bind mount is an arbitrary host path. Proxmox cannot check it, so it refuses, unless the mount point entry carries shared=1, which tells it you have taken responsibility for that path existing on every node. If you set the flag without doing the work, the container starts on the target with an empty directory where its data should be, and the application writes happily into the root disk.

What you need

Steps

  1. Find the mount point and the host path in the container config.
pct config 101 | grep '^mp'
# mp0: /mnt/cephfs/files/tenant7,mp=/data
  1. On every node, create an empty mount point and make it immutable, so a failed mount refuses writes instead of silently accepting them on the root filesystem.
mkdir -p /mnt/cephfs/files/tenant7
chattr +i /mnt/cephfs/files/tenant7
  1. On every node, create the systemd mount unit. The unit name must match the path with slashes turned into dashes. It is ordered before pve-guests.service, and RequiredBy makes guest startup depend on it.
# /etc/systemd/system/mnt-cephfs-files-tenant7.mount
[Unit]
Description=CephFS subvolume files/tenant7
After=network-online.target
Wants=network-online.target
Before=pve-guests.service

[Mount]
What=10.1.5.51,10.1.5.52,10.1.5.53:/volumes/files/tenant7/9a1c2d3e-0000-4000-8000-000000000001
Where=/mnt/cephfs/files/tenant7
Type=ceph
Options=name=files-tenant7,secretfile=/etc/ceph/files-tenant7.secret,fs=cephfs,_netdev

[Install]
RequiredBy=pve-guests.service
  1. Enable it on every node and confirm it mounted.
systemctl daemon-reload
systemctl enable --now mnt-cephfs-files-tenant7.mount
findmnt /mnt/cephfs/files/tenant7
  1. Only now set shared=1. pct set --mp0 replaces the whole entry, so repeat every option you want to keep.
pct set 101 --mp0 /mnt/cephfs/files/tenant7,mp=/data,shared=1
  1. Migrate. Containers cannot live-migrate, so pct migrate needs the container stopped or --restart. If the container is HA-enrolled, ask the HA manager instead, which stops, moves and starts it for you.
pct migrate 101 pve02 --restart
# or, for an HA resource
ha-manager migrate ct:101 pve02
flowchart LR
  CFS["CephFS subvolume<br/>/volumes/files/tenant7"]
  CFS --> N1["pve01<br/>mount unit, chattr +i"]
  CFS --> N2["pve02<br/>mount unit, chattr +i"]
  CFS --> N3["pve03<br/>mount unit, chattr +i"]
  N1 -- "mp0 shared=1" --> CT["CT 101<br/>/data"]
  CT -. "pct migrate" .-> N2

Verify it worked

Check from both sides. On the target node, confirm the container is running and that /data inside it reports the subvolume quota, not the size of the node's root disk:

pct status 101
pct exec 101 -- df -h /data

Then write a file from inside the container and read it on the host path of a third node. If it is visible there, every node really is looking at the same directory.

pct exec 101 -- sh -c 'date > /data/.migrate-check'
ssh pve03 cat /mnt/cephfs/files/tenant7/.migrate-check

Finally, check the target was ready before the move, not after: systemctl is-active mnt-cephfs-files-tenant7.mount on the node you intend to move to is a two-second habit that saves a restore.

Gotchas

FAQ

Can I just add shared=1 and skip the mount units? You can, and the migration will succeed, and the container will start on the target with an empty /data. The application will treat it as a fresh install. The option exists because Proxmox cannot know what your host path is; it is not a way to move data.

Why not mount CephFS inside the container instead? An unprivileged container holding a Ceph key can see the monitors and whatever the key allows. The point of the bind mount is that the container has no Ceph identity at all, and the key on the node is scoped to one subvolume path. The decision post below goes into why.

Does vzdump back up the bind mount? No. vzdump skips bind mounts by design, which is why the container backup stays small. The data is backed up separately from a CephFS snapshot with the backup client, on its own schedule.

Related