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