-
-
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