-
-
Save researcx/aff274bf5f806af0cf77d23da4c8aa34 to your computer and use it in GitHub Desktop.
#!/bin/bash -l | |
# set -x | |
# make sure you have zip installed | |
# running: /path/to/proxmox-backup.sh [0/1] | |
# use 0 for debugging, 1 to run | |
# gist.github.com/researcx | |
# configuration | |
backups_folder="/Backups/Pi/$hostname" # needs to exist | |
path="/tmp/backup-$hostname/" | |
path_host=$path"host/" # main sysetm (host) files | |
path_containers="/var/lib/vz/dump" # proxmox container backup storage | |
mail=1 # email a log and important server information (disk space, etc) | |
mailto="root" | |
make_encrypted=0 # luks encrypt the host files and lxd container images | |
encryption_passphrase="passphrase" # passphrase for luks encrypted container | |
path_crypt="luks/" | |
crypt_ext=".crypt" | |
days=7 # delete backups older than x days | |
run=$1 # whether to actually run commands (set to 0 for debugging) | |
wait=120 # amount of seconds to wait between running backup commands, helps calm server load | |
timestamp=$(date +%Y%m%d_%H%M%S) | |
# host files (this is kind of a catch-all) (good to get via history | grep "nano /etc"), space separated | |
host_files=("/root/.bashrc" "/root/.ssh" "/root/.bash_profile" "/root/.bash_history" "/root/.tmux.conf" "/root/.local/share/fish" "/root/Scripts" "/etc/wireguard" "/etc/logrotate.d" "/etc/profile" "/etc/netdata" "/etc/fish" "/etc/fail2ban" "/etc/ssh" "/etc/sysctl.conf" "/etc/cron.d" "/etc/cron.daily" "/etc/cron.weekly" "/etc/cron.hourly" "/etc/cron.deny" "/etc/crontab" "/var/spool/cron" "/etc/sysconfig" "/etc/fstab" "/etc/crypttab" "/etc/postfix" "/etc/hosts" "/etc/resolv.conf" "/etc/aliases" "/etc/rsyslog.d" "/etc/ufw" "/etc/pam.d" "/etc/netplan" "/etc/wpa_supplicant" "/etc/network" "/etc/networks" "/etc/apt" "/etc/apticron" "/etc/yum.repos.d" "/etc/iptables.rules" "/etc/ip6tables.rules" "/etc/iptables" "/etc/modprobe.d" "/etc/pve" "/etc/udev" "/etc/modules-load.d" "/etc/systemd" "/etc/update-motd.d" "/etc/lightdm" "/etc/groups" "/etc/passwd" "/etc/nsswitch.conf" "/etc/netatalk" "/etc/samba" "/etc/avahi" "/etc/default" "/etc/nanorc" "/etc/X11" "/etc/netconfig") | |
# proxmox containers, numbers, space separated | |
core=("100" "101" "102" "103") # dnscrypt, nginx, ldap, ircd | |
# log | |
log_file=backup-$hostname-$timestamp.log | |
log=$path$log_file | |
# make the directories | |
rm -r $path | |
rm -r $path_containers | |
mkdir -p $path | |
mkdir -p $path_host | |
mkdir -p $path_containers | |
mkdir -p $backups_folder | |
if [[ "$make_encrypted" == 0 ]]; then | |
mkdir -p $path$path_crypt | |
fi | |
# functions | |
convertsecs() { | |
((h=${1}/3600)) | |
((m=(${1}%3600)/60)) | |
((s=${1}%60)) | |
printf "%02d:%02d:%02d\n" $h $m $s | |
} | |
proxmox_backup() { | |
container=$1 | |
vzdump $container | |
pct unlock $container | |
} | |
make_encrypted_container(){ | |
name=$1 | |
file=$2 | |
mountpoint="$2/enc/" | |
size=$(du -s $file | awk '{print $1}') | |
if [ "$size" -lt "65536" ]; then # cryptsetup: luks images need to be +32mb in order to be able to be formatted/opened | |
size=65536 | |
else | |
size="$(($size + 65536))" #just being safe! hopefully | |
fi | |
crypt_filename=$hostname-$name-$timestamp$crypt_ext | |
crypt_mapper=$hostname-$name-$timestamp | |
crypt_devmapper="/dev/mapper/$crypt_mapper" | |
fallocate -l "$size"KB $path$path_crypt$crypt_filename | |
printf $encryption_passphrase | cryptsetup luksFormat $path$path_crypt$crypt_filename - | |
printf $encryption_passphrase | cryptsetup luksOpen $path$path_crypt$crypt_filename $crypt_mapper | |
mkfs -t ext4 $crypt_devmapper | |
mkdir -p $mountpoint | |
mount $crypt_devmapper $mountpoint | |
} | |
unmount_encrypted_container(){ | |
name=$1 | |
mountpoint="$2/enc/" | |
crypt_mapper=$hostname-$name-$timestamp | |
crypt_devmapper="/dev/mapper/$crypt_mapper" | |
umount $mountpoint | |
cryptsetup luksClose $crypt_mapper | |
} | |
# clean up old backups | |
if [[ "$run" == 1 ]]; then | |
if [[ "$make_encrypted" == 1 ]]; then | |
find $backups_folder -maxdepth 1 -name "*$crypt_ext" -type f -mtime +$days -print -delete >> $log | |
fi | |
find $backups_folder -maxdepth 1 -name "*.log" -type f -mtime +$days -print -delete >> $log | |
find $backups_folder -maxdepth 1 -name "*.tar" -type f -mtime +$days -print -delete >> $log | |
find $backups_folder -maxdepth 1 -name "*.zip" -type f -mtime +$days -print -delete >> $log | |
fi | |
# start main code | |
START_TIME=$(date +%s) | |
echo "Backup:: Script start -- $timestamp" >> $log | |
echo "Backup:: Host: $hostname -- Date: $timestamp" >> $log | |
echo "Paths:: Host: $path" >> $log | |
echo "Paths:: Containers: $path_containers" >> $log | |
echo "Paths:: Backups: $backups_folder" >> $log | |
# host files | |
echo "Backup:: Backing up the following host files to $path_host" >> $log | |
# echo $host_files >> $log | |
for host_file in ${host_files[@]}; do | |
echo "Backup:: Starting backup of $host_file to $path_host" >> $log | |
host_file_safe=$(echo $host_file | sed 's|/|-|g') | |
if [[ "$run" == 1 ]]; then | |
zip -r $path_host$host_file_safe-$timestamp.zip "$host_file" >> $log | |
fi | |
done | |
echo "Backup:: Host files successfully backed up" >> $log | |
if [[ "$run" == 1 ]]; then | |
if [[ "$make_encrypted" == 1 ]]; then | |
echo "Backup:: Making an encrypted container for host files" >> $log | |
make_encrypted_container "host" $path_host | |
echo "Backup:: Moving files to encrypted container" >> $log | |
mv $path_host/*.zip "$path_host/enc/" | |
echo "Backup:: Unmounting encrypted container" >> $log | |
unmount_encrypted_container "host" $path_host | |
rm -rf $path_host/* | |
echo "Backup:: Successfully encrypted host backup" >> $log | |
fi | |
fi | |
# containers | |
echo "Backup:: Backing up containers" >> $log | |
for container in ${core[@]}; do | |
echo "Backup:: Starting backup on $container to $path_containers" >> $log | |
if [[ "$run" == 1 ]]; then | |
proxmox_backup $container >> $log | |
sleep $wait | |
fi | |
done | |
if [[ "$run" == 1 ]]; then | |
if [[ "$make_encrypted" == 1 ]]; then | |
echo "Backup:: Making an encrypted container for containers" >> $log | |
make_encrypted_container "containers" $path_containers | |
echo "Backup:: Moving files to encrypted container" >> $log | |
mv $path_containers/*.tar.gz "$path_containers/enc/" | |
echo "Backup:: Unmounting encrypted container" >> $log | |
unmount_encrypted_container "core" $path_containers | |
rm -rf $path_containers/* | |
echo "Backup:: Successfully encrypted core container backup" >> $log | |
fi | |
sleep $wait | |
fi | |
rsync -a --progress $log $backups_folder >> $log | |
if [[ "$make_encrypted" == 1 ]]; then | |
rsync -a --progress $path$path_crypt $backups_folder >> $log | |
else | |
rsync -a --progress $path_host $backups_folder >> $log | |
rsync -a --progress $path_containers/ $backups_folder >> $log | |
fi | |
END_TIME=$(date +%s) | |
# end main code | |
elapsed_time=$(( $END_TIME - $START_TIME )) | |
echo "Backup :: Script End -- $(date +%Y%m%d_%H%M)" >> $log | |
echo "Elapsed Time :: $(convertsecs $elapsed_time) " >> $log | |
backup_size=`find $path -maxdepth 5 -type f -mmin -360 -exec du -ch {} + | grep total$ | awk '{print $1}'` | |
backup_stored=`find $path -maxdepth 5 -type f -exec du -ch {} + | grep total$ | awk '{print $1}'` | |
disk_remaining=`df -Ph $backups_folder | tail -1 | awk '{print $4}'` | |
echo -e "Subject: [$hostname] Backup Finished [$backup_size] [stored: $backup_stored | disk remaining: $disk_remaining] (took $(convertsecs $elapsed_time))\n\n$(cat $log)" > $log | |
if [[ "$mail" == 1 ]]; then | |
sendmail -v $mailto < $log | |
fi | |
sleep $wait | |
rm -r $path | |
rm -r $path_containers |
Hi i look at your script and not sure how it work... Was it it encrypt vm and then zip the thing, put this into folder : "/var/lib/vz/dump and send a mail ? Thanks for precision. As i don't figure on how to do proper backup.. hehe
Hi!
It runs vzdump on each VM listed in core
on line 34
https://gist.github.com/researcx/aff274bf5f806af0cf77d23da4c8aa34#file-proxmox-backup-sh-L34
path_containers
(/var/lib/vz/dump by default) is the location where the vzdump images/backups get saved by vzdump, if this location is different for you, then specify it, otherwise leave it
if make_encrypted is set to 1 then it will make LUKS images to put the folder containing the vzdump images and host files such as things from /etc/ into
the idea of this script is to encrypt VM and host backups if you want to upload them somewhere
Hi i look at your script and not sure how it work... Was it it encrypt vm and then zip the thing, put this into folder : "/var/lib/vz/dump and send a mail ? Thanks for precision. As i don't figure on how to do proper backup.. hehe