mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-11-09 02:13:38 +00:00
[Web][Restic][Dovecot][Dockerapi] Add restic backups with restore in the UI
- Scheduled, encrypted backups to S3, SFTP, REST or a local folder (new restic-mailcow container) - Restore of mailboxes and whole domains in the UI, also deleted ones, for admins and domain admins - Scope set by RESTIC_BACKUP_MODE in mailcow.conf (all, data, config) - Optional backup before updates (update.sh), helper-scripts/restic.sh for a full restore
This commit is contained in:
66 files changed
+15214
-97
No files matched your search
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env bash
|
||||
# _modules/scripts/backup.sh
|
||||
# THIS SCRIPT IS DESIGNED TO BE RUNNING BY MAILCOW SCRIPTS ONLY!
|
||||
# DO NOT, AGAIN, NOT TRY TO RUN THIS SCRIPT STANDALONE!!!!!!
|
||||
|
||||
# Backup with restic before the update when it is set up (target, confirmed password, initialized repository):
|
||||
# interactive: asked for; --backup: without asking; --force: none (with --backup: without asking, a failure or a backup
|
||||
# that cannot run stops the update; only "not set up" continues)
|
||||
backup_failed() {
|
||||
echo -e "\e[31m${1}\e[0m"
|
||||
if [ "$FORCE" ]; then
|
||||
echo "The update was started with --force --backup, it stops here. Nothing was changed."
|
||||
exit 1
|
||||
fi
|
||||
read -r -p "Continue the update without a backup? [y/N] " backup_response
|
||||
if [[ ! "${backup_response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
echo "OK, exiting."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Whether to back up (asked with the other questions); the backup itself runs before the first change of the checkout
|
||||
backup_decide() {
|
||||
local output rc
|
||||
RUN_BACKUP=
|
||||
if [ "$FORCE" ] && [ ! "$BACKUP" ]; then
|
||||
return 0
|
||||
fi
|
||||
if [[ -z "$($COMPOSE_COMMAND ps -q restic-mailcow 2> /dev/null)" ]]; then
|
||||
output="the backup container does not run"
|
||||
rc=1
|
||||
else
|
||||
# exit code 0: set up, 2: not set up, others: error (e.g. credentials this container cannot read)
|
||||
output=$($COMPOSE_COMMAND exec -T restic-mailcow python3 /usr/local/bin/restic_runner.py --configured 2>&1 < /dev/null)
|
||||
rc=$?
|
||||
fi
|
||||
if [[ ${rc} -eq 2 ]]; then
|
||||
[ "$BACKUP" ] && echo -e "\e[33mNo backup before the update: ${output}.\e[0m"
|
||||
return 0
|
||||
elif [[ ${rc} -ne 0 ]]; then
|
||||
if [ "$BACKUP" ]; then
|
||||
backup_failed "No backup before the update possible: ${output}"
|
||||
elif [[ -n "$($COMPOSE_COMMAND ps -q restic-mailcow 2> /dev/null)" ]]; then
|
||||
echo -e "\e[33mNo backup before the update: ${output}\e[0m"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
if [ ! "$BACKUP" ]; then
|
||||
read -r -p "Create a backup before the update? [Y/n] " backup_response
|
||||
if [[ "${backup_response}" =~ ^([nN][oO]|[nN])$ ]]; then
|
||||
echo "OK, no backup."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
RUN_BACKUP=y
|
||||
}
|
||||
|
||||
# The backup chosen by backup_decide, once
|
||||
backup_run() {
|
||||
if [ ! "$RUN_BACKUP" ]; then
|
||||
return 0
|
||||
fi
|
||||
RUN_BACKUP=
|
||||
if [[ "${RESTIC_BACKUP_MODE}" =~ ^(data|config)$ ]]; then
|
||||
echo -e "\e[33mRESTIC_BACKUP_MODE=${RESTIC_BACKUP_MODE}: the backup holds no complete mailcow directory, a restore does not bring back this mailcow version.\e[0m"
|
||||
fi
|
||||
echo -e "\e[32mCreating a backup before the update...\e[0m"
|
||||
if ! $COMPOSE_COMMAND exec -T restic-mailcow python3 /usr/local/bin/restic_runner.py --backup < /dev/null; then
|
||||
backup_failed "The backup before the update failed, see the output above and the backup jobs in the mailcow UI."
|
||||
fi
|
||||
}
|
||||
@@ -61,6 +61,8 @@ adapt_new_options() {
|
||||
"ACME_DNS_PROVIDER"
|
||||
"ACME_ACCOUNT_EMAIL"
|
||||
"NGINX_MAX_BODY_SIZE"
|
||||
"RESTIC_LOCAL_PATH"
|
||||
"RESTIC_BACKUP_MODE"
|
||||
)
|
||||
|
||||
sed -i --follow-symlinks '$a\' mailcow.conf
|
||||
@@ -315,6 +317,19 @@ adapt_new_options() {
|
||||
echo '# Keep it above the message size limit of Postfix (100 MB by default). The mailcow UI and API stay limited to 64m.' >> mailcow.conf
|
||||
echo 'NGINX_MAX_BODY_SIZE=128m' >> mailcow.conf
|
||||
;;
|
||||
RESTIC_LOCAL_PATH)
|
||||
echo '# Folder on the host for backups to the target "local" (backup settings in the mailcow UI), as an absolute path,' >> mailcow.conf
|
||||
echo '# e.g. a NAS mounted from another disk. The repository is created in a subfolder of it.' >> mailcow.conf
|
||||
echo '# Empty: the Docker volume restic-repo-vol-1 of mailcow, on the same disk as the mailcow data.' >> mailcow.conf
|
||||
echo 'RESTIC_LOCAL_PATH=' >> mailcow.conf
|
||||
;;
|
||||
RESTIC_BACKUP_MODE)
|
||||
echo '# What the backups of the mailcow UI hold:' >> mailcow.conf
|
||||
echo '# - all (default),' >> mailcow.conf
|
||||
echo '# - data (vmail, vmail-index, database, redis, mail crypt keys and mailcow.conf)' >> mailcow.conf
|
||||
echo '# - config (database, redis, mail crypt keys, mailcow.conf and data/conf).' >> mailcow.conf
|
||||
echo 'RESTIC_BACKUP_MODE=all' >> mailcow.conf
|
||||
;;
|
||||
*)
|
||||
echo "${option}=" >> mailcow.conf
|
||||
;;
|
||||
|
||||
Reference in new issue
Block a user