diff --git a/Containers/borgbackup/backupscript.sh b/Containers/borgbackup/backupscript.sh index 62cf874e..03bd7b34 100644 --- a/Containers/borgbackup/backupscript.sh +++ b/Containers/borgbackup/backupscript.sh @@ -1,13 +1,9 @@ #!/bin/bash -# Variables -BORG_BACKUP_DIRECTORY="/mnt/borgbackup/borg" - # Functions get_start_time(){ START_TIME=$(date +%s) CURRENT_DATE=$(date --date @"$START_TIME" +"%Y%m%d_%H%M%S") - CURRENT_DATE_READABLE=$(date --date @"$START_TIME" +"%d.%m.%Y - %H:%M:%S") } get_expiration_time() { END_TIME=$(date +%s) @@ -150,9 +146,6 @@ if [ "$BORG_MODE" = backup ]; then # Remove the update skip file because the backup was successful rm -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/skip.update" - echo "$CURRENT_DATE,$CURRENT_DATE_READABLE" >> "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list" - chmod +r "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list" - # Prune options BORG_PRUNE_OPTS=(--stats --progress --keep-within=7d --keep-weekly=4 --keep-monthly=6 "$BORG_BACKUP_DIRECTORY") @@ -172,17 +165,20 @@ fi # Do the restore if [ "$BORG_MODE" = restore ]; then get_start_time - echo "Restoring the last backup..." # Perform the restore - FIRST_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)" + if [ -n "$SELECTED_RESTORE_TIME" ]; then + SELECTED_ARCHIVE"$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | grep "$SELECTED_RESTORE_TIME" | awk -F " " '{print $1}' | head -1)" + else + SELECTED_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)" + fi + echo "Restoring '$SELECTED_ARCHIVE'..." mkdir -p /tmp/borg - if ! borg mount "$BORG_BACKUP_DIRECTORY::$FIRST_ARCHIVE" /tmp/borg; then + if ! borg mount "$BORG_BACKUP_DIRECTORY::$SELECTED_ARCHIVE" /tmp/borg; then echo "Could not mount the backup!" exit 1 fi if ! rsync --stats --archive --human-readable -vv --delete \ - --exclude "nextcloud_aio_mastercontainer/data/backup_archives.list" \ --exclude "nextcloud_aio_mastercontainer/session/"** \ --exclude "nextcloud_aio_mastercontainer/certs/"** \ /tmp/borg/nextcloud_aio_volumes/ /nextcloud_aio_volumes; then diff --git a/Containers/borgbackup/start.sh b/Containers/borgbackup/start.sh index 9d23f26c..8781db49 100644 --- a/Containers/borgbackup/start.sh +++ b/Containers/borgbackup/start.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Variables +export BORG_BACKUP_DIRECTORY="/mnt/borgbackup/borg" + # Validate BORG_PASSWORD if [ -z "$BORG_PASSWORD" ]; then echo "BORG_PASSWORD is not allowed to be empty." @@ -24,6 +27,12 @@ fi # Remove lockfile rm -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running" +# Get a list of all available borg archives +set -x +borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1","$3,$4}' > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list" +chmod +r "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list" +set +x + if [ -n "$FAILED" ]; then if [ "$BORG_MODE" = backup ]; then # Add file to Nextcloud container so that it skips any update the next time diff --git a/php/containers.json b/php/containers.json index 52c94c4e..b50fa006 100644 --- a/php/containers.json +++ b/php/containers.json @@ -194,7 +194,8 @@ "internalPorts": [], "environmentVariables": [ "BORG_PASSWORD=%BORGBACKUP_PASSWORD%", - "BORG_MODE=%BORGBACKUP_MODE%" + "BORG_MODE=%BORGBACKUP_MODE%", + "SELECTED_RESTORE_TIME=%SELECTED_RESTORE_TIME%" ], "volumes": [ { diff --git a/php/public/index.php b/php/public/index.php index a1a8c189..8e5cf6fa 100644 --- a/php/public/index.php +++ b/php/public/index.php @@ -87,6 +87,7 @@ $app->get('/containers', function ($request, $response, $args) use ($container) 'was_start_button_clicked' => $configurationManager->wasStartButtonClicked(), 'has_update_available' => $dockerActionManger->isAnyUpdateAvailable(), 'last_backup_time' => $configurationManager->GetLastBackupTime(), + 'backup_times' => $configurationManager->GetBackupTimes(), ]); })->setName('profile'); $app->get('/login', function ($request, $response, $args) use ($container) { diff --git a/php/src/Controller/DockerController.php b/php/src/Controller/DockerController.php index 027832e5..1e0940e8 100644 --- a/php/src/Controller/DockerController.php +++ b/php/src/Controller/DockerController.php @@ -83,6 +83,7 @@ class DockerController public function StartBackupContainerRestore(Request $request, Response $response, $args) : Response { $config = $this->configurationManager->GetConfig(); $config['backup-mode'] = 'restore'; + $config['selected-restore-time'] = $request->getParsedBody()['selected_restore_time']; $this->configurationManager->WriteConfig($config); $id = self::TOP_CONTAINER; diff --git a/php/src/Data/ConfigurationManager.php b/php/src/Data/ConfigurationManager.php index ab1948e0..2a6c47fe 100644 --- a/php/src/Data/ConfigurationManager.php +++ b/php/src/Data/ConfigurationManager.php @@ -64,7 +64,7 @@ class ConfigurationManager } $content = file_get_contents(DataConst::GetBackupArchivesList()); - if ($content === "") { + if (count($content) === 0) { return ''; } @@ -83,6 +83,30 @@ class ConfigurationManager return $lastBackupTime; } + public function GetBackupTimes() : array { + if (!file_exists(DataConst::GetBackupArchivesList())) { + return $array[] = ''; + } + + $content = file_get_contents(DataConst::GetBackupArchivesList()); + if (count($content) === 0) { + return $array[] = ''; + } + + $backupLines = explode('\n', $content); + $backupTimes = []; + foreach($backupLines as $lines) { + $backupTimesTemp = explode(',', $lines); + $backupTimes[] = $backupTimesTemp[1]; + } + + if (!is_array($backupTimes)) { + return $array[] = ''; + } + + return $backupTimes; + } + public function wasStartButtonClicked() : bool { if (isset($this->GetConfig()['wasStartButtonClicked'])) { return true; @@ -152,6 +176,15 @@ class ConfigurationManager return $config['backup-mode']; } + public function GetSelectedRestoreTime() : string { + $config = $this->GetConfig(); + if(!isset($config['selected-restore-time'])) { + $config['selected-restore-time'] = ''; + } + + return $config['selected-restore-time']; + } + public function GetAIOURL() : string { $config = $this->GetConfig(); if(!isset($config['AIO_URL'])) { diff --git a/php/src/Docker/DockerActionManager.php b/php/src/Docker/DockerActionManager.php index cce5e481..349d99dd 100644 --- a/php/src/Docker/DockerActionManager.php +++ b/php/src/Docker/DockerActionManager.php @@ -212,6 +212,8 @@ class DockerActionManager $replacements[1] = $this->configurationManager->GetBackupMode(); } elseif ($out[1] === 'AIO_URL') { $replacements[1] = $this->configurationManager->GetAIOURL(); + } elseif ($out[1] === 'SELECTED_RESTORE_TIME') { + $replacements[1] = $this->configurationManager->GetSelectedRestoreTime(); } else { $replacements[1] = $this->configurationManager->GetSecret($out[1]); } diff --git a/php/templates/containers.twig b/php/templates/containers.twig index bc8f076e..b9b90fe5 100644 --- a/php/templates/containers.twig +++ b/php/templates/containers.twig @@ -206,11 +206,16 @@
- Click on the button below to restore the last backup from {{ last_backup_time }}. This will overwrite all your files with the state of the backup. It makes sense to run an integrity check before restoring your files but is not mandatory since it shouldn't be needed in most situations.

-
+ Choose the backup that you want to restore and click on the button below to restore the selected backup. This will overwrite all your files with the state of the backup so you should consider creating a backup first. It also makes sense to run an integrity check before restoring your files but is not mandatory since it shouldn't be needed in most situations.

+ - + +
{% endif %} {% endif %}