Skip to content

Commit 8664afa

Browse files
authoredNov 26, 2020
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
1 parent 82229ce commit 8664afa

File tree

4 files changed

+71
-11
lines changed

4 files changed

+71
-11
lines changed
 

‎management/backup.py

+17
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,23 @@ def list_target_files(config):
456456
raise ValueError(e.reason)
457457

458458
return [(key.name[len(path):], key.size) for key in bucket.list(prefix=path)]
459+
elif target.scheme == 'b2':
460+
from b2sdk.v1 import InMemoryAccountInfo, B2Api
461+
from b2sdk.v1.exception import NonExistentBucket
462+
info = InMemoryAccountInfo()
463+
b2_api = B2Api(info)
464+
465+
# Extract information from target
466+
b2_application_keyid = target.netloc[:target.netloc.index(':')]
467+
b2_application_key = target.netloc[target.netloc.index(':')+1:target.netloc.index('@')]
468+
b2_bucket = target.netloc[target.netloc.index('@')+1:]
469+
470+
try:
471+
b2_api.authorize_account("production", b2_application_keyid, b2_application_key)
472+
bucket = b2_api.get_bucket_by_name(b2_bucket)
473+
except NonExistentBucket as e:
474+
raise ValueError("B2 Bucket does not exist. Please double check your information!")
475+
return [(key.file_name, key.size) for key, _ in bucket.ls()]
459476

460477
else:
461478
raise ValueError(config["target"])

‎management/templates/system-backup.html

+43-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ <h3>Configuration</h3>
1818
<option value="local">{{hostname}}</option>
1919
<option value="rsync">rsync</option>
2020
<option value="s3">Amazon S3</option>
21+
<option value="b2">Backblaze B2</option>
2122
</select>
2223
</div>
2324
</div>
@@ -111,6 +112,31 @@ <h3>Configuration</h3>
111112
<input type="text" class="form-control" rows="1" id="backup-target-pass">
112113
</div>
113114
</div>
115+
<!-- Backblaze -->
116+
<div class="form-group backup-target-b2">
117+
<div class="col-sm-10 col-sm-offset-2">
118+
<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>
119+
<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>
120+
</div>
121+
</div>
122+
<div class="form-group backup-target-b2">
123+
<label for="backup-target-b2-user" class="col-sm-2 control-label">B2 Application KeyID</label>
124+
<div class="col-sm-8">
125+
<input type="text" class="form-control" rows="1" id="backup-target-b2-user">
126+
</div>
127+
</div>
128+
<div class="form-group backup-target-b2">
129+
<label for="backup-target-b2-pass" class="col-sm-2 control-label">B2 Application Key</label>
130+
<div class="col-sm-8">
131+
<input type="text" class="form-control" rows="1" id="backup-target-b2-pass">
132+
</div>
133+
</div>
134+
<div class="form-group backup-target-b2">
135+
<label for="backup-target-b2-bucket" class="col-sm-2 control-label">B2 Bucket</label>
136+
<div class="col-sm-8">
137+
<input type="text" class="form-control" rows="1" id="backup-target-b2-bucket">
138+
</div>
139+
</div>
114140
<!-- Common -->
115141
<div class="form-group backup-target-local backup-target-rsync backup-target-s3">
116142
<label for="min-age" class="col-sm-2 control-label">Retention Days:</label>
@@ -144,7 +170,7 @@ <h3>Available backups</h3>
144170

145171
function toggle_form() {
146172
var target_type = $("#backup-target-type").val();
147-
$(".backup-target-local, .backup-target-rsync, .backup-target-s3").hide();
173+
$(".backup-target-local, .backup-target-rsync, .backup-target-s3, .backup-target-b2").hide();
148174
$(".backup-target-" + target_type).show();
149175

150176
init_inputs(target_type);
@@ -215,7 +241,7 @@ <h3>Available backups</h3>
215241
}
216242

