# Backup and Restore

## Purpose

This page documents the backup and restore process for Bytek VMs, LXCs, application data, and configuration.

The current backup system protects against:

<div id="bkmrk-failed-upgrades.-bro" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Failed upgrades.
- Broken configuration changes.
- Guest operating-system corruption.
- Accidental deletion.
- Application database damage.
- Failure of a production NVMe disk, provided the backup HDD remains healthy.

</div>The current backup system does not fully protect against:

<div id="bkmrk-fire.-theft.-complet" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Fire.
- Theft.
- Complete host destruction.
- Electrical damage affecting the entire server.
- Compromise of both production and backup storage.
- Failure of the backup HDD before another copy exists.

---

</div>## Backup Storage

<div id="bkmrk-setting-value-proxmo" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;"><div aria-expanded="false" class="___5wvz9a0 ftgm304 f1oy3dpc fm6nont f48hbct" data-stable-ignore="true" data-tabster="{"restorer":{"type":1}}" role="presentation" tabindex="0"><div class="___1dmoc29 f10pi13n ftgm304 f1enuhaj fdclmfp f1nbblvp fat0sn4 f1ov4xf1 fekwl8i f1lmfglv f1oz7aqm f1abmfm4 f1w619qj f16h0jq8"><table class="___1vyiefv f1ddd56o f16vktn6 f1ahpp82 f11qra4b f1uinfot fibjyge fvueend f9yszdx f1fu4s3n f3l3pb3 f10ghnd0 f8fmt76 fjvbh62 f1qrqxae f1vw5qpk fc02sbz fxawf59 fymf513 f1aoyrul f1el8yx3 f1pymoxg f1ofu761 fe6itr f7coize f1794535 f1o0pw0q fbjjl9v fk1v6el f16pyhcb f1ixlhx9 f12zef0i flu5r5u f19haqzy f1owmcxx f1oddm8q f1004tna fcoaxci fh0ee9u f15v23i2 f1dmj53 f1r1gcv9 f14z1veh ffufd3x f1ypplot f1660cg"><tbody><tr><th>Setting</th><th>Value</th></tr><tr><td>Proxmox storage ID</td><td>`pve-backup`</td></tr><tr><td>Mount point</td><td>`/mnt/pve/pve-backup`</td></tr><tr><td>Physical disk</td><td>`/dev/sda`</td></tr><tr><td>Partition</td><td>`/dev/sda1`</td></tr><tr><td>Filesystem</td><td>ext4</td></tr><tr><td>Approximate capacity</td><td>4 TB</td></tr><tr><td>Content type</td><td>VZDump backup files</td></tr><tr><td>Mount protection</td><td>Enabled</td></tr><tr><td>Current location</td><td>Same physical Proxmox server</td></tr></tbody></table>

</div></div></div>The backup HDD is dedicated to Proxmox backups.

Do not use the backup HDD for:

<div id="bkmrk-active-vm-disks.-nex" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Active VM disks.
- Nextcloud user data.
- Plex media.
- Game-server data.
- Docker application data.
- Temporary downloads.
- General file storage.

---

</div>## Mount Validation

Before relying on a backup job, confirm that the backup HDD is mounted.

Use:

`findmnt /mnt/pve/pve-backup`

The source should be `/dev/sda1`.

Check capacity using:

`df -h /mnt/pve/pve-backup`

Check Proxmox storage state using:

`pvesm status`

The `pve-backup` storage must show as active.

Mount-point protection prevents Proxmox from writing backup archives into the empty mount directory on the Proxmox root filesystem if the HDD is unavailable.

<div id="bkmrk-" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Scheduled Backup Policy

<div id="bkmrk-setting-recommended-" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;"><div aria-expanded="false" class="___5wvz9a0 ftgm304 f1oy3dpc fm6nont f48hbct" data-stable-ignore="true" data-tabster="{"restorer":{"type":1}}" role="presentation" tabindex="0"><div class="___1dmoc29 f10pi13n ftgm304 f1enuhaj fdclmfp f1nbblvp fat0sn4 f1ov4xf1 fekwl8i f1lmfglv f1oz7aqm f1abmfm4 f1w619qj f16h0jq8"><table class="___1vyiefv f1ddd56o f16vktn6 f1ahpp82 f11qra4b f1uinfot fibjyge fvueend f9yszdx f1fu4s3n f3l3pb3 f10ghnd0 f8fmt76 fjvbh62 f1qrqxae f1vw5qpk fc02sbz fxawf59 fymf513 f1aoyrul f1el8yx3 f1pymoxg f1ofu761 fe6itr f7coize f1794535 f1o0pw0q fbjjl9v fk1v6el f16pyhcb f1ixlhx9 f12zef0i flu5r5u f19haqzy f1owmcxx f1oddm8q f1004tna fcoaxci fh0ee9u f15v23i2 f1dmj53 f1r1gcv9 f14z1veh ffufd3x f1ypplot f1660cg"><tbody><tr><th>Setting</th><th>Recommended Value</th></tr><tr><td>Storage</td><td>`pve-backup`</td></tr><tr><td>Compression</td><td>ZSTD</td></tr><tr><td>General backup mode</td><td>Snapshot</td></tr><tr><td>Initial application baseline</td><td>Stop mode where practical</td></tr><tr><td>Selection</td><td>All production VMs and LXCs</td></tr><tr><td>Notification</td><td>Configure for failed jobs</td></tr></tbody></table>

