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
This commit is contained in:
Hilko 2020-11-26 13:13:31 +01:00 committed by GitHub
parent 82229ce04b
commit 8664afa997
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 11 deletions

View file

@ -456,6 +456,23 @@ def list_target_files(config):
raise ValueError(e.reason) raise ValueError(e.reason)
return [(key.name[len(path):], key.size) for key in bucket.list(prefix=path)] 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: else:
raise ValueError(config["target"]) raise ValueError(config["target"])

View file

@ -18,6 +18,7 @@
<option value="local">{{hostname}}</option> <option value="local">{{hostname}}</option>
<option value="rsync">rsync</option> <option value="rsync">rsync</option>
<option value="s3">Amazon S3</option> <option value="s3">Amazon S3</option>
<option value="b2">Backblaze B2</option>
</select> </select>
</div> </div>
</div> </div>
@ -111,6 +112,31 @@
<input type="text" class="form-control" rows="1" id="backup-target-pass"> <input type="text" class="form-control" rows="1" id="backup-target-pass">
</div> </div>
</div> </div>
<!-- Backblaze -->
<div class="form-group backup-target-b2">
<div class="col-sm-10 col-sm-offset-2">
<p>Backups are stored in a <a href="https://www.backblaze.com/" target="_blank" rel="noreferrer">Backblaze</a> B2 bucket. You must have a Backblaze account already.</p>
<p>You MUST manually copy the encryption password from <tt class="backup-encpassword-file"></tt> to a safe and secure location. You will need this file to decrypt backup files. It is NOT stored in your Backblaze B2 bucket.</p>
</div>
</div>
<div class="form-group backup-target-b2">
<label for="backup-target-b2-user" class="col-sm-2 control-label">B2 Application KeyID</label>
<div class="col-sm-8">
<input type="text" class="form-control" rows="1" id="backup-target-b2-user">
</div>
</div>
<div class="form-group backup-target-b2">
<label for="backup-target-b2-pass" class="col-sm-2 control-label">B2 Application Key</label>
<div class="col-sm-8">
<input type="text" class="form-control" rows="1" id="backup-target-b2-pass">
</div>
</div>
<div class="form-group backup-target-b2">
<label for="backup-target-b2-bucket" class="col-sm-2 control-label">B2 Bucket</label>
<div class="col-sm-8">
<input type="text" class="form-control" rows="1" id="backup-target-b2-bucket">
</div>
</div>
<!-- Common --> <!-- Common -->
<div class="form-group backup-target-local backup-target-rsync backup-target-s3"> <div class="form-group backup-target-local backup-target-rsync backup-target-s3">
<label for="min-age" class="col-sm-2 control-label">Retention Days:</label> <label for="min-age" class="col-sm-2 control-label">Retention Days:</label>
@ -144,7 +170,7 @@
function toggle_form() { function toggle_form() {
var target_type = $("#backup-target-type").val(); 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(); $(".backup-target-" + target_type).show();
init_inputs(target_type); init_inputs(target_type);
@ -215,7 +241,7 @@ function show_system_backup() {
} }
function show_custom_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( api(
"/system/backup/config", "/system/backup/config",
"GET", "GET",
@ -245,6 +271,15 @@ function show_custom_backup() {
var host = hostpath.shift(); var host = hostpath.shift();
$("#backup-target-s3-host").val(host); $("#backup-target-s3-host").val(host);
$("#backup-target-s3-path").val(hostpath.join('/')); $("#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() toggle_form()
}) })
@ -264,6 +299,11 @@ function set_custom_backup() {
target = "rsync://" + $("#backup-target-rsync-user").val() + "@" + $("#backup-target-rsync-host").val() target = "rsync://" + $("#backup-target-rsync-user").val() + "@" + $("#backup-target-rsync-host").val()
+ "/" + $("#backup-target-rsync-path").val(); + "/" + $("#backup-target-rsync-path").val();
target_user = ''; 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()); set_host($('#backup-target-s3-host-select').val());
} }
} }
</script> </script>

View file

@ -18,11 +18,7 @@ while [ -d /usr/local/lib/python3.4/dist-packages/acme ]; do
pip3 uninstall -y acme; pip3 uninstall -y acme;
done done
# duplicity is used to make backups of user data. It uses boto # duplicity is used to make backups of user data.
# (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.
# #
# virtualenv is used to isolate the Python 3 packages we # virtualenv is used to isolate the Python 3 packages we
# install via pip from the system-installed packages. # install via pip from the system-installed packages.
@ -30,7 +26,11 @@ done
# certbot installs EFF's certbot which we use to # certbot installs EFF's certbot which we use to
# provision free TLS certificates. # provision free TLS certificates.
apt_install duplicity python-pip virtualenv certbot 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 # Create a virtualenv for the installation of Python 3 packages
# used by the management daemon. # used by the management daemon.
@ -50,8 +50,8 @@ hide_output $venv/bin/pip install --upgrade pip
hide_output $venv/bin/pip install --upgrade \ hide_output $venv/bin/pip install --upgrade \
rtyaml "email_validator>=1.0.0" "exclusiveprocess" \ rtyaml "email_validator>=1.0.0" "exclusiveprocess" \
flask dnspython python-dateutil \ flask dnspython python-dateutil \
qrcode[pil] pyotp \ qrcode[pil] pyotp \
"idna>=2.0.0" "cryptography==2.2.2" boto psutil postfix-mta-sts-resolver "idna>=2.0.0" "cryptography==2.2.2" boto psutil postfix-mta-sts-resolver b2sdk
# CONFIGURATION # CONFIGURATION

View file

@ -93,6 +93,9 @@ hide_output add-apt-repository -y universe
# Install the certbot PPA. # Install the certbot PPA.
hide_output add-apt-repository -y ppa:certbot/certbot 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 Packages
# Update system packages to make sure we have the latest upstream versions # Update system packages to make sure we have the latest upstream versions