217243
function show_custom_backup() {
218-
$(".backup-target-local, .backup-target-rsync, .backup-target-s3").hide();
244+
$(".backup-target-local, .backup-target-rsync, .backup-target-s3, .backup-target-b2").hide();
219245
api(
220246
"/system/backup/config",
221247
"GET",
@@ -245,6 +271,15 @@ <h3>Available backups</h3>
245271
var host = hostpath.shift();
246272
$("#backup-target-s3-host").val(host);
247273
$("#backup-target-s3-path").val(hostpath.join('/'));
274+
} else if (r.target.substring(0, 5) == "b2://") {
275+
$("#backup-target-type").val("b2");
276+
var targetPath = r.target.substring(5);
277+
var b2_application_keyid = targetPath.split(':')[0];
278+
var b2_applicationkey = targetPath.split(':')[1].split('@')[0];
279+
var b2_bucket = targetPath.split('@')[1];
280+
$("#backup-target-b2-user").val(b2_application_keyid);
281+
$("#backup-target-b2-pass").val(b2_applicationkey);
282+
$("#backup-target-b2-bucket").val(b2_bucket);
248283
}
249284
toggle_form()
250285
})
@@ -264,6 +299,11 @@ <h3>Available backups</h3>
264299
target = "rsync://" + $("#backup-target-rsync-user").val() + "@" + $("#backup-target-rsync-host").val()
265300
+ "/" + $("#backup-target-rsync-path").val();
266301
target_user = '';
302+
} else if (target_type == "b2") {
303+
target = 'b2://' + $('#backup-target-b2-user').val() + ':' + $('#backup-target-b2-pass').val()
304+
+ '@' + $('#backup-target-b2-bucket').val()
305+
target_user = '';
306+
target_pass = '';
267307
}
268308

269309

@@ -303,4 +343,4 @@ <h3>Available backups</h3>
303343
set_host($('#backup-target-s3-host-select').val());
304344
}
305345
}
306-
</script>
346+
</script>

‎setup/management.sh

+8-8
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ while [ -d /usr/local/lib/python3.4/dist-packages/acme ]; do
1818
pip3 uninstall -y acme;
1919
done
2020

21-
# duplicity is used to make backups of user data. It uses boto
22-
# (via Python 2) to do backups to AWS S3. boto from the Ubuntu
23-
# package manager is too out-of-date -- it doesn't support the newer
24-
# S3 api used in some regions, which breaks backups to those regions.
25-
# See #627, #653.
21+
# duplicity is used to make backups of user data.
2622
#
2723
# virtualenv is used to isolate the Python 3 packages we
2824
# install via pip from the system-installed packages.
2925
#
3026
# certbot installs EFF's certbot which we use to
3127
# provision free TLS certificates.
3228
apt_install duplicity python-pip virtualenv certbot
33-
hide_output pip2 install --upgrade boto
29+
30+
# b2sdk is used for backblaze backups.
31+
# boto is used for amazon aws backups.
32+
# Both are installed outside the pipenv, so they can be used by duplicity
33+
hide_output pip3 install --upgrade b2sdk boto
3434

3535
# Create a virtualenv for the installation of Python 3 packages
3636
# used by the management daemon.
@@ -50,8 +50,8 @@ hide_output $venv/bin/pip install --upgrade pip
5050
hide_output $venv/bin/pip install --upgrade \
5151
rtyaml "email_validator>=1.0.0" "exclusiveprocess" \
5252
flask dnspython python-dateutil \
53-
qrcode[pil] pyotp \
54-
"idna>=2.0.0" "cryptography==2.2.2" boto psutil postfix-mta-sts-resolver
53+
qrcode[pil] pyotp \
54+
"idna>=2.0.0" "cryptography==2.2.2" boto psutil postfix-mta-sts-resolver b2sdk
5555

5656
# CONFIGURATION
5757

‎setup/system.sh

+3
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ hide_output add-apt-repository -y universe
9393
# Install the certbot PPA.
9494
hide_output add-apt-repository -y ppa:certbot/certbot
9595

96+
# Install the duplicity PPA.
97+
hide_output add-apt-repository -y ppa:duplicity-team/duplicity-release-git
98+
9699
# ### Update Packages
97100

98101
# Update system packages to make sure we have the latest upstream versions

0 commit comments

Comments
 (0)
Please sign in to comment.