backup-scripts/admin.sh
2025-04-16 08:16:09 +00:00

809 lines
25 KiB
Bash
Executable File

#!/bin/bash
trap nfcunmount EXIT
set -o noglob
SCRIPT="$(readlink -f "${BASH_SOURCE}")"
CONFIGURATION="/home/user/scripts/admin.conf"
if [ "$EUID" -ne 0 ]; then
echo "Ce script nécessite des privilèges administrateur."
echo "Relance avec sudo..."
exec sudo "$0" "$@"
fi
echo "Le script est bien lancé avec sudo/root !"
function show()
{
NC='\033[0m'
if [ -z "$2" ]; then
COLOR=$NC
elif [ "$2" == "ERR" ]; then
COLOR='\033[1;31m'
else
COLOR='\033[0;32m'
fi
printf "${COLOR}$1${NC}\n"
}
function assign()
{
KEYS=$(cat "$1"|sed 's/.*%\([A-Z0-9]*\)%.*/%\1/g'|grep "%"|tr -d '%')
while read -r KEY; do
REALKEY=$(eval echo \$${KEY})
show "Apply key $KEY" 1
sed -i "s#%${KEY}%#${REALKEY}#g" /mnt/usb/rclone/rclone.conf
done < <(echo "${KEYS}")
}
function extract()
{
ALLCONTENT=$(cat "${SCRIPT}"|grep "#$1"|sed "s/^#$1\(.*\)$/\1/")
CONTENT=$(echo "${ALLCONTENT}"|tail -n +2)
CONTENTSIZE=$(echo "${CONTENT}"|wc -c)
FILEINFO=$(echo "${ALLCONTENT}"|head -n1)
FILENAME=$(echo "${FILEINFO}"|cut -d"," -f1)
FILEMOD=$(echo "${FILEINFO}"|cut -d"," -f2)
show "Extract piece $1 (${CONTENTSIZE}o) at ${FILENAME} with ${FILEMOD}"
echo "${CONTENT}" > "${FILENAME}"
chmod ${FILEMOD} "${FILENAME}"
}
function excludepath()
{
EXCLUD=""
while read SRC; do
if [ ! -z "${SRC}" ]; then
EXCLUD="${EXCLUD} --exclude ${SRC}"
fi
done < <(echo "$1"|tr "," "\n")
echo "${EXCLUD}"
}
function nfcunmount()
{
TMPFS=$(mount -t tmpfs|grep "/mnt/usb")
if [ ! -z "${TMPFS}" ]; then
umount /mnt/usb
fi
TMPFS=$(mount -t tmpfs|grep "/mnt/usb")
if [ ! -z "${TMPFS}" ]; then
show "Unable to umount" ERR
fi
}
function nfcmountonly()
{
if [ ! -d /mnt/usb ]; then
mkdir -p /mnt/usb
fi
TMPFS=$(mount -t tmpfs|grep "/mnt/usb")
if [ -z "${TMPFS}" ]; then
mount -t tmpfs tmpfs /mnt/usb
fi
}
function rclonemount()
{
if [ ! -f /mnt/usb/rclone/rclone.conf ]; then
show "NO RCLONE CONFIGURATION FILE" ERR
nfcmountonly
if [ ! -d /mnt/usb/rclone ]; then
show "Create /mnt/usb/rclone" 1
mkdir -p /mnt/usb/rclone
show "Create rclone.conf" 1
extract 5
TOKEN=$(${ZFS} get rclone:token $1 -o value -H|decrypt_now "{\"url\": \"${URL}\"}" 2> /dev/null)
if [[ "${TOKEN}" == "" ]]; then
show "Unable to find connexion information: token"
nfcunmount
exit
fi
if [[ "$2" == "rclone" ]]; then
show "RCLONE mode"
PASSWD1=$(${ZFS} get rclone:password1 $1 -o value -H|decrypt_now "{\"url\": \"${URL}\"}" 2> /dev/null)
if [[ "${PASSWD1}" == "" ]]; then
show "Unable to find connexion information: passwd1"
nfcunmount
exit
fi
PASSWD2=$(${ZFS} get rclone:password2 $1 -o value -H|decrypt_now "{\"url\": \"${URL}\"}" 2> /dev/null)
if [[ "${PASSWD2}" == "" ]]; then
show "Unable to find connexion information: passwd2"
nfcunmount
exit
fi
REMOTE=$(${ZFS} get sync:dstpath $1 -o value -H)
if [[ "${REMOTE}" == "" ]]; then
show "Unable to find connexion information: dstpath"
nfcunmount
exit
fi
ACTIVE=$(${ZFS} get sync:active $1 -o value -H)
if [[ ! "${ACTIVE}" == "on" ]]; then
show "Sync not active"
nfcunmount
exit
fi
RCLONE_EXCLUDE=$(${ZFS} get sync:exclude $1 -o value -H)
RCLONE_VOLS="/$1"
else
PASSWD1=$(${ZFS} get restic:password1 $1 -o value -H|decrypt_now "{\"url\": \"${URL}\"}" 2> /dev/null)
if [[ "${PASSWD1}" == "" ]]; then
show "Unable to find connexion information: passwd1"
nfcunmount
exit
fi
PASSWD2=$(${ZFS} get restic:password2 $1 -o value -H|decrypt_now "{\"url\": \"${URL}\"}" 2> /dev/null)
if [[ "${PASSWD2}" == "" ]]; then
show "Unable to find connexion information: passwd2"
nfcunmount
exit
fi
show "RESTIC mode"
REMOTE=$(${ZFS} get backup:dstpath $1 -o value -H)
if [[ "${REMOTE}" == "" ]]; then
show "Unable to find connexion information: dstpath"
nfcunmount
exit
fi
ACTIVE=$(${ZFS} get backup:active $1 -o value -H)
if [[ ! "${ACTIVE}" == "on" ]]; then
show "Backup not active"
nfcunmount
exit
fi
RESTIC_PASSWORD=$(${ZFS} get restic:password $1 -o value -H|decrypt_now "{\"url\": \"${URL}\"}" 2> /dev/null)
if [[ "${RESTIC_PASSWORD}" == "" ]]; then
show "Unable to find connexion information: passwd"
nfcunmount
exit
fi
RESTIC_EXCLUDE=$(${ZFS} get backup:exclude $1 -o value -H)
RESTIC_ALL=$(${ZFS} get backup:retention $1 -o value -H)
RESTIC_MONTHLY=$(echo "${RESTIC_ALL}"|cut -d',' -f1)
RESTIC_WEEKLY=$(echo "${RESTIC_ALL}"|cut -d',' -f2)
RESTIC_DAILY=$(echo "${RESTIC_ALL}"|cut -d',' -f3)
RESTIC_VOLS="/$1"
fi
assign /mnt/usb/rclone/rclone.conf
fi
fi
TOKEN=""
PASSWD1=""
PASSWD2=""
show "List remotes" 1
${RCLONE_CMD} --config /mnt/usb/rclone/rclone.conf listremotes
show "Connect to Cloud without cyphering" 1
${RCLONE_CMD} --config /mnt/usb/rclone/rclone.conf lsd pcloud:/
show "Connect to Cloud with cyphering" 1
${RCLONE_CMD} --config /mnt/usb/rclone/rclone.conf lsd crypt:/
}
function attribute()
{
VAL=""
ATTRIBUTE=$(${ZFS} get $1 $4 -o value -H)
if [[ "${ATTRIBUTE}" == "-" ]]; then
ATTRIBUTE="$5"
show "Init attribute $1 with $5"
${ZFS} set $1=$5 $4
fi
if [[ "$2" == "passwd" ]]; then
ATTRIBUTE_DEC=$(echo -en "${ATTRIBUTE}"|decrypt_now "{\"url\": \"${URL}\"}" 2> /dev/null)
BEGIN=$(echo "${ATTRIBUTE_DEC}"|head -c 10)
MIDDLE="..."
END=$(echo "${ATTRIBUTE_DEC}"|tail -c 10)
BLOB="${BEGIN}${MIDDLE}${END}"
read -p "$3 [${BLOB}]:" ASK_DEC </dev/tty
if [[ "${ASK_DEC}" == "" ]]; then
ASK=""
else
ASK=$(echo -en "${ASK_DEC}"|encrypt_now "{\"url\": \"${URL}\"}" 2> /dev/null)
fi
ATTRIBUTE_DEC=""
ASK_DEC=""
elif [[ "$2" == "bool" ]]; then
if [[ "${ATTRIBUTE}" == "on" ]]; then
VALUE="off"
else
VALUE="on"
fi
read -p "$3 [${ATTRIBUTE}]/${VALUE}:" ASK </dev/tty
else
read -p "$3 [${ATTRIBUTE}]:" ASK </dev/tty
fi
if [[ "${ASK}" != "${ATTRIBUTE}" ]]; then
if [[ "${ASK}" == "" ]]; then
#${ZFS} set $1=${ATTRIBUTE} $4
VAL=${ATTRIBUTE}
elif [[ "${ASK}" == "-" ]]; then
show "...with $5"
${ZFS} set $1=$5 $4
VAL=$5
else
show "..."
${ZFS} set $1=${ASK} $4
VAL=${ASK}
fi
else
VAL="${ATTRIBUTE}"
fi
}
function configure()
{
show "********* Configure pools ***********"
while read ITEM; do
show " - ${ITEM}"
attribute rclone:token passwd "Pcloud token" ${ITEM} ""
if [[ "${VAL}" == "" ]]; then
continue
fi
attribute rclone:password1 passwd "Pcloud password N1" ${ITEM} ""
if [[ "${VAL}" == "" ]]; then
continue
fi
attribute rclone:password2 passwd "Pcloud password N2" ${ITEM} ""
if [[ "${VAL}" == "" ]]; then
continue
fi
attribute sync:active bool "Sync active" ${ITEM} off
if [[ "${VAL}" == "on" ]]; then
attribute sync:dstpath str "Sync path" ${ITEM} ${RCLONE_PATH}
attribute sync:exclude str "Sync exclude" ${ITEM} ""
fi
attribute restic:password1 passwd "Restic password N1" ${ITEM} ""
if [[ "${VAL}" == "" ]]; then
continue
fi
attribute restic:password2 passwd "Restic password N2" ${ITEM} ""
if [[ "${VAL}" == "" ]]; then
continue
fi
attribute backup:active bool "Backup active" ${ITEM} off
if [[ "${VAL}" == "on" ]]; then
attribute restic:password passwd "Backup password" ${ITEM} ""
if [[ "${VAL}" == "" ]]; then
continue
fi
attribute backup:dstpath str "Backup path" ${ITEM} ${RESTIC_PATH}
attribute backup:exclude str "Backup exclude" ${ITEM} ""
attribute backup:retention str "Backup retention" ${ITEM} ${RESTIC_MONTHLY},${RESTIC_WEEKLY},${RESTIC_DAILY}
fi
done < <(${ZFS} list -o name -d 1 -t filesystem|grep "/")
}
function help()
{
show "Usage: admin [ command ] [ args... ]" 1
show ""
show "help for COMPLEX commands: admin command"
show ""
show "-< Save/Restore"
show "sync - sync, check data to cloud COMPLEX"
show "backup - backup data to cloud COMPLEX"
show "config - configure Restic and Rclone NOARG"
show ""
show "-< Tang"
show "tangcrypt - encrypt /dev/stdin to /dev/stdout NOARG"
show "tangdecrypt - decrypt /dev/stdin to /dev/stdout NOARG"
show ""
exit 2
}
function help_restic()
{
show "Usage: admin backup ${ZFS}dataset [ init|view|ls|check|now|prune|remove|config ]" 1
show ""
show "Use the restic backend to make some cloud backup operations"
show ""
show "init - initialize the data storage on cloud"
show "view - view snapshots stored on cloud"
show "ls - list all files 1ARG"
show "check - check integrity of distant data"
show "now - perform a backup on cloud"
show "prune - purge unused data on cloud storage"
show "remove - remove a snapshot store on cloud 1ARG"
show "unlock - unlock data storage on cloud"
show ""
exit 2
}
function help_rclone()
{
show "Usage: admin sync ${ZFS}dataset [ now|dryrun|copy|view|ls|check|config ]" 1
show ""
show "Use the rclone backend to make cloud mirror operations"
show ""
show "now - perform a sync with the cloud"
show "dryrun - perform a simulation of sync with the cloud"
show "copy - copy ARG to local"
show "view - view interactivly server data"
show "ls - list all files"
show "check - check integrity of distant data"
show ""
exit 2
}
function encrypt_now() {
SUMMARY="Encrypts using a Tang binding server policy"
if [ "$1" == "--summary" ]; then
echo "$SUMMARY"
exit 0
fi
if [ -t 0 ]; then
exec >&2
echo
echo "Usage: clevis encrypt tang CONFIG [-y] < PLAINTEXT > JWE"
echo
echo "$SUMMARY"
echo
echo " -y Use this option for skipping the advertisement"
echo " trust check. This can be useful in automated"
echo " deployments"
echo
echo "This command uses the following configuration properties:"
echo
echo " url: <string> The base URL of the Tang server (REQUIRED)"
echo
echo " thp: <string> The thumbprint of a trusted signing key"
echo
echo " adv: <string> A filename containing a trusted advertisement"
echo " adv: <object> A trusted advertisement (raw JSON)"
echo
echo "Obtaining the thumbprint of a trusted signing key is easy. If you"
echo "have access to the Tang server's database directory, simply do:"
echo
echo " $ jose jwk thp -i \$DBDIR/\$SIG.jwk "
echo
echo "Alternatively, if you have certainty that your network connection"
echo "is not compromised (not likely), you can download the advertisement"
echo "yourself using:"
echo
echo " $ curl -f \$URL/adv > adv.jws"
echo
exit 2
fi
if ! cfg="$(jose fmt -j- -Oo- <<< "$1" 2>/dev/null)"; then
echo "Configuration is malformed!" >&2
exit 1
fi
CLEVIS_DEFAULT_THP_ALG=S256 # SHA-256.
CLEVIS_ALTERNATIVE_THP_ALGS=S1 # SHA-1.
trust=
[ -n "${2}" ] && [ "${2}" == "-y" ] && trust=yes
if ! url="$(jose fmt -j- -Og url -u- <<< "$cfg")"; then
echo "Missing the required 'url' property!" >&2
exit 1
fi
thp="$(jose fmt -j- -Og thp -Su- <<< "$cfg")" || true
### Get the advertisement
if jws="$(jose fmt -j- -g adv -Oo- <<< "$cfg")"; then
thp="${thp:-any}"
elif jws="$(jose fmt -j- -g adv -Su- <<< "$cfg")"; then
if ! [ -f "$jws" ]; then
echo "Advertisement file '$jws' not found!" >&2
exit 1
fi
if ! jws="$(jose fmt --json="${jws}" -Oo- 2>/dev/null)"; then
echo "Advertisement file '$jws' is malformed!" >&2
exit 1
fi
thp="${thp:-any}"
elif ! jws="$(curl -sfg "$url/adv/$thp")"; then
echo "Unable to fetch advertisement: '$url/adv/$thp'!" >&2
exit 1
fi
if ! jwks="$(jose fmt --json="${jws}" -Og payload -SyOg keys \
-AUo- 2>/dev/null)"; then
echo "Advertisement is malformed!" >&2
exit 1
fi
### Check advertisement validity
ver="$(jose jwk use -i- -r -u verify -o- <<< "$jwks")"
if ! jose jws ver -i "$jws" -k- -a <<< "$ver"; then
echo "Advertisement is missing signatures!" >&2
exit 1
fi
### Check advertisement trust
if [ -z "${trust}" ]; then
if [ -z "$thp" ]; then
echo "The advertisement contains the following signing keys:" >&2
echo >&2
jose jwk thp -i- -a "${CLEVIS_DEFAULT_THP_ALG}" <<< "$ver" >&2
echo >&2
elif [ "$thp" != "any" ] && \
! jose jwk thp -i- -f "${thp}" -a "${CLEVIS_DEFAULT_THP_ALG}" \
-o /dev/null <<< "$ver"; then
# Thumbprint of trusted JWK did not match the signature. Let's check
# alternative thumbprints generated with clevis supported hash
# algorithms to be sure.
for alg in ${CLEVIS_ALTERNATIVE_THP_ALGS}; do
srv="$(jose jwk thp -i- -f "${thp}" -a "${alg}" <<< "${ver}")" \
&& break
done
if [ -z "${srv}" ]; then
echo "Trusted JWK '$thp' did not sign the advertisement!" >&2
exit 1
fi
fi
fi
### Perform encryption
if ! enc="$(jose jwk use -i- -r -u deriveKey -o- <<< "$jwks")"; then
echo "Key derivation key not available!" >&2
exit 1
fi
jose fmt -j "$enc" -Og keys -A || enc="{\"keys\":[$enc]}"
if ! jwk="$(jose fmt -j- -Og keys -Af- <<< "$enc")"; then
echo "No exchange keys found!" >&2
exit 1
fi
jwk="$(jose fmt -j- -Od key_ops -o- <<< "$jwk")"
jwk="$(jose fmt -j- -Od alg -o- <<< "$jwk")"
kid="$(jose jwk thp -i- -a "${CLEVIS_DEFAULT_THP_ALG}" <<< "$jwk")"
jwe='{"protected":{"alg":"ECDH-ES","enc":"A256GCM","clevis":{"pin":"tang","tang":{}}}}'
jwe="$(jose fmt -j "$jwe" -g protected -q "$kid" -s kid -UUo-)"
jwe="$(jose fmt -j "$jwe" -g protected -g clevis -g tang -q "$url" -s url -UUUUo-)"
jwe="$(jose fmt -j "$jwe" -g protected -g clevis -g tang -j- -s adv -UUUUo- <<< "$jwks")"
exec jose jwe enc -i- -k- -I- -c < <(echo -n "$jwe$jwk"; /bin/cat)
echo -en ""
}
function decrypt_now() {
[ $# -eq 1 ] && [ "$1" == "--summary" ] && exit 2
if [ -t 0 ]; then
exec >&2
echo
echo "Usage: clevis decrypt tang < JWE > PLAINTEXT"
echo
exit 2
fi
read -r -d . hdr
if ! jhd="$(jose b64 dec -i- <<< "$hdr")"; then
echo "Error decoding JWE protected header!" >&2
exit 1
fi
if [ "$(jose fmt -j- -Og clevis -g pin -u- <<< "$jhd")" != "tang" ]; then
echo "JWE pin mismatch!" >&2
exit 1
fi
if ! clt="$(jose fmt -j- -Og epk -Oo- <<< "$jhd")"; then
echo "JWE missing required 'epk' header parameter!" >&2
exit 1
fi
if ! kid="$(jose fmt -j- -Og kid -Su- <<< "$jhd")"; then
echo "JWE missing required 'kid' header parameter!" >&2
exit 1
fi
# Tang advertisement validation.
if ! keys="$(jose fmt -j- -Og clevis -g tang -g adv -Oo- <<< "${jhd}")"; then
echo "JWE missing required 'clevis.tang.adv' header parameter!" >&2
exit 1
fi
# Check if the thumbprint we have in `kid' is in the advertised keys.
CLEVIS_DEFAULT_THP_ALG=S256 # SHA-256.
CLEVIS_DEFAULT_THP_LEN=43 # Length of SHA-256 thumbprint.
CLEVIS_ALTERNATIVE_THP_ALGS=S1 # SHA-1.
# Issue a warning if we are using a hash that has a shorter length than the
# default one.
if [ "${#kid}" -lt "${CLEVIS_DEFAULT_THP_LEN}" ]; then
echo "WARNING: tang using a deprecated hash for the JWK thumbprints" >&2
fi
if ! srv="$(jose jwk thp -i- -f "${kid}" -a "${CLEVIS_DEFAULT_THP_ALG}" \
<<< "${keys}")"; then
# `kid' thumprint not in the advertised keys, but it's possible it was
# generated using a different algorithm than the default one.
# Let us try the alternative supported algorithms to make sure `kid'
# really is not part of the advertised keys.
for alg in ${CLEVIS_ALTERNATIVE_THP_ALGS}; do
srv="$(jose jwk thp -i- -f "$kid" -a "${alg}" <<< "${keys}")" && break
done
if [ -z "${srv}" ]; then
echo "JWE header validation of 'clevis.tang.adv' failed: key thumbprint does not match" >&2
exit 1
fi
fi
if ! url="$(jose fmt -j- -Og clevis -g tang -g url -Su- <<< "$jhd")"; then
echo "JWE missing required 'clevis.tang.url' header parameter!" >&2
exit 1
fi
if ! crv="$(jose fmt -j- -Og crv -Su- <<< "$clt")"; then
echo "Unable to determine EPK's curve!" >&2
exit 1
fi
if ! eph="$(jose jwk gen -i "{\"alg\":\"ECMR\",\"crv\":\"$crv\"}")"; then
echo "Error generating ephemeral key!" >&2
exit 1
fi
xfr="$(jose jwk exc -i '{"alg":"ECMR"}' -l- -r- <<< "$clt$eph")"
rec_url="$url/rec/$kid"
ct="Content-Type: application/jwk+json"
if ! rep="$(curl -sfg -X POST -H "$ct" --data-binary @- "$rec_url" <<< "$xfr")"; then
echo "Error communicating with server $url" >&2
exit 1
fi
if ! rep="$(jose fmt -j- -Og kty -q EC -EUUg crv -q "$crv" -EUUo- <<< "$rep")"; then
echo "Received invalid server reply!" >&2
exit 1
fi
tmp="$(jose jwk exc -i '{"alg":"ECMR"}' -l- -r- <<< "$eph$srv")"
rep="$(jose jwk pub -i- <<< "$rep")"
jwk="$(jose jwk exc -l- -r- <<< "$rep$tmp")"
(echo -n "$jwk$hdr."; /bin/cat) | exec jose jwe dec -k- -i-
echo -en ""
}
function rcloneapp()
{
if [ -z "$1" ]; then
help_rclone
fi
case "$2" in
copy)
DEST="/tmp/"
show "Copy from $3 to ${DEST}" 1
rclonemount $1 rclone
${RCLONE_CMD} -vv --config /mnt/usb/rclone/rclone.conf copy crypt:/$2 ${DEST}
;;
dryrun)
show "Dry run..." 1
echo "********* Synchonize *************" >> /var/log/rclone.log
date >> /var/log/rclone.log
rclonemount $1 rclone
excluded=$(excludepath $RCLONE_EXCLUDE)
while read src; do
dstemp=$(basename "${src^}")
dst=${dstemp^}
show "$src => $dst"
echo "$src => $dst" >> /var/log/rclone.log
${RCLONE_CMD} --config /mnt/usb/rclone/rclone.conf sync -c -P --dry-run --links --checkers=20 --low-level-retries=10 --retries=10 --retries-sleep=1s --transfers=20 --delete-excluded $excluded --exclude ".zfs/**" $src crypt:/${dst}/ 2>&1 | tee -a /var/log/rclone.log
done < <(echo "$RCLONE_VOLS"|tr "," "\n")
echo "***********************************" >> /var/log/rclone.log
;;
now)
show "Synchronize..." 1
echo "********* Synchonize *************" >> /var/log/rclone.log
date >> /var/log/rclone.log
rclonemount $1 rclone
excluded=$(excludepath $RCLONE_EXCLUDE)
while read src; do
dstemp=$(basename "${src^}")
dst=${dstemp^}
show "$src => $dst"
echo "$src => $dst" >> /var/log/rclone.log
${RCLONE_CMD} --config /mnt/usb/rclone/rclone.conf sync -c -P ${DRY} --links --checkers=20 --low-level-retries=10 --retries=10 --retries-sleep=1s --transfers=20 --delete-excluded $excluded --exclude ".zfs/**" $src crypt:/${dst}/ 2>&1 | tee -a /var/log/rclone.log
done < <(echo "$RCLONE_VOLS"|tr "," "\n")
echo "***********************************" >> /var/log/rclone.log
;;
view)
show "View..." 1
rclonemount $1 rclone
${RCLONE_CMD} --config /mnt/usb/rclone/rclone.conf ncdu crypt:
;;
ls)
show "View files..." 1
rclonemount $1 rclone
${RCLONE_CMD} --config /mnt/usb/rclone/rclone.conf lsd crypt: -R
;;
check)
show "Check..." 1
echo "************** Check **************" >> /var/log/rclone.log
date >> /var/log/rclone.log
rclonemount $1 rclone
excluded=$(excludepath $RCLONE_EXCLUDE)
while read src; do
dstemp=$(basename "${src^}")
dst=${dstemp^}
show "$src => $dst"
echo "$src => $dst" >> /var/log/rclone.log
${RCLONE_CMD} --config /mnt/usb/rclone/rclone.conf check -c -P --differ /var/log/differ_${dst}.log --links --checkers=20 --low-level-retries=10 --retries=10 --retries-sleep=1s --transfers=20 $excluded --exclude ".zfs/**" $src crypt:/${dst}/ 2>&1 | tee -a /var/log/rclone.log
done < <(echo "$RCLONE_VOLS"|tr "," "\n")
echo "***********************************" >> /var/log/rclone.log
;;
*)
help_rclone
;;
esac
nfcunmount
}
function resticapp()
{
if [ -z "$1" ]; then
help_restic
fi
export RCLONE_CONFIG
export RESTIC_PASSWORD
case "$2" in
init)
show "Initializing..." 1
echo "********* Initialiazing *************" >> /var/log/restic.log
date >> /var/log/restc.log
rclonemount $1 restic
${RESTIC_CMD} init -r rclone:crypt:/ | tee -a /var/log/restic.log
echo "***********************************" >> /var/log/restic.log
;;
unlock)
show "Unlocking..." 1
echo "********* Unlocking *************" >> /var/log/restic.log
date >> /var/log/restc.log
rclonemount $1 restic
${RESTIC_CMD} unlock -r rclone:crypt:/ | tee -a /var/log/restic.log
echo "***********************************" >> /var/log/restic.log
;;
ls)
show "View files..." 1
rclonemount $1 restic
${RESTIC_CMD} ls -r rclone:crypt:/ $3
;;
view)
show "View..." 1
rclonemount $1 restic
${RESTIC_CMD} snapshots -r rclone:crypt:/
;;
check)
show "Check..." 1
echo "************** Check **************" >> /var/log/restic.log
date >> /var/log/restic.log
rclonemount $1 restic
${RESTIC_CMD} check --read-data -r rclone:crypt:/ | tee -a /var/log/restic.log
${RESTIC_CMD} rebuild-index -r rclone:crypt:/ | tee -a /var/log/restic.log
echo "***********************************" >> /var/log/restic.log
;;
prune)
show "Cleaning..." 1
echo "************** Cleaning **************" >> /var/log/restic.log
date >> /var/log/restic.log
rclonemount $1 restic
${RESTIC_CMD} prune -r rclone:crypt:/ | tee -a /var/log/restic.log
echo "***********************************" >> /var/log/restic.log
;;
remove)
show "Removing..." 1
echo "************** Removing **************" >> /var/log/restic.log
date >> /var/log/restic.log
rclonemount $1 restic
${RESTIC_CMD} forget $2 -r rclone:crypt:/ | tee -a /var/log/restic.log
echo "***********************************" >> /var/log/restic.log
;;
now)
show "Backing up..." 1
echo "************** Backup **************" >> /var/log/restic.log
date >> /var/log/restic.log
rclonemount $1 restic
excluded=$(excludepath $RESTIC_EXCLUDE)
while read src; do
dstemp=$(basename "${src^}")
dst=${dstemp^}
show "$src => $dst"
echo "$src => $dst" >> /var/log/restic.log
${RESTIC_CMD} backup $src -r rclone:crypt:/ --verbose=1 $excluded --exclude ".zfs/**" --tag admin_command|tee -a /var/log/restic.log
${RESTIC_CMD} forget -r rclone:crypt:/ --tag admin_command --keep-monthly=$RESTIC_MONTHLY --keep-weekly=$RESTIC_WEEKLY --keep-daily=$RESTIC_DAILY
done < <(echo "$RESTIC_VOLS"|tr "," "\n")
echo "***********************************" >> /var/log/restic.log
;;
*)
help_restic
;;
esac
nfcunmount
}
if [[ ! -f "${CONFIGURATION}" ]]; then
show "Creating configuration file..."
extract 4
fi
source "${CONFIGURATION}"
nfcunmount
COMMAND="$1"
shift
case "${COMMAND}" in
config)
configure
;;
backup)
resticapp $1 $2 $3
;;
sync)
rcloneapp $1 $2 $3
;;
nfcunmount)
nfcunmount
;;
tangcrypt)
cat /dev/stdin|encrypt_now "{\"url\": \"${URL}\"}"
;;
tangdecrypt)
cat /dev/stdin|decrypt_now "{\"url\": \"${URL}\"}"
;;
*)
help
;;
esac
#4/home/user/scripts/admin.conf,644
#4# Hard settings
#4ALIB="--module /usr/lib/x86_64-linux-gnu/libykcs11.so.2"
#4ZFS="zfs"
#4PZFS="zfs"
#4ZPOOL="zpool"
#4PZPOOL="zpool"
#4PATH="/usr/local/bin:/usr/bin:$PATH"
#4FONT=""
#4MAXSIZE=700
#4RCLONE_CMD="rclone"
#4RESTIC_CMD="restic"
#4
#4# Settings
#4RCLONE_CONFIG="/mnt/usb/rclone/rclone.conf"
#4URL="https://tang.ia86.cc"
#4
#4# Default parameters
#4RCLONE_PATH="/hetzner/kube.ia86.cc"
#4RCLONE_EXCLUDE=""
#4RESTIC_PATH="/hetzner/restic"
#4RESTIC_MONTHLY="12"
#4RESTIC_WEEKLY="10"
#4RESTIC_DAILY="31"
#4RESTIC_EXCLUDE=""
#5/mnt/usb/rclone/rclone.conf,644
#5[pcloud]
#5type = pcloud
#5hostname = eapi.pcloud.com
#5token = {"access_token":"%TOKEN%","token_type":"bearer","expiry":"0001-01-01T00:00:00Z"}
#5[crypt]
#5type = crypt
#5remote = pcloud:%REMOTE%
#5filename_encryption = standard
#5directory_name_encryption = true
#5password = %PASSWD1%
#5password2 = %PASSWD2%
#5[sauvegarde]
#5type = crypt
#5remote = pcloud:%REMOTE%
#5filename_encryption = standard
#5directory_name_encryption = true
#5password = %PASSWD3%
#5password2 = %PASSWD4%