# 🛟 An Undo Button for Your Proxmox Box

**URL:** <https://onehack.st/t/an-undo-button-for-your-proxmox-box/325179>\
**Category:** Tools & Scripts\
**Tags:** freebies, backup, self-hosted-tools\
**Created:** [August 31, 2026, 8:07am UTC](https://onehack.st/t/an-undo-button-for-your-proxmox-box/325179 "2026-08-31T08:07:22Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![BCBC](https://onehack.st/user_avatar/onehack.st/bcbc/32/174133_2.png) [@BCBC](https://onehack.st/u/BCBC)\
**Post date:** [August 31, 2026, 8:07am UTC](https://onehack.st/t/an-undo-button-for-your-proxmox-box/325179/1 "2026-08-31T08:07:23Z")

</div>

## 📄 Full inspectable Bash script, list-only default, dry-run mode, manifest + log on every run, SHA-256 verified ZIP

Ever run a command on your Proxmox box and immediately think “…I should’ve snapshotted that first”? This is for exactly that moment — a small, inspectable toolkit that makes “undo” possible before you make the change.

```plaintext
BACK UP FOR REAL (vzdump, separate storage)
              ↓
   SNAPSHOT CHECKPOINT (this tool)
              ↓
     MANIFEST + LOG SAVED
              ↓
        MAKE YOUR CHANGE

```

⚠ **The trap this avoids:** a snapshot lives on the SAME storage as your container. If that disk dies, your “backup” dies with it. Snapshots are a fast rollback, not a real backup — this toolkit forces you to do a proper `vzdump` backup separately, first.

## 🔒 Why this one’s actually safe to run as root

- 📋 **Defaults to LIST-ONLY** — it won’t touch anything unless you explicitly pass `--all` or `--vmid`
- 🚫 **No auto-delete, ever** — old snapshots never get silently pruned. That’s a deliberate choice, not a missing feature.
- 👀 **Full source is right below** — you’re not trusting a black-box zip with root access on your hypervisor, read exactly what it does first
- ✅ **Actually tested** on a real 3-container Proxmox host — list, dry-run, real snapshot, manifest, verification all confirmed working
- 🧾 **Every run logs a manifest** — a paper trail of what got snapshotted and when, under `/var/log/bcbc-lxc-snapshots/`

## 🚀 Use it

```auto
sudo bcbc-lxc-snapshot list ← see what you've got, nothing changes
sudo bcbc-lxc-snapshot --all --dry-run ← preview what WOULD happen
sudo bcbc-lxc-snapshot --vmid 123 ← checkpoint one container
sudo bcbc-lxc-snapshot --all ← checkpoint everything listed

```

Install:

```auto
sudo install -m 0755 bcbc-lxc-snapshot /usr/local/sbin/bcbc-lxc-snapshot

```

## 🔐 Verify the download

SHA-256 of the release ZIP:

```auto
28cc3e74e8c3dc32ad37126ebb926eab478e5c442a1489073ad1ebf61011c43c

```

```auto
sha256sum BCBC-Proxmox-Backup-LXC-Snapshot-Safety-Toolkit-v1.0.0-2026-08-31.zip

```

A match confirms your download is byte-for-byte what got packaged and tested — it doesn’t prove the tool is safe on its own, so read the source below too.

> **📄 Full script source — bcbc-lxc-snapshot (read before you run it as root)**
>
> ```bash
> #!/usr/bin/env bash
> set -Eeuo pipefail
> 
> PREFIX="bcbc"
> MODE="list"
> VMID=""
> DRY_RUN=0
> LOG_DIR="/var/log/bcbc-lxc-snapshots"
> STAMP="$(date +%Y%m%d-%H%M%S)"
> RUNLOG="${LOG_DIR}/run-${STAMP}.log"
> MANIFEST="${LOG_DIR}/manifest-${STAMP}.tsv"
> 
> safe_name() {
> local s="$1"
> s="${s//[^A-Za-z0-9_-]/-}"
> printf '%s' "${s:0:30}"
> }
> 
> log() {
> printf '%s %s\n' "$(date '+%F %T%z')" "$*" | tee -a "$RUNLOG"
> }
> 
> need_root() {
> [[$EUID -eq 0]] || {
> echo "ERROR: run as root on the Proxmox host." >&2
> exit 1
> }
> }
> 
> need_cmds() {
> command -v pct >/dev/null || {
> echo "ERROR: pct not found. Run this on a Proxmox VE host." >&2
> exit 1
> }
> }
> 
> list_one() {
> local id="$1" name
> name="$(pct config "$id" 2>/dev/null | awk -F': ' '$1=="hostname"{print $2;exit}')"
> printf '\nCT %s %s\n' "$id" "${name:-unknown}"
> pct listsnapshot "$id" 2>/dev/null || echo " (no snapshots or listing unavailable)"
> }
> 
> list_all() {
> pct list
> while read -r id _; do
> [["$id" =~ ^[0-9]+$ ]] || continue
> list_one "$id"
> done < <(pct list | tail -n +2)
> }
> 
> snapshot_one() {
> local id="$1" name snap desc
> 
> pct status "$id" >/dev/null 2>&1 || {
> log "ERROR CT ${id}: not found"
> return 1
> }
> 
> name="$(pct config "$id" | awk -F': ' '$1=="hostname"{print $2;exit}')"
> name="$(safe_name "${name:-ct$id}")"
> snap="$(safe_name "${PREFIX}-${STAMP}")"
> desc="BCBC checkpoint ${STAMP} host=${HOSTNAME} ct=${id} name=${name}"
> 
> log "CT ${id} (${name}): creating snapshot ${snap}"
> 
> if (( DRY_RUN )); then
> log "DRY-RUN: pct snapshot ${id} ${snap} --description '${desc}'"
> printf '%s\t%s\t%s\t%s\tDRY-RUN\n' \
> "$STAMP" "$id" "$name" "$snap" >> "$MANIFEST"
> return 0
> fi
> 
> if pct snapshot "$id" "$snap" --description "$desc" >> "$RUNLOG" 2>&1; then
> log "SUCCESS CT ${id}: ${snap}"
> printf '%s\t%s\t%s\t%s\tSUCCESS\n' \
> "$STAMP" "$id" "$name" "$snap" >> "$MANIFEST"
> else
> log "FAILED CT ${id}: ${snap}"
> printf '%s\t%s\t%s\t%s\tFAILED\n' \
> "$STAMP" "$id" "$name" "$snap" >> "$MANIFEST"
> return 1
> fi
> }
> 
> while (($#)); do
> case "$1" in
> list)
> MODE="list"
> shift
> ;;
> --all)
> MODE="all"
> shift
> ;;
> --vmid)
> MODE="one"
> VMID="${2:-}"
> shift 2
> ;;
> --prefix)
> PREFIX="$(safe_name "${2:-bcbc}")"
> shift 2
> ;;
> --dry-run)
> DRY_RUN=1
> shift
> ;;
> -h|--help)
> cat <<'EOF'
> Usage:
> bcbc-lxc-snapshot list
> bcbc-lxc-snapshot --all [--dry-run] [--prefix NAME]
> bcbc-lxc-snapshot --vmid ID [--dry-run] [--prefix NAME]
> 
> Safety:
> Default action is LIST ONLY.
> No snapshot is created unless --all or --vmid is explicitly supplied.
> No pruning or deletion is implemented in this public starter.
> EOF
> exit 0
> ;;
> *)
> echo "Unknown option: $1" >&2
> exit 2
> ;;
> esac
> done
> 
> need_root
> need_cmds
> 
> mkdir -p "$LOG_DIR"
> touch "$RUNLOG" "$MANIFEST"
> chmod 750 "$LOG_DIR"
> chmod 640 "$RUNLOG" "$MANIFEST"
> 
> if [["$MODE" == "list"]]; then
> list_all
> exit 0
> fi
> 
> fail=0
> 
> if [["$MODE" == "one"]]; then
> [["$VMID" =~ ^[0-9]+$ ]] || {
> echo "ERROR: --vmid requires a numeric container ID." >&2
> exit 2
> }
> snapshot_one "$VMID" || fail=1
> else
> mapfile -t ids < <(pct list | awk 'NR>1 && $1~/^[0-9]+$/{print $1}')
> for id in "${ids[@]}"; do
> snapshot_one "$id" || fail=1
> done
> fi
> 
> log "Manifest: ${MANIFEST}"
> log "Run log: ${RUNLOG}"
> exit "$fail"
> 
> ```

Also in the ZIP: a single self-contained HTML guide, no framework or external JS needed, works offline.

**Download:** [BCBC-Proxmox-Backup-LXC-Snapshot-Safety-Toolkit-v1.0.0-2026-08-31.zip](https://onehack.st/uploads/short-url/q6lYIpUSuLsNbJ4Ph0Vpb4W2qYe.zip) (8.8 KB)
