System Backup

Jan 21st 2026

Security Hub allows you to back up the entire system configuration, capturing all set­tings, rules, and policies in a timestamped archive. These backups serve as a reliable recovery point, enabling you to restore the system to a known, stable state in the event of misconfiguration, failures, or security incidents. With versioned snapshots, you can quickly roll back to a previous configuration minimizing downtime and maintaining operational continuity.

Creating a Local Backup

In the settings menu, the “Backups & Reboot” tab simply creates a local backup file, which is a point in time for recovery, for example to revert a configuration change.

Backup confirmation screen

Creating a Remote Backup

For disaster recovery purposes, it can be useful to save the backups outside of the device. Access Gate offers a simple to set up, yet secure HTTP option to do so: 

  1. In “Backups and Reboot”, choose the “Setup remote repository” option
  2. Enter the address the system can use to save backups, and an encryption password

The server protocol is very simple, and should accept a POST request to store a backup, and a GET request to download one.

As an example, the following Python code demonstrate a minimal server:

from http.server import BaseHTTPRequestHandler, HTTPServer
import os
import urllib.parse
import shutil
import subprocess
import sys

class Handler(BaseHTTPRequestHandler):

    def read_body(self):
        length = self.headers.get("Content-Length")
        transfer_encoding = self.headers.get("Transfer-Encoding", "").lower()

        if length is not None:
            return self.rfile.read(int(length))

        elif "chunked" in transfer_encoding:
            body = b""
            while True:
                line = self.rfile.readline().strip()
                if not line:
                    break
                chunk_size = int(line, 16)
                if chunk_size == 0:
                    break
                chunk = self.rfile.read(chunk_size)
                body += chunk
                self.rfile.readline()
            return body

        else:
            return self.rfile.read()

    def do_POST(self):
        path = urllib.parse.unquote(self.path)
        parts = path.split("/", 1)

        if len(parts) != 2 or not parts[1]:
            self.send_response(400)
            self.end_headers()
            print("Missing filename in URL. Use /<filename>")
            return

        filename = parts[1]
        safe_filename = os.path.basename(filename)

        data = self.read_body()
        with open(safe_filename, "wb") as f:
            f.write(data)
        self.send_response(200)
        self.end_headers()
        print("Uploaded file ", len(data), "bytes")

    def do_GET(self):
        path = urllib.parse.unquote(self.path)
        parts = path.split("/", 1)
        if len(parts) != 2 or not parts[1]:
            self.send_response(400)
            self.end_headers()
            print("Missing filename in URL. Use /<filename>")
            return

        filename = parts[1]
        safe_filename = os.path.basename(filename)

        if safe_filename == "list":
            result = subprocess.run(
              ["sha1sum backup_*"],
               capture_output=True,
               text=True,
               shell=True
            )
            self.send_response(200)
            self.send_header("Content-type", "text/plain")
            self.end_headers()
            copy = result.stdout
            self.wfile.write(result.stdout.encode("utf-8"))
            print(copy)

        else:          
            f = open(safe_filename, 'rb')
            self.send_response(200)
            self.send_header("Content-type", "application/x-binary")
            fs = os.fstat(f.fileno())
            self.send_header("Content-Length", str(fs[6]))
            self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
            self.end_headers()
            shutil.copyfileobj(f, self.wfile)
            f.close()
            print("Downloaded file ", str(fs[6]), "bytes")

        return

if __name__ == "__main__":
    serverAddr = sys.argv[1]
    serverPort = sys.argv[2]
    print("Listening on http://",serverAddr,":",serverPort)
    HTTPServer((serverAddr, int(serverPort)), Handler).serve_forever()