</div></div></div>Recommended retention:

<div id="bkmrk-retention-rule-count" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;"><div aria-expanded="false" class="___5wvz9a0 ftgm304 f1oy3dpc fm6nont f48hbct" data-stable-ignore="true" data-tabster="{"restorer":{"type":1}}" role="presentation" tabindex="0"><div class="___1dmoc29 f10pi13n ftgm304 f1enuhaj fdclmfp f1nbblvp fat0sn4 f1ov4xf1 fekwl8i f1lmfglv f1oz7aqm f1abmfm4 f1w619qj f16h0jq8"><table class="___1vyiefv f1ddd56o f16vktn6 f1ahpp82 f11qra4b f1uinfot fibjyge fvueend f9yszdx f1fu4s3n f3l3pb3 f10ghnd0 f8fmt76 fjvbh62 f1qrqxae f1vw5qpk fc02sbz fxawf59 fymf513 f1aoyrul f1el8yx3 f1pymoxg f1ofu761 fe6itr f7coize f1794535 f1o0pw0q fbjjl9v fk1v6el f16pyhcb f1ixlhx9 f12zef0i flu5r5u f19haqzy f1owmcxx f1oddm8q f1004tna fcoaxci fh0ee9u f15v23i2 f1dmj53 f1r1gcv9 f14z1veh ffufd3x f1ypplot f1660cg"><tbody><tr><th>Retention Rule</th><th>Count</th></tr><tr><td>Keep last</td><td>3</td></tr><tr><td>Keep daily</td><td>7</td></tr><tr><td>Keep weekly</td><td>4</td></tr><tr><td>Keep monthly</td><td>3</td></tr></tbody></table>

</div></div></div>Retention must be adjusted if the backup HDD approaches capacity.

<div id="bkmrk--1" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Backup Modes

### Snapshot Mode

Use snapshot mode for normal scheduled backups when minimizing downtime is important.

Snapshot mode is appropriate for:

<div id="bkmrk-infrastructure-servi" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Infrastructure services.
- Stateless or lightly written services.
- Routine nightly backups.
- Applications with guest-agent filesystem freeze support.

</div>### Stop Mode

Use stop mode for the strongest whole-VM consistency when brief downtime is acceptable.

Stop mode is recommended for:

<div id="bkmrk-initial-known-good-b" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Initial known-good baselines.
- Database-heavy services before major changes.
- Backups taken before risky upgrades.
- Plex or other VMs with PCI passthrough when snapshot behavior is limited.
- Applications where exact application consistency is more important than continuous availability.

</div>### Suspend Mode

Suspend mode is not the preferred mode for the current environment.

<div id="bkmrk--2" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## QEMU Guest Agent

VMs should have the QEMU Guest Agent enabled.

Check a VM configuration using:

`qm config <VMID>`

The configuration should include the guest agent.

Test guest-agent communication using:

`qm guest cmd <VMID> ping`

Expected result:

<div id="bkmrk-an-empty-successful-" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- An empty successful response.

</div>Inside the VM, verify:

`systemctl is-active qemu-guest-agent`

Expected result:

<div id="bkmrk-active" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `active`

</div>The guest agent improves guest coordination during snapshot-mode backups.

<div id="bkmrk--3" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Disk Inclusion

A VM disk is included in backup by default unless its configuration contains:

`backup=0`

Review a VM using:

`qm config <VMID>`

Confirm every required operating-system and application-data disk is included.

For Nextcloud, both of these must be included:

<div id="bkmrk-the-64-gb-operating-" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- The 64 GB operating-system disk.
- The 500 GB user-data disk.

</div>Large replaceable media disks may eventually be excluded, but only after the exclusion is documented and the application configuration remains protected elsewhere.

<div id="bkmrk--4" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Service Backup Coverage

### Proxmox Host

The normal guest backup job does not back up the Proxmox host operating system.

Preserve separately:

