mirror of
				https://github.com/mail-in-a-box/mailinabox.git
				synced 2025-11-03 19:30:54 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			215 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<style>
 | 
						|
#backup-status th { text-align: center; }
 | 
						|
#backup-status tr.full-backup td { font-weight: bold; }
 | 
						|
</style>
 | 
						|
 | 
						|
<h2>Backup Status</h2>
 | 
						|
 | 
						|
<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>
 | 
						|
 | 
						|
<h3>Configuration</h3>
 | 
						|
 | 
						|
<form class="form-horizontal" role="form" onsubmit="set_custom_backup(); return false;">
 | 
						|
  <div class="form-group">
 | 
						|
    <label for="backup-target-type" class="col-sm-2 control-label">Backup to:</label>
 | 
						|
    <div class="col-sm-2">
 | 
						|
      <select class="form-control" rows="1" id="backup-target-type" onchange="toggle_form()">
 | 
						|
        <option value="off">Nowhere (Disable Backups)</option>
 | 
						|
        <option value="local">{{hostname}}</option>
 | 
						|
        <option value="s3">Amazon S3</option>
 | 
						|
      </select>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
  <div class="form-group backup-target-local">
 | 
						|
    <div class="col-sm-10 col-sm-offset-2">
 | 
						|
      <p>Backups are stored on this machine’s own hard disk. You are responsible for periodically using SFTP (FTP over SSH) to copy the backup files from <tt id="backup-location"></tt> to a safe location. These files are encrypted, so they are safe to store anywhere.</p>
 | 
						|
      <p>Separately 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.</p>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
  <div class="form-group backup-target-s3">
 | 
						|
    <div class="col-sm-10 col-sm-offset-2">
 | 
						|
      <p>Backups are stored in an Amazon Web Services S3 bucket. You must have an AWS 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 Amazon S3 bucket.</p>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
  <div class="form-group backup-target-local backup-target-s3">
 | 
						|
    <label for="min-age" class="col-sm-2 control-label">How many days should backups be kept?</label>
 | 
						|
    <div class="col-sm-8">
 | 
						|
      <input type="number" class="form-control" rows="1" id="min-age">
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
  <div class="form-group backup-target-s3">
 | 
						|
    <label for="backup-target-s3-host" class="col-sm-2 control-label">S3 Region</label>
 | 
						|
    <div class="col-sm-8">
 | 
						|
      <select class="form-control" rows="1" id="backup-target-s3-host">
 | 
						|
        {% for name, host in backup_s3_hosts %}
 | 
						|
          <option value="{{host}}">{{name}}</option>
 | 
						|
        {% endfor %}
 | 
						|
      </select>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
  <div class="form-group backup-target-s3">
 | 
						|
    <label for="backup-target-s3-path" class="col-sm-2 control-label">S3 Path</label>
 | 
						|
    <div class="col-sm-8">
 | 
						|
      <input type="text" placeholder="your-bucket-name/backup-directory" class="form-control" rows="1" id="backup-target-s3-path">
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
  <div class="form-group backup-target-s3">
 | 
						|
    <label for="backup-target-user" class="col-sm-2 control-label">S3 Access Key</label>
 | 
						|
    <div class="col-sm-8">
 | 
						|
      <input type="text" class="form-control" rows="1" id="backup-target-user">
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
  <div class="form-group backup-target-s3">
 | 
						|
    <label for="backup-target-pass" class="col-sm-2 control-label">S3 Secret Access Key</label>
 | 
						|
    <div class="col-sm-8">
 | 
						|
      <input type="text" class="form-control" rows="1" id="backup-target-pass">
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
  <div class="form-group">
 | 
						|
    <div class="col-sm-offset-2 col-sm-10">
 | 
						|
      <button id="set-s3-backup-button" type="submit" class="btn btn-primary">Save</button>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
</form>
 | 
						|
 | 
						|
<h3>Available Backups</h3>
 | 
						|
 | 
						|
<p>The backup location currently contains the backups listed below. The total size of the backups is currently <span id="backup-total-size"></span>.</p>
 | 
						|
 | 
						|
<table id="backup-status" class="table" style="width: auto">
 | 
						|
  <thead>
 | 
						|
    <th colspan="2">When</th>
 | 
						|
    <th>Type</th>
 | 
						|
    <th>Size</th>
 | 
						|
    <th>Deleted in...</th>
 | 
						|
  </thead>
 | 
						|
  <tbody>
 | 
						|
  </tbody>
 | 
						|
</table>
 | 
						|
<script>
 | 
						|
 | 
						|
function toggle_form() {
 | 
						|
  var target_type = $("#backup-target-type").val();
 | 
						|
  $(".backup-target-local, .backup-target-s3").hide();
 | 
						|
  $(".backup-target-" + target_type).show();
 | 
						|
}
 | 
						|
 | 
						|
function nice_size(bytes) {
 | 
						|
  var powers = ['bytes', 'KB', 'MB', 'GB', 'TB'];
 | 
						|
  while (true) {
 | 
						|
    if (powers.length == 1) break;
 | 
						|
    if (bytes < 1000) break;
 | 
						|
    bytes /= 1024;
 | 
						|
    powers.shift();
 | 
						|
  }
 | 
						|
  // round to have three significant figures but at most one decimal place
 | 
						|
  if (bytes >= 100)
 | 
						|
    bytes = Math.round(bytes)
 | 
						|
  else
 | 
						|
    bytes = Math.round(bytes*10)/10;
 | 
						|
  return bytes + " " + powers[0];
 | 
						|
}
 | 
						|
 | 
						|
