)) {
26 | ### specify the regex that defines how to find 'SearchDate'
27 | if ($ThisLine =~ m/\[$SearchDate\] /o) {
28 | print $ThisLine;
29 | }
30 | }
31 |
32 | # vi: shiftwidth=3 syntax=perl tabstop=3 et
33 | # Local Variables:
34 | # mode: perl
35 | # perl-indent-level: 3
36 | # indent-tabs-mode: nil
37 | # End:
38 |
--------------------------------------------------------------------------------
/root/NCscripts/503.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 503 - Unavailable: Backup in progress
7 |
8 |
9 |
17 |
18 |
19 |
20 | Bad timing!
21 | Seems you're trying to access me during my daily backup window. Don't
22 | worry though, I should be up and running again very soon.
23 | My average backup window duration is around 10 minutes during which time
24 | I'm quite busy copying your super-important files to my ultra-secret hiding
25 | place so they stay safe in case anything ever happens to me!
26 | I'm really sorry for the delay. Please try me again soon!
27 |
28 |
29 |
--------------------------------------------------------------------------------
/root/NCscripts/backup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 |
4 | ### Text formatting presets
5 | normal="\e[0m"
6 | bold="\e[1m"
7 | default="\e[39m"
8 | err="\e[1;31m"
9 | warn="\e[1;93m"
10 | ok="\e[32m"
11 | lit="\e[93m"
12 | op="\e[39m"
13 | info="\e[96m"
14 | note="\e[95m"
15 |
16 |
17 | ### Functions ###
18 |
19 | ### scriptHelp -- display usage information for this script
20 | function scriptHelp {
21 | echo -e "${bold}${note}\n${scriptName} usage instructions:\n${normal}"
22 | echo -e "${default}This script performs a backup of your NextCloud system"
23 | echo -e "assuming a fairly standard set up such as outlined at"
24 | echo -e "${lit}https://mytechiethoughts.com${default}. Full details about"
25 | echo -e "this script can be found at that site."
26 | echo -e "${bold}\nThe script performs the following tasks:${normal}${default}"
27 | echo -e "1. Puts NextCloud in maintenance mode."
28 | echo -e "2. Optionally copies a 503 error page to your webroot."
29 | echo -e "3. Dumps SQL to a temporary directory."
30 | echo -e "4. Invokes borgbackup to backup your SQL info, NextCloud program"
31 | echo -e "\tand data files along with any other files you specify."
32 | echo -e "5. Removes temp files, the 503 error page and restores"
33 | echo -e "\tNextCloud to operational status."
34 | echo -e "\nThe readme file included in this script's git contains detailed"
35 | echo -e "usage information. The following is a brief summary:\n"
36 | echo -e "${bold}${note}Mandatory parameters:${normal}${default}"
37 | echo -e "${lit}\n-d, NextCloud data directory${default}"
38 | echo -e "This is the physical location of your NextCloud data."
39 | echo -e "${lit}\n-n, NextCloud webroot${default}"
40 | echo -e "This is the location of the actual NextCloud web files (php & html"
41 | echo -e ",etc.), usually within your NGINX or Apache webroot."
42 | echo -e "${lit}\n-u, NGINX/Apache webuser account${default}"
43 | echo -e "The webuser account NGINX/Apache (and thus, NextCloud) are running"
44 | echo -e "under. Some actions must run as this user due to file ownership"
45 | echo -e "restrictions."
46 | echo -e "${bold}${note}\nOptional parameters:${normal}${default}"
47 | echo -e "${lit}\n-5, Location of 503 error page file${default}"
48 | echo -e "FULL PATH to the 503 error page HTML file you want copied to your"
49 | echo -e "webroot to inform users the server is down during the backup. If"
50 | echo -e "you don't specify a path/file, the default will be used. If the"
51 | echo -e "default cannot be found, a warning will be logged and the script"
52 | echo -e "will continue."
53 | echo -e "${info}Default: ScriptPath/503.html${default}"
54 | echo -e "${lit}\n-b, Location of file with borg repo details${default}"
55 | echo -e "FULL PATH to the plain text file containing all information needed"
56 | echo -e "to connect and process your borg repo. Details on the structure of"
57 | echo -e "this file are in the readme and on ${lit}https://mytechiethoughts.com${default}"
58 | echo -e "${info}Default: ScriptPath/nc_borg.details${default}"
59 | echo -e "${lit}\n-l, Location to save log file${default}"
60 | echo -e "This script writes a detailed log file of all activities. It is"
61 | echo -e "structured in an way easy for log parsers (like Logwatch) to read."
62 | echo -e "${info}Default: ScriptPath/ScriptName.log${default}"
63 | echo -e "${lit}\n-s, Location of file with mySQL details${default}"
64 | echo -e "FULL PATH to the plain text file containing all information needed"
65 | echo -e "to connect to your mySQL (mariaDB) server and NextCloud database."
66 | echo -e "Details on the structure of this file are in the readme and on ${lit}"
67 | echo -e "https://mytechiethoughts.com${default}"
68 | echo -e "${info}Default: ScriptPath/nc_sql.details${default}"
69 | echo -e "${lit}\n-v, Verbose output from borgbackup${default}"
70 | echo -e "By default, this script will only log summary data from borg."
71 | echo -e "If you need/want more detailed information, the verbose setting"
72 | echo -e "will list every file processed along with their status. Note: Your"
73 | echo -e "log file can quickly get very very large using this option!"
74 | echo -e "${info}Default: NOT activated (standard logging)${default}"
75 | echo -e "${lit}\n-w, webserver's webroot directory${default}"
76 | echo -e "This is the location from which your webserver (NGINX, Apache,"
77 | echo -e "etc.) physically stores files to be served. This is NOT the"
78 | echo -e "configuration directory for your webserver! It is the place"
79 | echo -e "where the actual HTML/PHP/CSS/JS/etc. files are stored."
80 | echo -e "NOTE: If you omit this option, then the entire 503 copy process"
81 | echo -e "will be skipped regardless of the presence of a 503.html file."
82 | echo -e "If you don't want to use the 503 feature, omitting this is an easy"
83 | echo -e "way to skip it!"
84 | echo -e "${info}Default: NONE${default}"
85 | echo -e "${lit}\n-?, This help screen${default}\n"
86 | echo -e "${bold}Please refer to the readme file and/or ${lit}https://mytechiethoughts.com${default}"
87 | echo -e "for more information on this script.${normal}\n"
88 | # exit with code 1 -- there is no use logging this
89 | exit 1
90 | }
91 |
92 | ### generate dynamic timestamps
93 | function stamp {
94 | echo `date +%F" "%T`
95 | }
96 |
97 | ### quit -- exit the script after logging any errors, warnings, etc.
98 | function quit {
99 | # list generated warnings, if any
100 | if [ ${#exitWarn[@]} -gt 0 ]; then
101 | echo -e "${warn}${scriptName} generated the following warnings:" \
102 | "${normal}" >> "$logFile"
103 | for warnCode in "${exitWarn[@]}"; do
104 | warnStamp="${warnCode%%_*}"
105 | warnValue="${warnCode##*_}"
106 | echo -e "${warn}${warnStamp} -- [WARNING]" \
107 | "${warningExplain[$warnValue]} (code: ${warnValue}) --" \
108 | "${normal}" >> "$logFile"
109 | done
110 | fi
111 | if [ -z "${exitError}" ]; then
112 | # exit cleanly
113 | echo -e "${note}[$(stamp)] --- ${scriptName} completed" \
114 | "---${normal}" >> "$logFile"
115 | exit 0
116 | else
117 | # list generated errors and explanations then exit script with code 2
118 | echo -e "${err}${scriptName} generated the following errors:" \
119 | "${normal}" >> "$logFile"
120 | for errCode in "${exitError[@]}"; do
121 | errStamp="${errCode%%_*}"
122 | errValue="${errCode##*_}"
123 | echo -e "${err}${errStamp} -- [ERROR] ${errorExplain[$errValue]}" \
124 | "(code: ${errValue}) --${normal}" >> "$logFile"
125 | done
126 | exit 2
127 | fi
128 | }
129 |
130 | function checkExist {
131 | if [ "$1" = "ff" ]; then
132 | # find file
133 | if [ -f "$2" ]; then
134 | # found
135 | return 0
136 | else
137 | # not found
138 | return 1
139 | fi
140 | elif [ "$1" = "fd" ]; then
141 | # find directory
142 | if [ -d "$2" ]; then
143 | # found
144 | return 0
145 | else
146 | # not found
147 | return 1
148 | fi
149 | fi
150 | }
151 |
152 | ### ncMaint - pass requested mode change type to NextCloud occ
153 | function ncMaint {
154 | sudo -u "${webUser}" php "${ncRoot}/occ" maintenance:mode --"$1" \
155 | >> "$logFile" 2>&1
156 | maintResult="$?"
157 | return "$maintResult"
158 | }
159 |
160 | ### cleanup - cleanup files and directories created by this script
161 | function cleanup {
162 | ## remove SQL dump file and directory
163 | rm -rf "$sqlDumpDir" >> "$logFile" 2>&1
164 | # verify directory is gone
165 | checkExist fd "$sqlDumpDir"
166 | checkResult="$?"
167 | if [ "$checkResult" = "0" ]; then
168 | # directory still exists
169 | exitWarn+=("[$(stamp)]_111")
170 | else
171 | # directory removed
172 | echo -e "${op}[$(stamp)] Removed SQL temp directory${normal}" \
173 | >> "$logFile"
174 | fi
175 |
176 | ## remove 503 error page
177 | # check value of 'clean503' to see if this is necessary (=1) otherwise, skip
178 | if [ "$clean503" = "1" ]; then
179 | # proceed with cleanup
180 | echo -e "${op}[$(stamp)] Removing 503 error page..." >> "$logFile"
181 | rm -f "$webroot/$err503File" >> "$logFile" 2>&1
182 | # verify file is actually gone
183 | checkExist ff "$webroot/$err503File"
184 | checkResult="$?"
185 | if [ "$checkResult" = "0" ]; then
186 | # file still exists
187 | exitWarn+=("[$(stamp)]_5030")
188 | else
189 | # file removed
190 | echo -e "${info}[$(stamp)] -- [INFO] 503 page removed from webroot" \
191 | "--${normal}" >> "$logFile"
192 | fi
193 | else
194 | echo -e "${op}[$(stamp)] 503 error page never copied to webroot," \
195 | "nothing to cleanup" >> "$logFile"
196 | fi
197 |
198 | ## Exit NextCloud maintenance mode regardless of current status
199 | ncMaint off
200 | # check if successful
201 | if [ "$maintResult" = "0" ]; then
202 | echo -e "${info}[$(stamp)] -- [INFO] NextCloud now in regular" \
203 | "operating mode --${normal}" >> "$logFile"
204 | else
205 | exitError+=("[$(stamp)]_101")
206 | quit
207 | fi
208 | }
209 |
210 | ### End of Functions ###
211 |
212 |
213 | ### Default parameters
214 |
215 | # store the logfile in the same directory as this script using the script's name
216 | # with the extension .log
217 | scriptPath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
218 | scriptName="$( basename ${0} )"
219 | logFile="$scriptPath/${scriptName%.*}.log"
220 |
221 | # set default 503 error page name and location in scriptPath
222 | err503Path="$scriptPath/503.html"
223 | err503File="${err503Path##*/}"
224 |
225 | # set default sqlDetails path to scriptPath
226 | sqlDetails="$scriptPath/nc_sql.details"
227 |
228 | # set default borgDetails path to scriptPath
229 | borgDetails="$scriptPath/nc_borg.details"
230 |
231 | # set borg parameters to 'normal' verbosity
232 | borgCreateParams='--stats'
233 | borgPruneParams='--list'
234 |
235 |
236 | ### Set script parameters to null and initialize array variables
237 | unset PARAMS
238 | unset sqlDumpDir
239 | unset webroot
240 | unset ncRoot
241 | unset webUser
242 | unset clean503
243 | unset sqlParams
244 | unset ncDataDir
245 | unset borgXtra
246 | unset borgExclude
247 | unset borgPrune
248 | unset BORG_BASE_DIR
249 | unset BORG_RSH
250 | unset BORG_REPO
251 | unset BORG_PASSPHRASE
252 | unset BORG_REMOTE_PATH
253 | unset TMPDIR
254 | exitError=()
255 | errorExplain=()
256 | exitWarn=()
257 | warningExplain=()
258 | borgConfig=()
259 | xtraFiles=()
260 |
261 | ### Error codes
262 | errorExplain[100]="Could not put NextCloud into maintenance mode"
263 | errorExplain[101]="Could not exit NextCloud maintenance mode"
264 | errorExplain[200]="Could not dump NextCloud SQL database"
265 | errorExplain[210]="Invalid or non-existant borg base directory specified (borg backup details file)"
266 | errorExplain[211]="Invalid or non-existant path to borg SSH keyfile (borg backup details file)"
267 | errorExplain[212]="Name of borg repo was not specified (borg backup details file)"
268 | errorExplain[215]="Could not find/create 'tmp' directory within borg base directory. Please manually create it and ensure it's writable"
269 | errorExplain[220]="Borg exited with a critical error. Please check this script's logfile for details"
270 | errorExplain[221]="Borg prune exited with ERRORS. Please check this script's logfile for details"
271 |
272 | ### Warning codes & messages
273 | warningExplain[111]="Could not remove SQL dump file and directory, please remove manually"
274 | warningExplain[5030]="Could not remove 503 error page. This MUST be removed manually before NGINX will serve webclients!"
275 | warningExplain[5031]="No webroot path was specified (-w parameter missing)"
276 | warningExplain[5032]="The specified webroot (-w parameter) could not be found"
277 | warningExplain[5033]="No 503 error page could be found. If not using the default located in the script directory, then check your -5 parameter"
278 | warningExplain[5035]="Error copying 503 error page to webroot"
279 | warn503="Web users will NOT be informed the server is down!"
280 | warningExplain[2111]="No password used for access to remote borg repo. This is an insecure configuration"
281 | warningExplain[2112]="No remote borg instance specified. Operations will be slower in this configuration"
282 | warningExplain[2113]="The specified file containing extra files for inclusion in borgbackup could not be found"
283 | warningExplain[2114]="The specified file containing exclusion patterns for borgbackup could not be found. Backup was performed as though NO exclusions were defined"
284 | warningExplain[2115]="No paramters provided for borg prune. No repo pruning has taken place. You should reconsider this decision to control the size/history of your backups"
285 | warningExplain[2116]="No additional locations are specified for inclusion in backup. ONLY NextCloud DATA will be backed up (no configuration, etc). If this is unintentional, check the inclusion file referenced in your borgbackup settings"
286 | warningExplain[2200]="Borg completed with warnings. Please check this script's logfile for details"
287 | warningExplain[2201]="Borg exited with an unknown return-code. Please check this script's logfile for details"
288 | warningExplain[2210]="Borg prune exited with warnings. Please check this script's logfile for details"
289 | warningExplain[2212]="Borg prune exited with an unknown return-code. Please check this script's logfile for details"
290 |
291 |
292 | ### Process script parameters
293 |
294 | # If parameters are provided but don't start with '-' then show the help page
295 | # and exit with an error
296 | if [ -n "$1" ] && [[ ! "$1" =~ ^- ]]; then
297 | # show script help page
298 | scriptHelp
299 | fi
300 |
301 | # use GetOpts to process parameters
302 | while getopts ':l:n:u:v5:w:s:b:d:' PARAMS; do
303 | case "$PARAMS" in
304 | l)
305 | # use provided location for logFile
306 | logFile="${OPTARG%/}"
307 | ;;
308 | n)
309 | # NextCloud webroot
310 | ncRoot="${OPTARG%/}"
311 | ;;
312 | u)
313 | # webuser
314 | webUser="${OPTARG}"
315 | ;;
316 | v)
317 | # verbose output from Borg
318 | borgCreateParams='--list --stats'
319 | borgPruneParams='--list'
320 | ;;
321 | 5)
322 | # Full path to 503 error page
323 | err503Path="${OPTARG%/}"
324 | err503File="${err503Path##*/}"
325 | ;;
326 | w)
327 | # path to webserver webroot to copy 503 error page
328 | webroot="${OPTARG%/}"
329 | ;;
330 | s)
331 | # path to file containing SQL login details
332 | sqlDetails="${OPTARG%/}"
333 | ;;
334 | b)
335 | # path to file containing borgbackup settings and details
336 | borgDetails="${OPTARG%/}"
337 | ;;
338 | d)
339 | # nextcloud data directory
340 | ncDataDir="${OPTARG%/}"
341 | ;;
342 | ?)
343 | # unrecognized parameters trigger scriptHelp
344 | scriptHelp
345 | ;;
346 | esac
347 | done
348 |
349 |
350 | ### Verify script pre-requisties
351 |
352 | ## If not running as root, display error on console and exit
353 | if [ $(id -u) -ne 0 ]; then
354 | echo -e "\n${err}This script MUST be run as ROOT. Exiting.${normal}"
355 | exit 3
356 | fi
357 |
358 | ## Check NextCloud webroot
359 | # Ensure NextCloud webroot is provided
360 | if [ -z "$ncRoot" ]; then
361 | echo -e "\n${err}The NextCloud webroot must be specified (-n parameter)" \
362 | "${normal}\n"
363 | exit 1
364 | # Ensure NextCloud webroot directory exists
365 | elif [ -n "$ncRoot" ]; then
366 | checkExist fd "$ncRoot"
367 | checkResult="$?"
368 | if [ "$checkResult" = "1" ]; then
369 | # Specified NextCloud webroot directory could not be found
370 | echo -e "\n${err}The provided NextCloud webroot directory" \
371 | "(-n parameter) does not exist.${normal}\n"
372 | exit 1
373 | fi
374 | fi
375 |
376 | ## Check NextCloud webuser account
377 | # Ensure NextCloud webuser account is provided
378 | if [ -z "$webUser" ]; then
379 | echo -e "\n${err}The webuser account running NextCloud must be provided" \
380 | "(-u parameter)${normal}\n"
381 | exit 1
382 | # Check if supplied webUser account exists
383 | elif [ -n "$webUser" ]; then
384 | user_exists=$(id -u "$webUser" > /dev/null 2>&1; echo $?)
385 | if [ "$user_exists" -ne 0 ]; then
386 | echo -e "\n${err}The supplied webuser account (-u parameter) does not" \
387 | "exist.${normal}\n"
388 | exit 1
389 | fi
390 | fi
391 |
392 | ## Ensure sqlDetails file exists
393 | checkExist ff "$sqlDetails"
394 | checkResult="$?"
395 | if [ "$checkResult" = "1" ]; then
396 | # sqlDetails file cannot be found
397 | echo -e "\n${err}The file containing your SQL details does not exist" \
398 | "(-s parameter)${normal}\n"
399 | exit 1
400 | fi
401 |
402 | ## Ensure borgDetails file exists
403 | checkExist ff "$borgDetails"
404 | checkResult="$?"
405 | if [ "$checkResult" = "1" ]; then
406 | # sqlDetails file cannot be found
407 | echo -e "\n${err}The file containing your borgbackup details does not" \
408 | "exist (-b parameter)${normal}\n"
409 | exit 1
410 | fi
411 |
412 | ## Check NextCloud data directory
413 | # Ensure NextCloud data directory is provided
414 | if [ -z "$ncDataDir" ]; then
415 | echo -e "\n${err}The NextCloud data directory must be specified" \
416 | "(-d parameter)${normal}\n"
417 | exit 1
418 | # Ensure NextCloud data directory exists
419 | elif [ -n "$ncDataDir" ]; then
420 | checkExist fd "$ncDataDir"
421 | checkResult="$?"
422 | if [ "$checkResult" = "1" ]; then
423 | # Specified NextCloud data directory could not be found
424 | echo -e "\n${err}The provided NextCloud data directory" \
425 | "(-d parameter) does not exist.${normal}\n"
426 | exit 1
427 | fi
428 | fi
429 |
430 |
431 | ### Log start of script operations
432 | echo -e "${note}[$(stamp)] --- Start $scriptName execution ---${normal}" \
433 | >> "$logFile"
434 | echo -e "${info}[$(stamp)] -- [INFO] Log file located at ${lit}${logFile}${info}" \
435 | "--${normal}" >> "$logFile"
436 |
437 |
438 | ### Export logFile variable for use by Borg
439 | export logFile="$logFile"
440 |
441 |
442 | ### Create sqlDump temporary directory and sqlDumpFile name
443 | sqlDumpDir=$( mktemp -d )
444 | sqlDumpFile="backup-`date +%Y%m%d_%H%M%S`.sql"
445 | echo -e "${info}[$(stamp)] -- [INFO] mySQL dump file will be stored" \
446 | "at: ${lit}${sqlDumpDir}/${sqlDumpFile}${normal}" >> "$logFile"
447 |
448 |
449 | ### 503 error page: If you don't plan on using the auto-copied 503 then comment
450 | ### this entire section starting with '--- Begin 503 section ---' until
451 | ### '--- End 503 section ---' to suppress generated warnings
452 |
453 | ### --- Begin 503 section ---
454 |
455 | ## Check if webroot has been specified, if not, skip this entire section since there is nowhere to copy the 503 file.
456 | if [ -z "$webroot" ]; then
457 | # no webroot path provided
458 | echo -e "${info}[$(stamp)] -- [INFO] ${warn503} --${normal}" \
459 | >> "$logFile"
460 | exitWarn+=("[$(stamp)]_5031")
461 | clean503=0
462 | else
463 | # verify webroot actually exists
464 | checkExist fd "$webroot"
465 | checkResult="$?"
466 | if [ "$checkResult" = "1" ]; then
467 | # webroot directory specified could not be found
468 | echo -e "${info}[$(stamp)] -- [INFO] ${warn503} --${normal}" \
469 | >> "$logFile"
470 | exitWarn+=("{$stamp}_5032")
471 | clean503=0
472 | else
473 | # webroot exists
474 | echo -e "${op}[$(stamp)] Using webroot: ${lit}${webroot}${normal}" \
475 | >> "$logFile"
476 | # Verify 503 file existance at given path
477 | checkExist ff "$err503Path"
478 | checkResult="$?"
479 | if [ "$checkResult" = "1" ]; then
480 | # 503 file could not be found
481 | echo -e "${info}[$(stamp)] -- [INFO] ${warn503} --${normal}" \
482 | >> "$logFile"
483 | exitWarn+=("[$(stamp)]_5033")
484 | clean503=0
485 | else
486 | # 503 file exists and webroot is valid. Let's copy it!
487 | echo -e "${op}[$(stamp)] ${err503File} found at ${lit}${err503Path}" \
488 | "${normal}" >> "$logFile"
489 | echo -e "${op}[$(stamp)] Copying 503 error page to webroot..." \
490 | "${normal}" >> "$logFile"
491 | cp "${err503Path}" "$webroot/" >> "$logFile" 2>&1
492 | copyResult="$?"
493 | # verify copy was successful
494 | if [ "$copyResult" = "1" ]; then
495 | # copy was unsuccessful
496 | echo -e "${info}[$(stamp)] -- [INFO] ${warn503} --${normal}" \
497 | >> "$logFile"
498 | exitWarn+=("[$(stamp)]_5035")
499 | clean503=0
500 | else
501 | # copy was successful
502 | echo -e "${info}[$(stamp)] -- [INFO] 503 error page" \
503 | "successfully copied to webroot --${normal}" >> "$logFile"
504 | clean503=1
505 | fi
506 | fi
507 | fi
508 | fi
509 |
510 | ### --- End 503 section ---
511 |
512 |
513 | ### Put NextCloud in maintenance mode
514 | ncMaint on
515 | # check if successful
516 | if [ "$maintResult" = "0" ]; then
517 | echo -e "${info}[$(stamp)] -- [INFO] NextCloud now in maintenance mode --" \
518 | "${normal}" >> "$logFile"
519 | else
520 | exitError+=("[$(stamp)]_100")
521 | cleanup
522 | quit
523 | fi
524 |
525 |
526 | ### Get SQL info from sqlDetails
527 | mapfile -t sqlParams < "$sqlDetails"
528 |
529 |
530 | ### Dump SQL
531 | echo -e "${op}[$(stamp)] Dumping NextCloud SQL database...${normal}" >> "$logFile"
532 | mysqldump --single-transaction -h"${sqlParams[0]}" -u"${sqlParams[1]}" \
533 | -p"${sqlParams[2]}" "${sqlParams[3]}" > "${sqlDumpDir}/${sqlDumpFile}" \
534 | 2>> "$logFile"
535 | # verify
536 | dumpResult="$?"
537 | if [ "$dumpResult" = "0" ]; then
538 | echo -e "${ok}[$(stamp)] -- [SUCCESS] SQL dumped successfully --${normal}" \
539 | >> "$logFile"
540 | else
541 | exitError+=("[$(stamp)]_200")
542 | cleanup
543 | quit
544 | fi
545 |
546 | ### Call borgbackup to copy actual files
547 | echo -e "${op}[$(stamp)] Pre-backup tasks completed, calling borgbackup..." \
548 | "${normal}" >> "$logFile"
549 |
550 | ## Get borgbackup settings and repo details
551 | # read definition file and map to array variable
552 | mapfile -t borgConfig < "$borgDetails"
553 | ## check if any required borg configuration variables in defintion file are
554 | ## empty and exit with error, otherwise, map array items to variables
555 | # check: borg base directory
556 | echo -e "${op}[$(stamp)] Verifying supplied borg configuration variables..." \
557 | "${normal}" >> "$logFile"
558 | if [ -z "${borgConfig[0]}" ]; then
559 | exitError+=("[$(stamp)]_210")
560 | cleanup
561 | quit
562 | else
563 | # verify the path actually exists
564 | checkExist fd "${borgConfig[0]}"
565 | checkResult="$?"
566 | if [ "$checkResult" = "1" ]; then
567 | # borg base directory specified could not be found
568 | exitError+=("[$(stamp)]_210")
569 | cleanup
570 | quit
571 | fi
572 | echo -e "${op}[$(stamp)] Borg base dir... OK${normal}" >> "$logFile"
573 | export BORG_BASE_DIR="${borgConfig[0]%/}"
574 | fi
575 | # check: path to SSH keyfile
576 | if [ -z "${borgConfig[1]}" ]; then
577 | exitError+=("[$(stamp)]_211")
578 | cleanup
579 | quit
580 | else
581 | checkExist ff "${borgConfig[1]}"
582 | checkResult="$?"
583 | if [ "$checkResult" = 1 ]; then
584 | # SSH keyfile specified could not be found
585 | exitError+=("[$(stamp)]_211")
586 | cleanup
587 | quit
588 | fi
589 | echo -e "${op}[$(stamp)] Borg SSH key... OK${normal}" >> "$logFile"
590 | export BORG_RSH="ssh -i ${borgConfig[1]}"
591 | fi
592 | # check: name of borg repo
593 | if [ -z "${borgConfig[2]}" ]; then
594 | exitError+=("[$(stamp)]_212")
595 | cleanup
596 | quit
597 | else
598 | echo -e "${op}[$(stamp)] Borg REPO name... OK${normal}" >> "$logFile"
599 | export BORG_REPO="${borgConfig[2]}"
600 | fi
601 | # repo password
602 | if [ -n "${borgConfig[3]}" ]; then
603 | echo -e "${op}[$(stamp)] Borg REPO password... OK${normal}" >> "$logFile"
604 | export BORG_PASSPHRASE="${borgConfig[3]}"
605 | else
606 | exitWarn+=("[$(stamp)]_2111")
607 | # if the password was omitted by mistake, export a dummy password so borg
608 | # fails with an error instead of sitting and waiting for input
609 | export BORG_PASSPHRASE="DummyPasswordSoBorgFails"
610 | fi
611 | # additional files to be backed up
612 | borgXtra="${borgConfig[4]}"
613 | # file with pattern definition for excluded files
614 | borgExclude="${borgConfig[5]}"
615 | # parameters for borg prune
616 | borgPrune="${borgConfig[6]}"
617 | # export: borg remote path (if not blank)
618 | if [ -n "${borgConfig[7]}" ]; then
619 | echo -e "${op}[$(stamp)] Borg REMOTE path... OK${normal}" >> "$logFile"
620 | export BORG_REMOTE_PATH="${borgConfig[7]}"
621 | else
622 | exitWarn+=("[$(stamp)]_2112")
623 | fi
624 |
625 | ## If borgXtra exists, map contents to an array variable
626 | if [ -n "$borgXtra" ]; then
627 | echo -e "${op}[$(stamp)] Processing referenced extra files list for" \
628 | "borgbackup to include in backup${normal}" >> "$logFile"
629 | checkExist ff "$borgXtra"
630 | checkResult="$?"
631 | if [ "$checkResult" = "0" ]; then
632 | echo -e "${op}[$(stamp)] Found ${lit}${borgXtra}${normal}" >> "$logFile"
633 | mapfile -t xtraFiles < "$borgXtra"
634 | echo -e "${op}[$(stamp)] Processed extra files list for inclusion in" \
635 | "borgbackup${normal}" >> "$logFile"
636 | else
637 | exitWarn+=("[$(stamp)]_2113")
638 | fi
639 | else
640 | # no extra locations specified
641 | echo -e "${op}[$(stamp)] No additional locations specified for backup." \
642 | "Only NextCloud data files will be backed up${normal}" >> "$logFile"
643 | exitWarn+=("[$(stamp)]_2116")
644 | fi
645 |
646 | ## Check if borgExclude exists since borg will throw an error if it's missing
647 | if [ -n "$borgExclude" ]; then
648 | checkExist ff "$borgExclude"
649 | checkResult="$?"
650 | if [ "$checkResult" = "0" ]; then
651 | echo -e "${op}[$(stamp)] Found ${lit}${borgExclude}${normal}" \
652 | >> "$logFile"
653 | else
654 | # file not found, unset the variable so it's like it was not specified
655 | # in the first place and continue with backup
656 | unset borgExclude
657 | exitWarn+=("[$(stamp)]_2114")
658 | fi
659 | else
660 | echo -e "${op}[$(stamp)] Exclusion pattern file not specified." \
661 | "No exclusions will be processed${normal}" >> "$logFile"
662 | fi
663 |
664 |
665 | ## Export TMPDIR environment variable for borg via python
666 | ## Python requires a writable temporary directory when unpacking borg and
667 | ## executing commands. This defaults to /tmp but many systems mount /tmp with
668 | ## the 'noexec' option for security. Thus, we will use/create a 'tmp' folder
669 | ## within the BORG_BASE_DIR and instruct python to use that instead of /tmp
670 | # check if BORG_BASE_DIR/tmp exists, if not, create it
671 | echo -e "${op}[$(stamp)] Checking for tmp directory at ${lit}${BORG_BASE_DIR}" \
672 | "${normal}" >> "$logFile"
673 | checkExist fd "$BORG_BASE_DIR/tmp"
674 | checkResult="$?"
675 | if [ "$checkResult" = "1" ]; then
676 | # folder not found
677 | echo -e "${op}[$(stamp)] tmp folder not found... creating${lit}" \
678 | "${BORG_BASE_DIR}/tmp${normal}" >> "$logFile"
679 | mkdir "$BORG_BASE_DIR/tmp" 2>> "$logFile"
680 | # verify folder created
681 | checkExist fd "$BORG_BASE_DIR/tmp"
682 | checkResult="$?"
683 | if [ "$checkResult" = "0" ]; then
684 | # folder exists
685 | echo -e "${op}[$(stamp)] tmp folder created within borg base directory" \
686 | "${normal}" >> "$logFile"
687 | else
688 | # problem creating folder and script will exit
689 | exitError+=("[$(stamp)]_215")
690 | cleanup
691 | quit
692 | fi
693 | else
694 | # folder found
695 | echo -e "${op}[$(stamp)] tmp folder found within borg base directory" \
696 | "${normal}" >> "$logFile"
697 | fi
698 | # export TMPDIR environment variable
699 | export TMPDIR="${BORG_BASE_DIR}/tmp"
700 |
701 |
702 | ## Generate and execute borg
703 | # commandline depends on whether borgExclude is empty or not
704 | if [ -z "$borgExclude" ]; then
705 | # borgExclude is empty
706 | echo -e "${info}[$(stamp)] --[INFO] Executing borg without exclusions --" \
707 | "${normal}" >> "$logFile"
708 | borg --show-rc create ${borgCreateParams} ::`date +%Y-%m-%d_%H%M%S` \
709 | "${xtraFiles[@]}" \
710 | "${sqlDumpDir}" "${ncDataDir}" \
711 | 2>> "$logFile"
712 | else
713 | # borgExclude is not empty
714 | echo -e "${info}[$(stamp)] --[INFO] Executing borg with exclusions --" \
715 | "${normal}" >> "$logFile"
716 | borg --show-rc create ${borgCreateParams} --exclude-from "${borgExclude}" \
717 | ::`date +%Y-%m-%d_%H%M%S` \
718 | "${xtraFiles[@]}" \
719 | "${sqlDumpDir}" "${ncDataDir}" \
720 | 2>> "$logFile"
721 | fi
722 |
723 | ## Check status of borg operation
724 | borgResult="$?"
725 | if [ "$borgResult" -eq 0 ]; then
726 | echo -e "${ok}[$(stamp)] -- [SUCCESS] Borg backup completed successfully --" \
727 | "${normal}" >> "$logFile"
728 | elif [ "$borgResult" -eq 1 ]; then
729 | exitWarn+=("[$(stamp)]_2200")
730 | elif [ "$borgResult" -ge 2 ]; then
731 | exitError+=("[$(stamp)]_220")
732 | cleanup
733 | quit
734 | else
735 | exitWarn+=("[$(stamp)]_2201")
736 | fi
737 |
738 | ## Generate and execute borg prune
739 | # command depends on whether or not parameters have been defined
740 | if [ -n "$borgPrune" ]; then
741 | # parameters defined
742 | echo -e "${info}[$(stamp)] --[INFO] Executing borg prune operation --" \
743 | "${normal}" >> "$logFile"
744 | borg prune --show-rc -v ${borgPruneParams} ${borgPrune} \
745 | 2>> "$logFile"
746 | # check return-status
747 | pruneResult="$?"
748 | if [ "$pruneResult" -eq 0 ]; then
749 | echo -e "${ok}[$(stamp)] -- [SUCCESS] Borg prune completed successfully" \
750 | "--${normal}" >> "$logFile"
751 | elif [ "$pruneResult" -eq 1 ]; then
752 | exitWarn+=("[$(stamp)]_2210")
753 | elif [ "$pruneResult" -ge 2 ]; then
754 | exitError+=("[$(stamp)]_221")
755 | else
756 | exitWarn+=("[$(stamp)]_2212")
757 | fi
758 | else
759 | # parameters not defined... skip pruning
760 | exitWarn+=("[$(stamp)]_2115")
761 | fi
762 |
763 |
764 | ### borgbackup completed
765 | echo -e "${op}[$(stamp)] Borgbackup completed... begin cleanup" \
766 | "${normal}" >> "$logFile"
767 |
768 |
769 | ### Exit script
770 | echo -e "${bold}${op}[$(stamp)] ***Normal exit process***${normal}" \
771 | >> "$logFile"
772 | cleanup
773 | echo -e "${bold}${ok}[$(stamp)] -- [SUCCESS] All processes completed" \
774 | "successfully --${normal}" >> "$logFile"
775 | quit
776 |
777 | # This code should not be executed since the 'quit' function should terminate
778 | # this script. Therefore, exit with code 99 if we get to this point.
779 | exit 99
780 |
--------------------------------------------------------------------------------
/root/NCscripts/excludeLocations.borg:
--------------------------------------------------------------------------------
1 | '/var/nc_data/cache'
2 | sh:/var/nc_data/appdata_*/preview/
3 | EOF
4 |
--------------------------------------------------------------------------------
/root/NCscripts/nc_borg.details:
--------------------------------------------------------------------------------
1 | /var/borgbackup
2 | /var/borgbackup/sshPrivate.key
3 | user@servername.tld:repoName/
4 | pAsSwOrd
5 | /root/NCscripts/xtraLocations.borg
6 | /root/NCscripts/excludeLocations.borg
7 | --keep-within=7d --keep-daily=30 --keep-weekly=12 --keep-monthly=-1
8 | borg1
--------------------------------------------------------------------------------
/root/NCscripts/nc_sql.details:
--------------------------------------------------------------------------------
1 | localhost
2 | nextcloud
3 | pAsSwOrd
4 | nextcloudDB
5 |
--------------------------------------------------------------------------------
/root/NCscripts/xtraLocations.borg:
--------------------------------------------------------------------------------
1 | /etc/fstab
2 | /etc/network/interfaces
3 | /etc/network/interfaces.d/
4 | /etc/systemd/timesyncd.conf
5 | /etc/profile
6 | /etc/bash.bashrc
7 | /etc/skel/
8 | /etc/nanorc
9 | /etc/msmtprc
10 | /etc/msmtp_aliases
11 | /etc/apt/sources.list
12 | /etc/apt/sources.list.d/
13 | /etc/apt/listchanges.conf
14 | /etc/apt/apt.conf.d/50unattended-upgrades
15 | /etc/apt/apt.conf.d/20auto-upgrades
16 | /etc/ssh/
17 | /etc/logwatch/
18 | /etc/letsencrypt/
19 | /etc/fail2ban/fail2ban.local
20 | /etc/fail2ban/jail.local
21 | /etc/fail2ban/filter.d/nextcloud.conf
22 | /etc/fail2ban/jail.d/
23 | /root/.bashrc
24 | /root/NCscripts/
25 | /root/.ssh/
26 | /etc/mysql/my.cnf
27 | /etc/nginx/
28 | /etc/php/7.2/cli/php.ini
29 | /etc/php/7.2/fpm/php-fpm.conf
30 | /etc/php/7.2/fpm/php.ini
31 | /etc/php/7.2/fpm/pool.d/www.conf
32 | /etc/redis/redis.conf
33 | /usr/share/nginx/html/
--------------------------------------------------------------------------------