<div id="bkmrk-%2Fetc%2Fpve-network-con" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `/etc/pve`
- Network configuration.
- Storage configuration.
- Firewall configuration.
- Authentik realm settings.
- Backup-mount configuration.
- VM and LXC inventory.
- Recovery credentials.

</div>### WireGuard Gateway

Protect:

<div id="bkmrk-wireguard-configurat" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- WireGuard configuration.
- Private and public keys.
- Peer definitions.
- Firewall rules.
- NAT rules.
- SSH configuration.
- Network configuration.

</div>Private keys must remain in encrypted storage, not in BookStack.

### Pi-hole

Protect:

<div id="bkmrk-local-dns-records.-d" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Local DNS records.
- DHCP reservations.
- Pi-hole configuration.
- Allow and deny lists.
- Upstream DNS settings.
- LXC network configuration.

</div>A Pi-hole configuration export may supplement the Proxmox backup.

### Traefik

Protect:

<div id="bkmrk-%2Fopt%2Ftraefik%2Fcompose" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `/opt/traefik/compose.yml`
- `/opt/traefik/traefik.yml`
- `/opt/traefik/.env`
- `/opt/traefik/dynamic/`
- `/opt/traefik/data/acme.json`
- Any Basic Auth files.
- Certificate API configuration.

</div>Never delete `acme.json` during normal troubleshooting.

### Authentik

Protect:

<div id="bkmrk-postgresql-data.-red" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- PostgreSQL data.
- Redis configuration.
- Compose configuration.
- Environment file.
- Signing keys.
- Applications.
- Providers.
- Policies.
- Groups.
- Outpost configuration.
- Custom templates and media.

</div>PostgreSQL is the authoritative data source for the Authentik configuration.

### Uptime Kuma

Protect:

<div id="bkmrk-persistent-%2Fapp%2Fdata" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Persistent `/app/data`.
- Embedded database.
- Monitor configuration.
- Notification configuration.
- Status pages.
- Compose file.
- Uploaded assets.

</div>### Nextcloud AIO

Protect:

<div id="bkmrk-64-gb-operating-syst" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- 64 GB operating-system disk.
- 500 GB user-data disk.
- AIO master-container configuration.
- PostgreSQL.
- Redis.
- Nextcloud configuration.
- User files.
- Collabora configuration.

</div>The AIO Borg repository is currently unconfigured because no separate backup destination is available.

### Vikunja

Protect:

<div id="bkmrk-%2Fopt%2Fvikunja%2Fpostgre" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `/opt/vikunja/postgres`
- `/opt/vikunja/files`
- `/opt/vikunja/config.yml`
- `/opt/vikunja/.env`
- `/opt/vikunja/compose.yml`

</div>### BookStack

Protect:

<div id="bkmrk-%2Fopt%2Fbookstack%2Fapp-%2F" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `/opt/bookstack/app`
- `/opt/bookstack/database`
- `/opt/bookstack/.env`
- `/opt/bookstack/compose.yml`
- BookStack application key.
- Uploaded images and attachments.
- Themes and configuration.

</div>The BookStack application key and database must be restored together.

<div id="bkmrk--5" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Application-Level Database Exports

Application-level exports supplement the whole-VM backup.

They do not replace the Proxmox backup.

### Vikunja PostgreSQL

Run from `/opt/vikunja`:

`sudo docker compose exec -T db pg_dump -U vikunja vikunja > vikunja-backup.sql`

### BookStack MariaDB

Run from `/opt/bookstack` using the database service and credentials defined in the Compose environment.

Prompt for the database password rather than placing the password directly in shell history.

Database exports contain sensitive application data.

Store exports securely and remove obsolete copies.

<div id="bkmrk--6" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Manual Baseline Backup

Create a manual backup before:

<div id="bkmrk-major-upgrades.-auth" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Major upgrades.
- Authentication changes.
- Database migrations.
- GPU passthrough.
- Major firewall changes.
- Storage changes.
- Disabling a local authentication method.
- Removing an old service.

</div>Example pattern:

`vzdump <VMID> --storage pve-backup --mode stop --compress zstd`

Confirm the task ends with:

<div id="bkmrk-task-ok" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `TASK OK`

</div>List the backup storage using:

`pvesm list pve-backup`

<div id="bkmrk--7" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Restore-Test Procedure

A backup is not fully trusted until it has been restored and inspected.

<div id="bkmrk-select-a-recent-back" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">1. Select a recent backup.
2. Restore to a new VM or LXC ID.
3. Choose an appropriate target storage.
4. Disconnect the restored guest network adapter.
5. Start the restored guest using the Proxmox console.
6. Confirm the operating system starts.
7. Confirm expected disks are present.
8. Confirm expected filesystems are mounted.
9. Confirm Docker starts.
10. Confirm application containers exist.
11. Confirm the database is available.
12. Confirm persistent application data exists.
13. Shut down the restored clone.
14. Delete the test clone after documenting the result.

