"title":"Restoring a backup — full and custom flows | ProxMenux",
"description":"The complete restore workflow. Documents the three actions available on any backup (view, download, restore), the compatibility check and its outcomes, the Full and Custom restore modes, the path classification that decides what applies live and what waits for the next boot, the on-boot dispatcher, and the post-boot component reinstall pass.",
"ogTitle":"ProxMenux Backup — restoring",
"ogDescription":"Full and custom restore flows with the compatibility check, path classification, on-boot dispatcher and post-boot reinstall.",
"twitterTitle":"Restoring a backup | ProxMenux",
"twitterDescription":"How a ProxMenux host backup is turned back into a working Proxmox host."
},
"header":{
"title":"Restoring a backup",
"description":"The full restore workflow: from picking an archive to a working host. Documents the compatibility check, the two restore modes, the on-boot dispatcher, the post-boot reinstall pass, and the mechanisms that make cross-host and cross-kernel restores predictable.",
"section":"Backup & Restore"
},
"intro":{
"title":"The restore reproduces the source, not just the files",
"body":"Restoring a ProxMenux backup is not an extraction. Files are only the first step: after the filesystem is in place, the restore reads the manifest to detect differences between source and target, filters paths that would break the target's boot, hydrates operator-authored tuning that cannot be copied verbatim, and — after the mandatory reboot — reinstalls every component the source had (NVIDIA driver, Coral TPU, GPU tools) against the target's own kernel. What the operator picks from the menu is a single archive; what actually happens involves the compatibility check, the path classification, the on-boot dispatcher and the post-boot pass working together to produce a host that behaves like the source."
},
"threeActions":{
"heading":"Three actions on a backup",
"intro":"Selecting a backup from the list opens a menu with three actions.",
"detail":"Opens a read-only view of the archive: manifest.json contents (source hostname, PVE version, kernel, hardware, installed components), the list of paths inside <code>rootfs/</code>, and a diff of what would change on the current host if the backup were applied."
},
{
"action":"Download",
"detail":"Exports the archive as a portable <code>.tar.zst</code> file (tar compressed with zstd). It can be extracted on any Linux system with <code>tar --zstd -xf FILE.tar.zst</code>, or on macOS/Windows with any tool that supports zstd (7-Zip, PeaZip, Keka…). The extracted tree contains <code>manifest.json</code>, <code>metadata/</code> and <code>rootfs/</code> — exactly the same layout the restore consumes. Useful for offline inspection or for restoring on a host without access to the original destination (PBS, Borg)."
},
{
"action":"Restore",
"detail":"The write path. Extracts the archive into a staging directory, runs the compatibility check, and presents the mode picker (Full or Custom)."
"intro":"Before any file is written, <code>hb_compat_check</code> compares the state described in the manifest against the target host. The check runs read-only and produces four independent outputs that drive the rest of the restore.",
"detail":"<code>HB_COMPAT_KERNEL_DIRECTION</code> — one of <code>same</code>, <code>bk_newer</code> or <code>bk_older</code>. Compares the backup's major kernel version against the target's. Drives the cross-kernel safe-subset filter (only fires on <code>bk_older</code>) and the hydration pass documented on the cross-kernel page."
},
{
"output":"Skip-paths list",
"detail":"<code>RS_SKIP_PATHS</code> — every path the restore must NOT apply. Populated by two mechanisms: hardware drift (missing NIC, missing storage ID, foreign ZFS pool) and — when the direction is <code>bk_older</code> — the cross-kernel unsafe-paths list."
},
{
"output":"NIC remap plan",
"detail":"When a NIC on the target has the same MAC as one on the source but a different name (typical after a motherboard swap), the compatibility check registers a rename plan (<code>HB_NIC_REMAP</code>) that will rewrite <code>/etc/network/interfaces</code> during the restore."
},
{
"output":"Rollback plan",
"detail":"Computed by <code>compute_rollback_plan.sh</code>. Lists VMs, LXCs and components present on the target but not in the backup. The operator opts in during the confirmation dialog to have these removed as part of the restore, so the target ends up matching the backup exactly."
"reportBody":"The check also emits a structured report (<code>HB_COMPAT_RESULTS</code>) categorised as PASS / INFO / WARN / FAIL. WARN and FAIL entries surface in the pre-restore panel; the restore refuses to proceed only when a FAIL is present that the operator cannot resolve by clicking Continue."
},
"twoModes":{
"heading":"Full restore vs Custom restore",
"intro":"Once the compatibility check is complete, the restore mode menu appears. The choice determines <em>what</em> is applied, not <em>how</em> — both modes share the same underlying pipeline.",
"detail":"Applies every path in the archive that survives the drift and cross-kernel filters. Also runs the package install and the component auto-reinstall pass. This is the default and the recommended choice — the goal is to reproduce the source, not pick pieces."
},
{
"mode":"Custom restore",
"detail":"Opens a checklist showing every path the archive carries. The operator ticks a subset. Paths blocked by the cross-kernel filter appear greyed out and cannot be selected. Package install and component auto-reinstall are skipped by default in Custom mode — the operator is signalling that they want partial application, not a full reproduction."
"intro":"Every path selected for the restore is classified by <code>hb_classify_path</code> into one of three categories. The category determines when the path is applied to the system and why.",
"detail":"Paths applied <strong>immediately</strong> to the running system. The service that consumes them picks up the change on its own or at the next reload — no reboot required. These are the bulk of a backup: <code>/etc/ssh</code>, <code>/etc/apt</code>, <code>/etc/cron.*</code>, <code>/root</code>, <code>/usr/local/bin</code>, general service configuration files, etc."
},
{
"class":"reboot",
"detail":"Paths applied <strong>immediately</strong> as well, but whose actual effect only kicks in on the <strong>next boot</strong>: the kernel only reads <code>/etc/default/grub</code> when the bootloader starts, <code>/etc/fstab</code> when filesystems are mounted at boot, <code>/etc/modules</code> when modules are loaded, etc. The file is in place the moment it is applied but the system has to reboot to consume it. Examples: <code>/etc/default/grub</code>, <code>/etc/kernel</code>, <code>/etc/modules</code>, <code>/etc/fstab</code>, <code>/etc/zfs</code>, <code>/etc/initramfs-tools</code>."
},
{
"class":"dangerous",
"detail":"Paths that are <strong>NOT applied on the running system</strong> — a live write could corrupt state or drop the active connection. These are staged in the pending set and written by the post-boot dispatcher after the reboot, when the cluster is up but the system is not yet fully in use. Examples: <code>/etc/pve</code> (pmxcfs is a live FUSE mount; writing directly to it bypasses it), <code>/var/lib/pve-cluster</code> (live cluster data), <code>/etc/network</code> (could reconfigure the very interface the user is connected on over SSH and drop the session)."
"intro":"The complete pipeline from archive selection to a working restored host. Each stage feeds the next; the state written by earlier stages is consumed by later ones.",