System Backup
Jan 21st 2026
Security Hub allows you to back up the entire system configuration, capturing all settings, 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.
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:
- In “Backups and Reboot”, choose the “Setup remote repository” option
- 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()