</div>Do not start a restored clone on the live LAN while the production guest is active.

The clone may contain the same:

<div id="bkmrk-ip-address.-hostname" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- IP address.
- Hostname.
- DHCP identity.
- Application identity.
- Database.
- OIDC configuration.
- Scheduled tasks.

---

</div>## Nextcloud Restore Test

For Nextcloud, confirm:

<div id="bkmrk-the-64-gb-os-disk-re" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- The 64 GB OS disk restored.
- The 500 GB data disk restored.
- `/mnt/nextcloud-data` is mounted.
- `/mnt/nextcloud-data/ncdata` exists.
- Docker is active.
- AIO containers exist.
- User data is present.

</div>Keep the network adapter disconnected during inspection.

<div id="bkmrk--8" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Backup Monitoring

Monitor:

<div id="bkmrk-backup-job-success.-" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Backup job success.
- Backup-HDD mount.
- Backup-HDD free space.
- SMART health.
- Thin-pool usage.
- Backup duration.
- Unexpected backup-size growth.
- Failed guest-agent operations.

</div>Useful checks:

<div id="bkmrk-pvesm-status-df--h-%2F" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `pvesm status`
- `df -h /mnt/pve/pve-backup`
- `findmnt /mnt/pve/pve-backup`
- `smartctl -H /dev/disk/by-id/wwn-0x5000cca097c44d7e`

---

</div>## Backup-HDD Health

Stable device identifier:

`/dev/disk/by-id/wwn-0x5000cca097c44d7e`

Review:

<div id="bkmrk-overall-smart-health" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Overall SMART health.
- Reallocated sectors.
- Pending sectors.
- Offline uncorrectable sectors.
- CRC errors.
- Temperature.
- SMART error log.

</div>Pending or uncorrectable sectors require immediate investigation.

<div id="bkmrk--9" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Backup Failure Response

If a backup job fails:

<div id="bkmrk-read-the-proxmox-tas" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">1. Read the Proxmox task log.
2. Confirm `pve-backup` is mounted.
3. Confirm free space.
4. Confirm the guest exists.
5. Confirm all required storage is active.
6. Confirm the QEMU Guest Agent where applicable.
7. Confirm the VM is not locked.
8. Confirm no previous backup task is stuck.
9. Resolve the specific error.
10. Run a manual test backup.
11. Confirm `TASK OK`.
12. Document the failure and correction.

</div>Do not repeatedly rerun a failing job without reading the task log.

<div id="bkmrk--10" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Current Limitations

The current backup architecture has two copies:

<div id="bkmrk-live-production-data" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">1. Live production data.
2. Local backup archives on the internal HDD.

</div>Both copies remain:

<div id="bkmrk-in-the-same-physical" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- In the same physical server.
- In the same building.
- On the same electrical system.
- Under the same administrative control.

</div>A future third copy should use:

<div id="bkmrk-a-trusted-remote-ser" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- A trusted remote server.
- A dedicated Proxmox Backup Server.
- Encrypted Borg.
- Encrypted Restic.
- Remote PBS synchronization.
- Another physically separate destination.

---

</div>## Validation Checklist

<div id="bkmrk-pve-backup-is-mounte" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `pve-backup` is mounted.
- `pve-backup` is active in Proxmox.
- Backup HDD has sufficient free space.
- SMART health is acceptable.
- Nightly backup job is enabled.
- Retention is configured.
- Every production guest is included.
- Required virtual disks are included.
- Nextcloud OS and data disks are included.
- Backup-failure notifications are configured.
- A recent manual backup completed with `TASK OK`.
- A restored VM was tested offline.
- Recovery credentials are stored securely.
- Offsite backup remains documented as outstanding work.

---

</div>## Document Control

<div id="bkmrk-owner%3A-bryan-gagne-p" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- **Owner:** Bryan Gagne-Plante
- **Backup storage:** `pve-backup`
- **Mount point:** `/mnt/pve/pve-backup`
- **Physical backup disk:** 4 TB HDD
- **Compression:** ZSTD
- **Routine mode:** Snapshot
- **Baseline mode:** Stop where practical
- **Offsite backup:** Not configured
- **Last verified:** YYYY-MM-DD
- **Last successful scheduled backup:** YYYY-MM-DD
- **Last manual baseline:** YYYY-MM-DD
- **Last restore test:** YYYY-MM-DD
- **Last SMART review:** YYYY-MM-DD
- **Known limitation:** Backup and production storage remain in one physical server

</div>