Created
October 1, 2020 20:52
-
-
Save researcx/4ec53ed98270aa60f8ea93b3cf465aeb to your computer and use it in GitHub Desktop.
server backup script for host files and lxd containers (supports backing up into luks images)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#set -x | |
# configuration | |
hostname=$(hostname) | |
lxc="/snap/bin/lxc" | |
path="/mount/backups/$hostname/" | |
path_host=$path"host/" | |
path_lxd=$path"lxd/" | |
path_lxd_core=$path"lxd/core/" | |
mail=1 # email a log and important server information (disk space, etc) | |
mailto="root" | |
make_encrypted=1 # luks encrypt the host files and lxd container images | |
encryption_passphrase="passphrase" # passphrase for luks encrypted container | |
path_crypt="luks/" | |
crypt_ext=".encrypted" | |
days=7 # delete backups older than x days | |
run=1 # whether to actually run commands (set to 0 for debugging) | |
wait=15 # amount of time to wait between running backup commands, helps calm server load | |
timestamp=$(date +%Y%m%d_%H%M%S) | |
# make the directories | |
/bin/mkdir -p $path | |
/bin/mkdir -p $path_host | |
/bin/mkdir -p $path_lxd | |
/bin/mkdir -p $path_lxd_core | |
if [[ "$make_encrypted" == 1 ]]; then | |
/bin/mkdir -p $path$path_crypt | |
fi | |
# functions | |
convertsecs() { | |
((h=${1}/3600)) | |
((m=(${1}%3600)/60)) | |
((s=${1}%60)) | |
/usr/bin/printf "%02d:%02d:%02d\n" $h $m $s | |
} | |
lxdbackup() { | |
container=$1 | |
folder=$2 | |
snapshotname=$container-$timestamp.snapshot | |
backupname=lxd-image-$container-$timestamp | |
$lxc snapshot $container $snapshotname | |
$lxc publish --force $container/$snapshotname --alias $backupname | |
$lxc image export $backupname $folder$backupname | |
$lxc delete $container/$snapshotname | |
$lxc image delete $backupname | |
} | |
# use encrypted folders? | |
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" | |
/usr/bin/fallocate -l "$size"KB $path$path_crypt$crypt_filename | |
/usr/bin/printf $encryption_passphrase | /sbin/cryptsetup luksFormat $path$path_crypt$crypt_filename - | |
/usr/bin/printf $encryption_passphrase | /sbin/cryptsetup luksOpen $path$path_crypt$crypt_filename $crypt_mapper | |
/sbin/mkfs -t ext4 $crypt_devmapper | |
/bin/mkdir -p $mountpoint | |
/bin/mount $crypt_devmapper $mountpoint | |
} | |
unmount_encrypted_container(){ | |
name=$1 | |
mountpoint="$2/enc/" | |
crypt_mapper=$hostname-$name-$timestamp | |
crypt_devmapper="/dev/mapper/$crypt_mapper" | |
/bin/umount $mountpoint | |
/sbin/cryptsetup luksClose $crypt_mapper | |
} | |
# host files | |
host_files=("/root/.bashrc" "/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") | |
# lxd containers (names, space separated) | |
core=("nginx mariadb mail") | |
# log | |
logname=backup-$hostname-$timestamp.log | |
log=$path$logname | |
# clean up old backups | |
if [[ "$make_encrypted" == 1 ]]; then | |
find $path$path_crypt -maxdepth 1 -name "*$crypt_ext" -type f -mtime +$days -print -delete >> $log | |
fi | |
find $path_host -maxdepth 1 -name "*.zip" -type f -mtime +$days -print -delete >> $log | |
find $path_host -maxdepth 1 -name "*.log" -type f -mtime +$days -print -delete >> $log | |
find $path_lxd_core -maxdepth 1 -name "*.tar.gz" -type f -mtime +$days -print -delete >> $log | |
# start main code | |
START_TIME=$(date +%s) | |
echo "Backup:: Script start -- $timestamp" >> $log | |
echo "Backup:: Host: $hostname -- Date: $timestamp" >> $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 | |
/bin/mv $path_host/*.zip "$path_host/enc/" | |
echo "Backup:: Unmounting encrypted container" >> $log | |
unmount_encrypted_container "host" $path_host | |
/bin/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_lxd_core" >> $log | |
if [[ "$run" == 1 ]]; then | |
lxdbackup $container $path_lxd_core $ >> $log | |
/bin/sleep $wait | |
fi | |
done | |
if [[ "$run" == 1 ]]; then | |
if [[ "$make_encrypted" == 1 ]]; then | |
echo "Backup:: Making an encrypted container for core containers" >> $log | |
make_encrypted_container "core" $path_lxd_core | |
echo "Backup:: Moving files to encrypted container" >> $log | |
/bin/mv $path_lxd_core/*.tar.gz "$path_lxd_core/enc/" | |
echo "Backup:: Unmounting encrypted container" >> $log | |
unmount_encrypted_container "core" $path_lxd_core | |
/bin/rm -rf $path_lxd_core | |
echo "Backup:: Successfully encrypted core container backup" >> $log | |
fi | |
/bin/sleep $wait | |
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 $path | 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 | |
/usr/sbin/sendmail -v $mailto < $log | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment