borg_wrap.sh 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #!/bin/sh
  2. ##### This is my (demuredemeanor) borgbackup wrapper script.
  3. # Blog Post: https://demu.red/blog/2017/02/backups-revisited/
  4. # Source Code: https://notabug.org/demure/scripts/src/master/borg_wrap.sh
  5. # Uses tabstop=4; shiftwidth=4 tabs; foldmarker={{{,}}};
  6. #
  7. # This is a script to run my borg backups.
  8. # It has basic config error checking, and verifies I am on my home network.
  9. # Usage: borg_wrap.sh [-q|--quiet]
  10. #
  11. # Note: I run this as root, and have a /etc/sudoers.d/ file granting permissions.
  12. #
  13. # Note: I run this via crontab
  14. # 0 */1 * * * sudo /usr/local/sbin/borg_wrap.sh -q
  15. #
  16. # Note: pruning:
  17. # borg prune -v --list --dry-run -d=7 -w=4 -m=12 -y=-1 --keep-within=1d /media/store/backups/doom/
  18. ### Conf ### {{{
  19. ## Set Repo location
  20. #export BORG_REPO='/media/store/backups/doom/'
  21. export BORG_REPO='ssh://demure@10.0.0.10:500/mnt/borg/doom'
  22. ## Set the right ssh key
  23. ## Note, use with the following in the destination ssh authorized_keys
  24. ## command="borg serve --restrict-to-path /path/to/repo",no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-user-rc ssh-rsa AAAAB3[...]
  25. export BORG_RSH="ssh -i $HOME/.ssh/borg_id_ed25519"
  26. ## Pull Repo passwd
  27. export BORG_PASSPHRASE="$(pass cli/borg 2>/dev/null)"
  28. ## Path to log file
  29. Log_Path="$HOME/.config/borg/log"
  30. ## Temp file for log pruning
  31. Log_tmp="/tmp/borg_log.tmp"
  32. ## Define home routers MAC addr.
  33. MAC_addr="10:FE:ED:E9:63:04"
  34. ## Define remote address, for testing.
  35. Host="10.0.0.10"
  36. ### End Conf ### }}}
  37. ### Conf Check ### {{{
  38. ## Exit if BORG_REPO not specified.
  39. if [ "${BORG_REPO}" = "" ]; then
  40. echo 'No repo specified.'
  41. exit 78
  42. fi
  43. ## Exit if no log file specified.
  44. if [ "${Log_Path}" = "" ]; then
  45. echo 'No log file specified.'
  46. exit 78
  47. fi
  48. ## Exit if no router MAC specified.
  49. if [ "${MAC_addr}" = "" ]; then
  50. echo 'No router MAC specified.'
  51. exit 78
  52. fi
  53. ## Exit if storage address specified.
  54. if [ "${Host}" = "" ]; then
  55. echo 'No storage address specified.'
  56. exit 78
  57. fi
  58. ### End Conf Check ### }}}
  59. ### Startup Check ### {{{
  60. ### Augment Check ### {{{
  61. if [ $# -gt 1 ]; then
  62. echo 'Too many augments.'
  63. exit 1
  64. fi
  65. if [ ! -z "$1" ]; then
  66. if [ "$1" = '-q' ] || [ "$1" = '--Quiet' ]; then
  67. VERBOSE=""
  68. Quiet=1
  69. else
  70. echo 'Bad augments.'
  71. exit 1
  72. fi
  73. else
  74. VERBOSE='-v --stats -p'
  75. Quiet=0
  76. fi
  77. ### End Augment Check ### }}}
  78. ### Network Check ### {{{
  79. check_mac="$(/bin/ip neigh | awk '/router/ {} END {print $5}')"
  80. if [ ! "$MAC_addr" = "$check_mac" ]; then
  81. if [ $Quiet -eq 0 ]; then
  82. echo "Not on home network."
  83. fi
  84. Error='BadNet'
  85. else
  86. ping -c 3 $Host 1>/dev/null
  87. if [ ! $? = 0 ]; then
  88. if [ $Quiet -eq 0 ]; then
  89. echo "Can't reach host."
  90. fi
  91. Error='NoPing'
  92. fi
  93. fi
  94. ### End Network Check ### }}}
  95. ### Passwd Load Check ### {{{
  96. if [ -z "$BORG_PASSPHRASE" ]; then
  97. if [ $Quiet -eq 0 ]; then
  98. echo "Password failed to load."
  99. fi
  100. Error='NoPass'
  101. fi
  102. ### End Passed Load Check ### }}}
  103. ### End Startup Check ### }}}
  104. ## If no errors, run.
  105. if [ -z $Error ]; then
  106. borg create ${VERBOSE} -C lz4 \
  107. ::'{hostname}_{now:%Y-%m-%d_%H%M}' \
  108. / \
  109. --exclude-caches \
  110. -e /dev \
  111. -e /media/ \
  112. -e /mnt/ \
  113. -e /proc \
  114. -e /run \
  115. -e /sys \
  116. -e /tmp \
  117. -e /var/cache \
  118. -e '/var/tmp/*' \
  119. -e '/home/*/Downloads/' \
  120. -e '/home/*/temp/' \
  121. -e '/home/*/vault' \
  122. -e '/home/*/.config/chromium' \
  123. -e '/home/*/.local/share/mana/updates' \
  124. -e '*.cache' \
  125. -e '*.mail' \
  126. -e '*.thumbnails'
  127. ## Catch exit code
  128. Error=$?
  129. fi
  130. ## Log pass/fail state
  131. if [ ! $Error = "0" ]; then
  132. echo "$(date '+%F %T')\tfailed\t${Error}" | cat >> ${Log_Path}
  133. else
  134. echo "$(date '+%F %T')\tpassed" | cat >> ${Log_Path}
  135. fi
  136. ## This prunes the log, leaving last 30 days.
  137. ## If no passed backups in 30 days, also leaves lasted passed entry.
  138. ## You can comment out to disable
  139. awk -v cutoff="$(date -d"-30 days" +%F)" 'BEGIN{pchk=0} {a[i++]=$0} END{for(j=i-1;j>=0;j--) if(a[j] >= cutoff || pchk==0 && a[j] ~ /passed/){if(a[j] ~ /passed/){pchk=1}; b[k++]=a[j]};{for(l=k-1;l>=0;l--) print b[l]}}' ${Log_Path} > ${Log_tmp} && mv ${Log_tmp} ${Log_Path}
  140. ## Fix borg permissions so that things like `borg list` work without sudo
  141. ## This assumes that sudo preserves envars.
  142. chown -R ${USER}:${USER} ${HOME}/.config/borg ${HOME}/.cache/borg