function show_system_backup() {
 | 
						|
  show_custom_backup()
 | 
						|
  
 | 
						|
  $('#backup-status tbody').html("<tr><td colspan='2' class='text-muted'>Loading...</td></tr>")
 | 
						|
  api(
 | 
						|
    "/system/backup/status",
 | 
						|
    "GET",
 | 
						|
    { },
 | 
						|
    function(r) {
 | 
						|
      $('#backup-status tbody').html("");
 | 
						|
      var total_disk_size = 0;
 | 
						|
 | 
						|
      if (typeof r.backups == "undefined") {
 | 
						|
        var tr = $('<tr><td colspan="3">Backups are turned off.</td></tr>');
 | 
						|
        $('#backup-status tbody').append(tr);
 | 
						|
        return;
 | 
						|
      } else if (r.backups.length == 0) {
 | 
						|
        var tr = $('<tr><td colspan="3">No backups have been made yet.</td></tr>');
 | 
						|
        $('#backup-status tbody').append(tr);
 | 
						|
      }
 | 
						|
 | 
						|
      for (var i = 0; i < r.backups.length; i++) {
 | 
						|
        var b = r.backups[i];
 | 
						|
        var tr = $('<tr/>');
 | 
						|
        if (b.full) tr.addClass("full-backup");
 | 
						|
        tr.append( $('<td/>').text(b.date_str + " " + r.tz) );
 | 
						|
        tr.append( $('<td/>').text(b.date_delta + " ago") );
 | 
						|
        tr.append( $('<td/>').text(b.full ? "full" : "increment") );
 | 
						|
        tr.append( $('<td style="text-align: right"/>').text( nice_size(b.size)) );
 | 
						|
        if (b.deleted_in)
 | 
						|
          tr.append( $('<td/>').text(b.deleted_in) );
 | 
						|
        else
 | 
						|
          tr.append( $('<td class="text-muted">unknown</td>') );
 | 
						|
        $('#backup-status tbody').append(tr);
 | 
						|
 | 
						|
        total_disk_size += b.size;
 | 
						|
      }
 | 
						|
 | 
						|
      $('#backup-total-size').text(nice_size(total_disk_size));
 | 
						|
    })
 | 
						|
}
 | 
						|
 | 
						|
function show_custom_backup() {
 | 
						|
    $(".backup-target-local, .backup-target-s3").hide();
 | 
						|
    api(
 | 
						|
      "/system/backup/config",
 | 
						|
      "GET",
 | 
						|
      { },
 | 
						|
      function(r) {
 | 
						|
        if (r.target == "file://" + r.file_target_directory) {
 | 
						|
          $("#backup-target-type").val("local");
 | 
						|
        } else if (r.target == "off") {
 | 
						|
          $("#backup-target-type").val("off");
 | 
						|
        } else if (r.target.substring(0, 5) == "s3://") {
 | 
						|
          $("#backup-target-type").val("s3");
 | 
						|
	  var hostpath = r.target.substring(5).split('/');
 | 
						|
          var host = hostpath.shift();
 | 
						|
          $("#backup-target-s3-host").val(host);
 | 
						|
          $("#backup-target-s3-path").val(hostpath.join('/'));
 | 
						|
        }
 | 
						|
        $("#backup-target-user").val(r.target_user);
 | 
						|
        $("#backup-target-pass").val(r.target_pass);
 | 
						|
        $("#min-age").val(r.min_age_in_days);
 | 
						|
        $('#backup-location').text(r.file_target_directory);
 | 
						|
        $('.backup-encpassword-file').text(r.enc_pw_file);
 | 
						|
        toggle_form()
 | 
						|
      })
 | 
						|
}
 | 
						|
 | 
						|
function set_custom_backup() {
 | 
						|
  var target_type = $("#backup-target-type").val();
 | 
						|
  var target_user = $("#backup-target-user").val();
 | 
						|
  var target_pass = $("#backup-target-pass").val();
 | 
						|
  
 | 
						|
  var target;
 | 
						|
  if (target_type == "local" || target_type == "off")
 | 
						|
    target = target_type;
 | 
						|
  else if (target_type == "s3")
 | 
						|
    target = "s3://" + $("#backup-target-s3-host").val() + "/" + $("#backup-target-s3-path").val();
 | 
						|
 | 
						|
  var min_age = $("#min-age").val();
 | 
						|
  api(
 | 
						|
    "/system/backup/config",
 | 
						|
    "POST",
 | 
						|
    {
 | 
						|
      target: target,
 | 
						|
      target_user: target_user,
 | 
						|
      target_pass: target_pass,
 | 
						|
      min_age: min_age
 | 
						|
    },
 | 
						|
    function(r) {
 | 
						|
      // use .text() --- it's a text response, not html
 | 
						|
      show_modal_error("Backup configuration", $("<p/>").text(r), function() { if (r == "OK") show_system_backup(); }); // refresh after modal on success
 | 
						|
    },
 | 
						|
    function(r) {
 | 
						|
      // use .text() --- it's a text response, not html
 | 
						|
      show_modal_error("Backup configuration", $("<p/>").text(r));
 | 
						|
    });
 | 
						|
  return false;
 | 
						|
}
 | 
						|
</script>
 |