From 8664afa99798c9dbd7b52cf67da7e90b3280bbf0 Mon Sep 17 00:00:00 2001 From: Hilko Date: Thu, 26 Nov 2020 13:13:31 +0100 Subject: [PATCH] Implement Backblaze for Backup (#1812) * Installing b2sdk for b2 support * Added Duplicity PPA so the most recent version is used * Implemented list_target_files for b2 * Implemented b2 in frontend * removed python2 boto package --- management/backup.py | 17 +++++++++ management/templates/system-backup.html | 46 +++++++++++++++++++++++-- setup/management.sh | 16 ++++----- setup/system.sh | 3 ++ 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/management/backup.py b/management/backup.py index e1651552..0a8a021e 100755 --- a/management/backup.py +++ b/management/backup.py @@ -456,6 +456,23 @@ def list_target_files(config): raise ValueError(e.reason) return [(key.name[len(path):], key.size) for key in bucket.list(prefix=path)] + elif target.scheme == 'b2': + from b2sdk.v1 import InMemoryAccountInfo, B2Api + from b2sdk.v1.exception import NonExistentBucket + info = InMemoryAccountInfo() + b2_api = B2Api(info) + + # Extract information from target + b2_application_keyid = target.netloc[:target.netloc.index(':')] + b2_application_key = target.netloc[target.netloc.index(':')+1:target.netloc.index('@')] + b2_bucket = target.netloc[target.netloc.index('@')+1:] + + try: + b2_api.authorize_account("production", b2_application_keyid, b2_application_key) + bucket = b2_api.get_bucket_by_name(b2_bucket) + except NonExistentBucket as e: + raise ValueError("B2 Bucket does not exist. Please double check your information!") + return [(key.file_name, key.size) for key, _ in bucket.ls()] else: raise ValueError(config["target"]) diff --git a/management/templates/system-backup.html b/management/templates/system-backup.html index 6afe62c8..7cdc3803 100644 --- a/management/templates/system-backup.html +++ b/management/templates/system-backup.html @@ -18,6 +18,7 @@ + @@ -111,6 +112,31 @@ + +
+
+

Backups are stored in a Backblaze B2 bucket. You must have a Backblaze account already.

+

You MUST manually copy the encryption password from to a safe and secure location. You will need this file to decrypt backup files. It is NOT stored in your Backblaze B2 bucket.

+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
@@ -144,7 +170,7 @@ function toggle_form() { var target_type = $("#backup-target-type").val(); - $(".backup-target-local, .backup-target-rsync, .backup-target-s3").hide(); + $(".backup-target-local, .backup-target-rsync, .backup-target-s3, .backup-target-b2").hide(); $(".backup-target-" + target_type).show(); init_inputs(target_type); @@ -215,7 +241,7 @@ function show_system_backup() { } function show_custom_backup() { - $(".backup-target-local, .backup-target-rsync, .backup-target-s3").hide(); + $(".backup-target-local, .backup-target-rsync, .backup-target-s3, .backup-target-b2").hide(); api( "/system/backup/config", "GET", @@ -245,6 +271,15 @@ function show_custom_backup() { var host = hostpath.shift(); $("#backup-target-s3-host").val(host); $("#backup-target-s3-path").val(hostpath.join('/')); + } else if (r.target.substring(0, 5) == "b2://") { + $("#backup-target-type").val("b2"); + var targetPath = r.target.substring(5); + var b2_application_keyid = targetPath.split(':')[0]; + var b2_applicationkey = targetPath.split(':')[1].split('@')[0]; + var b2_bucket = targetPath.split('@')[1]; + $("#backup-target-b2-user").val(b2_application_keyid); + $("#backup-target-b2-pass").val(b2_applicationkey); + $("#backup-target-b2-bucket").val(b2_bucket); } toggle_form() }) @@ -264,6 +299,11 @@ function set_custom_backup() { target = "rsync://" + $("#backup-target-rsync-user").val() + "@" + $("#backup-target-rsync-host").val() + "/" + $("#backup-target-rsync-path").val(); target_user = ''; + } else if (target_type == "b2") { + target = 'b2://' + $('#backup-target-b2-user').val() + ':' + $('#backup-target-b2-pass').val() + + '@' + $('#backup-target-b2-bucket').val() + target_user = ''; + target_pass = ''; } @@ -303,4 +343,4 @@ function init_inputs(target_type) { set_host($('#backup-target-s3-host-select').val()); } } - + \ No newline at end of file diff --git a/setup/management.sh b/setup/management.sh index ae942985..f5685d4f 100755 --- a/setup/management.sh +++ b/setup/management.sh @@ -18,11 +18,7 @@ while [ -d /usr/local/lib/python3.4/dist-packages/acme ]; do pip3 uninstall -y acme; done -# duplicity is used to make backups of user data. It uses boto -# (via Python 2) to do backups to AWS S3. boto from the Ubuntu -# package manager is too out-of-date -- it doesn't support the newer -# S3 api used in some regions, which breaks backups to those regions. -# See #627, #653. +# duplicity is used to make backups of user data. # # virtualenv is used to isolate the Python 3 packages we # install via pip from the system-installed packages. @@ -30,7 +26,11 @@ done # certbot installs EFF's certbot which we use to # provision free TLS certificates. apt_install duplicity python-pip virtualenv certbot -hide_output pip2 install --upgrade boto + +# b2sdk is used for backblaze backups. +# boto is used for amazon aws backups. +# Both are installed outside the pipenv, so they can be used by duplicity +hide_output pip3 install --upgrade b2sdk boto # Create a virtualenv for the installation of Python 3 packages # used by the management daemon. @@ -50,8 +50,8 @@ hide_output $venv/bin/pip install --upgrade pip hide_output $venv/bin/pip install --upgrade \ rtyaml "email_validator>=1.0.0" "exclusiveprocess" \ flask dnspython python-dateutil \ - qrcode[pil] pyotp \ - "idna>=2.0.0" "cryptography==2.2.2" boto psutil postfix-mta-sts-resolver + qrcode[pil] pyotp \ + "idna>=2.0.0" "cryptography==2.2.2" boto psutil postfix-mta-sts-resolver b2sdk # CONFIGURATION diff --git a/setup/system.sh b/setup/system.sh index 4d33deb6..07f4aa1b 100755 --- a/setup/system.sh +++ b/setup/system.sh @@ -93,6 +93,9 @@ hide_output add-apt-repository -y universe # Install the certbot PPA. hide_output add-apt-repository -y ppa:certbot/certbot +# Install the duplicity PPA. +hide_output add-apt-repository -y ppa:duplicity-team/duplicity-release-git + # ### Update Packages # Update system packages to make sure we have the latest upstream versions