git:20260827.43d4308 to git:20261030.eca5933

11 added, 0 removed. Audit B to B.

---
name: infra-proxmox-bindsnap
description: Use when snapshotting or cloning Proxmox LXC containers that have bind/device mounts (mpN -> host paths) - the snapshot button is greyed out or pct snapshot refuses the container, or pct clone fails with "unable to clone mountpoint 'mpN' (type bind)", or you cannot snapshot a bind-mount container. Covers pve-bindsnap install, verify, the BINDSNAP-FORCE-RUNNING / BINDSNAP-UNSUPPORTED / BINDSNAP-EXCLUDE markers, the checksum guard for an untested pve-container build, clone, and uninstall on a Proxmox VE node.
---
# proxmox-bindsnap
Install, verify, configure and operate **pve-bindsnap** -- a small Perl overlay that lets
Proxmox snapshot AND clone LXC containers that carry bind/device mounts (`mpN` pointing at
host paths), which stock Proxmox greys out or refuses with `unable to clone mountpoint
'mp0' (type bind)`. It delegates to Proxmox's real snapshot/clone code (it does not fork it)
by dpkg-diverting `PVE::LXC::Config` (snapshots) and `PVE::API2::LXC` (clone). Source:
https://github.com/bitranox/pve-bindsnap
**Run on the Proxmox VE node, as root.** If you are driving the node from elsewhere, prefix
each command with `ssh root@<node>`. All `pct`/`journalctl`/`perl` commands below run on the node.
## When to use
- A container with a bind mount can't be snapshotted (the GUI button is greyed out).
- `pct clone` / GUI Clone fails: `unable to clone mountpoint 'mpN' (type bind)`.
- You need scheduled snapshots of bind-mount CTs (e.g. cv4pve-autosnap).
- You want to clone a bind-mount CT and control whether the copy inherits the bind mounts.
**Not for:** containers without bind/device mounts (they already snapshot/clone stock -- the
overlay never touches them). If you only need a rootfs snapshot and not the GUI/scheduler,
plain `zfs snapshot <pool>/subvol-<vmid>-disk-0@name` on the stopped CT is simpler and needs none of this.
## 1. Install
The model is "read the source, then install from it." Inspect first:
```
curl -fsSL https://raw.githubusercontent.com/bitranox/pve-bindsnap/main/install.sh | less
```
Then install (one node; idempotent; restarts pvedaemon/pveproxy/pvestatd):
```
curl -fsSL https://raw.githubusercontent.com/bitranox/pve-bindsnap/main/install.sh | bash
```
Or clone and run locally: `git clone https://github.com/bitranox/pve-bindsnap && cd pve-bindsnap && less install.sh && ./install.sh`.
It installs the overlay module to `/usr/local/lib/site_perl`, adds two dpkg-diverts (Config.pm
and API2/LXC.pm) with thin wrappers, pre-flights the load, and rolls back automatically (EXIT
trap) if anything fails before the daemons restart -- so a failed install leaves the node stock.
## 2. Verify
Read the activation line from the journal:
```
journalctl -u pvedaemon -b --no-pager | grep pve-bindsnap | tail -3
```
- `overlay active (... checksum-validated ...)` and `clone overlay active (... checksum-validated ...)`
-> this pve-container build is tested; bind-mount snapshots and clones work with no keyword.
- `overlay active in TEST mode: ... is untested` -> build not in the table; bind-mount snapshots
are refused unless opted in (section 5), and `clone overlay loaded but NOT active` -> clone stays
stock (bind clones refused). See section 5 to get the build vetted.
Optional direct check:
```
perl -e 'require PVE::LXC::Config; require PVE::API2::LXC;
printf "APPLIED=%d CLONE_APPLIED=%d\n", $PVE::LXC::BindSnap::APPLIED, $PVE::LXC::BindSnap::CLONE_APPLIED'
```
## 3. Decision quick reference
| Situation | Do this |
|------------------------------------------------|--------------------------------------------------------------------|
| Snapshot a STOPPED bind-mount CT, tested build | Just `pct snapshot <vmid> <name>` |
| Snapshot a RUNNING CT | Add `BINDSNAP-FORCE-RUNNING` (section 4) |
| Build shows TEST mode / untested | Opt in with `BINDSNAP-UNSUPPORTED`, then get it vetted (section 5) |
+ | Need a safety net NOW on an untested build | `vzdump <vmid> --storage <store>`, snapshot mode (section 5) |
| Keep a managed data disk out of the snapshot | `BINDSNAP-EXCLUDE: mpN` in CT Notes (section 4) |
| Clone a bind-mount CT | `pct clone` works; binds are carried (section 6) |
| Clone must NOT inherit a bind/data mount | `BINDSNAP-EXCLUDE: mpN` in the SOURCE CT Notes |
## 4. Configure: the BINDSNAP- markers
All UPPERCASE and case-sensitive. The two booleans are read BOTH from a snapshot's name or
description (per-snapshot) AND as a standing line in the CT Notes (its description). They match
as their own token: a hyphen, underscore or space delimits them; gluing onto a letter/digit or
the wrong case does not match.
- **`BINDSNAP-FORCE-RUNNING`** -- snapshot a *running* CT (a running CT is otherwise refused; the
snapshot briefly freezes the filesystem, which can stall on FUSE/CIFS mounts). Standing form in
the CT Notes is the opt-in for schedulers that can't set a per-snapshot keyword. No standing risk.
Example: `pct snapshot 123 pre-change --description "BINDSNAP-FORCE-RUNNING"`.
- **`BINDSNAP-UNSUPPORTED`** -- snapshot on a pve-container build not in the tested table. Prefer
the per-snapshot form. A **standing** `BINDSNAP-UNSUPPORTED` in the Notes is RISKY: after a PVE
update to a future untested build it silently covers that too instead of re-gating. Do not leave
it long-term -- get the build vetted (section 5).
- **`BINDSNAP-EXCLUDE: mp1 mp2`** -- a line in the CT Notes (write it as `#### BINDSNAP-EXCLUDE: mp1`
so it renders small). ALWAYS needs the colon. A directive in a snapshot's own description
overrides the Notes default; an empty `BINDSNAP-EXCLUDE:` means exclude nothing. `rootfs` is
never excluded. NOTE the mirror behaviour: for a SNAPSHOT it drops named MANAGED volumes; for a
CLONE it drops named BIND/DEVICE mounts.
## 5. Snapshot, and the checksum guard
Stopped CT on a tested build: `pct snapshot <vmid> <name>` (or the GUI). Each snapshot/rollback/
delete writes a summary to the task log. Only bind-mount CTs are gated; plain CTs are untouched.
**What snapshot/rollback does to a bind/device mount -- setting vs data:** only the mount
*setting* (the `mpN`/`devN` config line) is captured in the snapshot and restored on rollback.
The mount is NEVER dropped or lost. The host *data* behind it is never snapshotted, cloned, or
rolled back: a rollback rewinds the managed volumes (rootfs and `volume` disks), but the
bind/device host data stays exactly as it is now, untouched. So a rollback is not a point-in-time
restore of what a bind mount points at -- only managed-volume data is versioned. (Bind data is
host data outside Proxmox storage; stock Proxmox never versions it either.)
The guard is a content checksum of the upstream Proxmox source (two SEPARATE guards: snapshot
hashes `Config.pm`+`AbstractConfig.pm`; clone hashes `API2/LXC.pm`). On an **untested** build,
bind snapshots are refused and clone stays stock. The correct response is NOT to force forever:
1. Opt in once with `BINDSNAP-UNSUPPORTED` to TEST (the task finishes as a yellow `TASK WARNINGS`).
2. Run the test plan: https://github.com/bitranox/pve-bindsnap/blob/main/docs/testing.md
3. Report the version + combined checksum (both printed by the overlay) at
https://github.com/bitranox/pve-bindsnap/issues so the build joins the known-good list -- after
which it works with no keyword.
Which builds count as vetted is decided by the overlay, not from memory: the journal line in
section 2 tells you about THIS node's build, and
https://github.com/bitranox/pve-bindsnap/blob/main/docs/compatible-versions.md is the
authoritative list. As of pve-bindsnap **1.2.0** it holds **pve-container 6.1.10 and 6.1.12**
for both guards. Mind that the snapshot checksum also covers `AbstractConfig.pm`, which ships in
`libpve-guest-common-perl` rather than in `pve-container`, so an apt upgrade of EITHER package
can move a node into TEST mode.
A **known-BAD** build is a hard block: `BINDSNAP-UNSUPPORTED` will NOT override it; update
pve-container or use `zfs snapshot` directly.
+
+ **A pre-change safety net on a build the guard refuses:** take a stock backup,
+ `vzdump <vmid> --storage <store>`. The overlay passes every `vzdump` call straight to stock code
+ on any build, tested, untested or known-BAD, and stock `vzdump` leaves bind and device mounts out
+ of the archive (their data is host data, outside Proxmox storage) and backs up only the rootfs and
+ the `volume` mount points marked `backup=1`. It needs no marker and no raw `zfs snapshot`. Keep
+ the default `--mode snapshot`; `--mode stop` stops the container for the backup and starts it
+ again, which re-runs everything the container does at boot. A boot unit that pulls and recreates
+ its containers then performs, before you are ready, the very change the backup was meant to
+ precede.
## 6. Clone
`pct clone <vmid> <newid>` of a bind-mount CT now works: managed volumes (rootfs and `volume`
`mpN`) clone as stock, and each bind/device mount is **carried to the clone unchanged -- pointing
at the SAME host path as the source** (not a copy). The clone task finishes as a yellow
`TASK WARNINGS` naming the carried mounts, because the two CTs then share that host data.
To stop the clone inheriting a bind/data mount, add `#### BINDSNAP-EXCLUDE: mp0` to the **source**
CT's Notes before cloning. A full clone of a RUNNING CT still needs `--snapname` (Proxmox rule):
snapshot it first with `BINDSNAP-FORCE-RUNNING`, then `pct clone <vmid> <newid> --snapname <snap>`.
## 7. Uninstall
```
curl -fsSL https://raw.githubusercontent.com/bitranox/pve-bindsnap/main/uninstall.sh | bash
```
Reverts both diverts and restores stock Proxmox. Snapshots you already took persist as zfs
snapshots and in the CT config (`zfs list -t snapshot | grep subvol-<vmid>`).
## Troubleshooting
| Symptom | Cause / fix |
|----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| Snapshot button greyed for a bind-mount CT | Not installed, or daemons not restarted. Install (section 1), verify (section 2). |
| `unable to clone mountpoint 'mpN' (type bind)` | Clone override not active: not installed, OR build untested (clone stays stock). Install / get the build vetted (section 5). |
| `CT <vmid> is running ... stop ... or BINDSNAP-FORCE-RUNNING` | Stop the CT, or add `BINDSNAP-FORCE-RUNNING` (section 4). |
| `pve-container <ver> is ... untested ... BINDSNAP-UNSUPPORTED` | Build not in the table. Opt in to TEST and get it vetted (section 5). |
| `on the overlay's known-BAD list ... BLOCKED` | Hard block; update pve-container or use `zfs snapshot`. |
| Clone inherited a data mount it should not have | Add `BINDSNAP-EXCLUDE: mpN` to the SOURCE CT Notes (section 6). |
| No `pve-bindsnap:` line in the journal | Banner only prints from a PVE daemon (not a TTY). Check `journalctl -u pvedaemon -b`; confirm `$APPLIED`/`$CLONE_APPLIED` (section 2). |
## Further reading
Self-contained above; for depth, read these (WebFetch the URL, or read the local clone if you have it):
| Topic | URL |
|--------------------------------------------|--------------------------------------------------------------------------------|
| Overview, install, "Using it" | https://github.com/bitranox/pve-bindsnap/blob/main/README.md |
| How it works, limits, mechanism | https://github.com/bitranox/pve-bindsnap/blob/main/docs/design.md |
| The checksum guard, adding a version | https://github.com/bitranox/pve-bindsnap/blob/main/docs/checksum-guard.md |
| Supported / hard-blocked / untested builds | https://github.com/bitranox/pve-bindsnap/blob/main/docs/compatible-versions.md |
| BINDSNAP-EXCLUDE in depth | https://github.com/bitranox/pve-bindsnap/blob/main/docs/bindsnap-exclude.md |
| On-node test plan | https://github.com/bitranox/pve-bindsnap/blob/main/docs/testing.md |