Skip to content

Instantly share code, notes, and snippets.

@mrpeardotnet
Created December 17, 2019 18:03
Show Gist options
  • Save mrpeardotnet/6bdc4b504f43ce57fa7eaee96d376edf to your computer and use it in GitHub Desktop.
Save mrpeardotnet/6bdc4b504f43ce57fa7eaee96d376edf to your computer and use it in GitHub Desktop.
Proxmox PVE Host Config Backup Script

Proxmox PVE Host Config Backup Script

This script can be used to backup essential configuration files from the Proxmox Virtual Enivronment (PVE) host.

The script will create backups using tar with specified backup prefix and date and time stamp in the file name. Script will also delete backups that are older then number of days specified.

Create backup script file

To create backup script that will be executed every day we can create backup script in /etc/cron.daily/ folder. We need to make it writeable by root (creator) only, but readable and executable by everyone:

touch /etc/cron.daily/pvehost-backup
chmod 755 /etc/cron.daily/pvehost-backup

Copy and paste following script into the created file (e.g. using vim.tiny):

#!/bin/sh
BACKUP_PATH="/var/tmp/"
BACKUP_FILE="pve-host"
KEEP_DAYS=7
PVE_BACKUP_SET="/etc/pve/ /etc/lvm/ /etc/modprobe.d/ /etc/network/interfaces /etc/vzdump.conf /etc/sysctl.conf /etc/resolv.conf /etc/ksmtuned.conf /etc/hosts /etc/hostname /etc/cron* /etc/aliases"
PVE_CUSTOM_BACKUP_SET="/etc/apcupsd/ /etc/multipath/ /etc/multipath.conf"

tar -czf $BACKUP_PATH$BACKUP_FILE-$(date +%Y_%m_%d-%H_%M_%S).tar.gz --absolute-names $PVE_BACKUP_SET $PVE_CUSTOM_BACKUP_SET
find $BACKUP_PATH$BACKUP_FILE-* -mindepth 0 -maxdepth 0 -depth -mtime +$KEEP_DAYS -delete

Note: Please modify the PVE_CUSTOM_BACKUP_SET variable to fit your PVE host needs. You can leave it as empty string ("") if no host specific configuration is needed.

Don't forget to change path where to store backups, the best way is to store backups outside physical host, e.g. on attached NAS storage.

Modify variables

You can modify variables to fit backups for your individual hosts:

  • BACKUP_PATH to specifiy where to store backups,
  • BACKUP_FILE to specify backups file prefix,
  • KEEP_DAYS to specify how many old backups to keep (in days)
  • PVE_CUSTOM_BACKUP_SET to add your installation specific folders and/or files,
  • PVE_BACKUP_SET defines standard set of folders and config files for generic PVE host.
@supperka
Copy link

nice, I have update it with storing the backup inside a virtual disk.

#!/bin/sh
# touch /etc/cron.daily/pvehost-backup
# chmod 755 /etc/cron.daily/pvehost-backup

#BACKUP_PATH="/var/tmp/"
BACKUP_FILE="pve-host"
KEEP_DAYS=7
PVE_BACKUP_SET="/etc/pve/ /etc/lvm/ /etc/modprobe.d/ /etc/network/interfaces \
    /etc/vzdump.conf /etc/sysctl.conf /etc/resolv.conf /etc/ksmtuned.conf \
    /etc/hosts /etc/hostname /etc/cron* /etc/aliases /var/lib/pve*"
PVE_CUSTOM_BACKUP_SET=""

# storing the backups inside of disk image file:
DISK_LOCATION="/mnt/pve/usb-raid/images/104/vm-104-disk-0.raw"
DISK_MOUNTP="/mnt/tmpdisk"
losetup -fP $DISK_LOCATION
LOOPDEV=$(losetup -l | grep $DISK_LOCATION | awk '{print $1}')
mount $LOOPDEV $DISK_MOUNTP
BACKUP_PATH="$DISK_MOUNTP/bcpstorage/pvehost"
mkdir -p $BACKUP_PATH

tar -czf $BACKUP_PATH$BACKUP_FILE-$(date +%Y_%m_%d-%H_%M_%S).tar.gz \
    --absolute-names $PVE_BACKUP_SET $PVE_CUSTOM_BACKUP_SET
find $BACKUP_PATH$BACKUP_FILE-* -mindepth 0 -maxdepth 0 -depth -mtime +$KEEP_DAYS -delete

sleep 2
umount $DISK_MOUNTP
losetup -d $LOOPDEV

hello how can restore from this script?

@tgebler
Copy link

tgebler commented Aug 10, 2025

Appologies, I used your script for an AI prompt to extend it to upload the Backup to Nextcloud. Works perfect, the retention period is untested until now.

#!/bin/bash
set -euo pipefail
# Optional: tighten PATH for cron
PATH=/usr/sbin:/usr/bin:/sbin:/bin

# ===== Basic configuration =====
BACKUP_PATH="/var/tmp"
BACKUP_FILE="pve-host"
KEEP_DAYS_LOCAL=7                 # local retention on the PVE host
REMOTE_KEEP_DAYS=30               # remote retention in Nextcloud share (days)

PVE_BACKUP_SET="/etc/pve/ /etc/lvm/ /etc/modprobe.d/ /etc/network/interfaces /etc/vzdump.conf /etc/sysctl.conf /etc/resolv.conf /etc/ksmtuned.conf /etc/hosts /etc/hostname /etc/cron* /etc/aliases"
PVE_CUSTOM_BACKUP_SET="/etc/apcupsd/ /etc/multipath/ /etc/multipath.conf"

# ===== Nextcloud public share (with upload rights) =====
NEXTCLOUD_SHARE_LINK=""			  # Nextcloud Link
SHARE_PASSWORD=""                 # if your share link has a password, set it here (empty if none)

# Optional: upload into a subfolder of the share (e.g., the hostname)
REMOTE_SUBDIR="$(hostname -s)"    # e.g., "srv-prox01"
# REMOTE_SUBDIR=""                # leave empty to upload into the root of the share

# ===== Derived values =====
TS="$(date +%Y_%m_%d-%H_%M_%S)"
BACKUP_NAME="${BACKUP_FILE}-${TS}.tar.gz"
BACKUP_LOCAL="${BACKUP_PATH%/}/${BACKUP_NAME}"

BASE_URL="$(printf '%s\n' "$NEXTCLOUD_SHARE_LINK" | sed -E 's#(https?://[^/]+)/.*#\1#')"
SHARE_TOKEN="${NEXTCLOUD_SHARE_LINK##*/}"

# Curl options (add --insecure only if you knowingly use self-signed certs)
CURL_COMMON_OPTS=(--fail --silent --show-error --retry 3 --retry-delay 5)

# ===== Logging (optional) =====
# exec >>/var/log/pvehost-backup.log 2>&1
# echo "=== $(date -Is) Start pvehost-backup ==="

# ===== Helpers: endpoints & auth =====
remote_url_webdav_dir() {
  # /public.php/webdav/<REMOTE_SUBDIR>/
  if [[ -n "${REMOTE_SUBDIR:-}" ]]; then
    printf "%s/public.php/webdav/%s/" "$BASE_URL" "${REMOTE_SUBDIR%/}"
  else
    printf "%s/public.php/webdav/" "$BASE_URL"
  fi
}
remote_url_dav_dir() {
  # /public.php/dav/files/<TOKEN>/<REMOTE_SUBDIR>/
  if [[ -n "${REMOTE_SUBDIR:-}" ]]; then
    printf`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment