Commit 2e6c4103 authored by Leo Koppelkamm's avatar Leo Koppelkamm

Make backups more configurable

Backup location and maximum age can now be configured in the admin panel.
For now only S3 is supported, but adding other duplicity supported backends should be straightforward.
parent 0293e043
This diff is collapsed.
...@@ -402,6 +402,24 @@ def backup_status(): ...@@ -402,6 +402,24 @@ def backup_status():
from backup import backup_status from backup import backup_status
return json_response(backup_status(env)) return json_response(backup_status(env))
@app.route('/system/backup/get-custom')
@authorized_personnel_only
def backup_get_custom():
from backup import get_backup_config
return json_response(get_backup_config())
@app.route('/system/backup/set-custom', methods=["POST"])
@authorized_personnel_only
def backup_set_custom():
from backup import backup_set_custom
return json_response(backup_set_custom(
request.form.get('target', ''),
request.form.get('target_user', ''),
request.form.get('target_pass', ''),
request.form.get('target_type', ''),
request.form.get('max_age', '')
))
# MUNIN # MUNIN
@app.route('/munin/') @app.route('/munin/')
...@@ -432,4 +450,3 @@ if __name__ == '__main__': ...@@ -432,4 +450,3 @@ if __name__ == '__main__':
# Start the application server. Listens on 127.0.0.1 (IPv4 only). # Start the application server. Listens on 127.0.0.1 (IPv4 only).
app.run(port=10222) app.run(port=10222)
...@@ -7,12 +7,53 @@ ...@@ -7,12 +7,53 @@
<h3>Copying Backup Files</h3> <h3>Copying Backup Files</h3>
<p>The box makes an incremental backup each night. The backup is stored on the machine itself. You are responsible for copying the backup files off of the machine.</p> <p>The box makes an incremental backup each night. By default the backup is stored on the machine itself, but you can also have it stored on Amazon S3</p>
<p>Many cloud providers make this easy by allowing you to take snapshots of the machine's disk.</p>
<p>You can also use SFTP (FTP over SSH) to copy files from <tt id="backup-location"></tt>. These files are encrypted, so they are safe to store anywhere. Copy the encryption password from <tt id="backup-encpassword-file"></tt> also but keep it in a safe location.</p> <p>You can also use SFTP (FTP over SSH) to copy files from <tt id="backup-location"></tt>. These files are encrypted, so they are safe to store anywhere. Copy the encryption password from <tt id="backup-encpassword-file"></tt> also but keep it in a safe location.</p>
<h3>Backup Configuration</h3>
<form class="form-horizontal" role="form" onsubmit="set_custom_backup(); return false;">
<div class="form-group">
<label for="target" class="col-sm-2 control-label">Backup target</label>
<div class="col-sm-2">
<select class="form-control" rows="1" id="target-type" onchange="toggle_form()">
<option value="file">Store locally</option>
<option value="s3">Amazon S3</option>
</select>
</div>
</div>
<div class="form-group">
<label for="target" class="col-sm-2 control-label">Maximum time to keep old backups (in days)</label>
<div class="col-sm-8">
<input type="number" class="form-control" rows="1" id="max-age"></input>
</div>
</div>
<div class="form-group form-advanced">
<label for="target" class="col-sm-2 control-label">S3 URL</label>
<div class="col-sm-8">
<textarea class="form-control" rows="1" id="target"></textarea>
</div>
</div>
<div class="form-group form-advanced">
<label for="target-user" class="col-sm-2 control-label">S3&nbsp;Key</label>
<div class="col-sm-8">
<textarea class="form-control" rows="1" id="target-user"></textarea>
</div>
</div>
<div class="form-group form-advanced">
<label for="target-pass" class="col-sm-2 control-label">S3&nbsp;Secret</label>
<div class="col-sm-8">
<textarea class="form-control" rows="1" id="target-pass"></textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-11">
<button id="set-s3-backup-button" type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</form>
<h3>Current Backups</h3> <h3>Current Backups</h3>
<p>The backup directory currently contains the backups listed below. The total size on disk of the backups is currently <span id="backup-total-size"></span>.</p> <p>The backup directory currently contains the backups listed below. The total size on disk of the backups is currently <span id="backup-total-size"></span>.</p>
...@@ -27,8 +68,17 @@ ...@@ -27,8 +68,17 @@
<tbody> <tbody>
</tbody> </tbody>
</table> </table>
<script> <script>
function toggle_form() {
var target_type = $("#target-type").val();
if (target_type == 'file') {
$(".form-advanced").hide();
} else {
$(".form-advanced").show();
}
}
function nice_size(bytes) { function nice_size(bytes) {
var powers = ['bytes', 'KB', 'MB', 'GB', 'TB']; var powers = ['bytes', 'KB', 'MB', 'GB', 'TB'];
while (true) { while (true) {
...@@ -46,6 +96,8 @@ function nice_size(bytes) { ...@@ -46,6 +96,8 @@ function nice_size(bytes) {
} }
function show_system_backup() { function show_system_backup() {
show_custom_backup()
$('#backup-status tbody').html("<tr><td colspan='2' class='text-muted'>Loading...</td></tr>") $('#backup-status tbody').html("<tr><td colspan='2' class='text-muted'>Loading...</td></tr>")
api( api(
"/system/backup/status", "/system/backup/status",
...@@ -83,4 +135,45 @@ function show_system_backup() { ...@@ -83,4 +135,45 @@ function show_system_backup() {
$('#backup-total-size').text(nice_size(total_disk_size)); $('#backup-total-size').text(nice_size(total_disk_size));
}) })
} }
function show_custom_backup() {
api(
"/system/backup/get-custom",
"GET",
{ },
function(r) {
$("#target").val(r.target);
$("#target-type").val(r.target_type);
$("#target-user").val(r.target_user);
$("#target-pass").val(r.target_pass);
$("#max-age").val(r.max_age_in_days);
toggle_form()
})
}
function set_custom_backup() {
var target = $("#target").val();
var target_type = $("#target-type").val();
var target_user = $("#target-user").val();
var target_pass = $("#target-pass").val();
var max_age = $("#max-age").val();
api(
"/system/backup/set-custom",
"POST",
{
target: target,
target_type: target_type,
target_user: target_user,
target_pass: target_pass,
max_age: max_age
},
function(r) {
// Responses are multiple lines of pre-formatted text.
show_modal_error("Backup configuration", $("<pre/>").text(r));
},
function(r) {
show_modal_error("Backup configuration (error)", r);
});
return false;
}
</script> </script>
...@@ -4,8 +4,9 @@ source setup/functions.sh ...@@ -4,8 +4,9 @@ source setup/functions.sh
# build-essential libssl-dev libffi-dev python3-dev: Required to pip install cryptography. # build-essential libssl-dev libffi-dev python3-dev: Required to pip install cryptography.
apt_install python3-flask links duplicity libyaml-dev python3-dnspython python3-dateutil \ apt_install python3-flask links duplicity libyaml-dev python3-dnspython python3-dateutil \
build-essential libssl-dev libffi-dev python3-dev build-essential libssl-dev libffi-dev python3-dev python-pip
hide_output pip3 install --upgrade rtyaml email_validator idna cryptography hide_output pip3 install --upgrade rtyaml email_validator idna cryptography boto
hide_output pip install --upgrade boto
# email_validator is repeated in setup/questions.sh # email_validator is repeated in setup/questions.sh
# Create a backup directory and a random key for encrypting backups. # Create a backup directory and a random key for encrypting backups.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment