
Automate iptables/nftables Backup and Restore
Before you run this
This guide sets up two things: a small script that dumps your host's live packet-filter ruleset to a timestamped, versioned file, and a scheduled systemd timer to run it. It also shows the standard restore path. The backup part is read-only and safe. The restore part is not — reloading a ruleset replaces your firewall's entire running state in one transaction, and a bad ruleset can drop your SSH session and cut the host off the network instantly.
- Privileges: Reading and writing the ruleset requires root. Run the backup script as root (via
sudoor a root cron/systemd context). Restoring also requires root. - Test first: Read the script before you run it. Try the whole cycle — back up, deliberately change a rule, restore — on a test VM or a non-production box where you have console access, before you trust it on anything live. Do not paste a restore command onto a remote production host you can only reach over SSH without a fallback.
- This changes live firewall state on restore:
nft -fwith aflush ruleset(oriptables-restore) atomically wipes the current tables and loads the file. If the file is wrong or incomplete, you can lock yourself out. Treat every restore as a change window. - Keep an out-of-band way in: before restoring on a remote machine, have console/KVM/serial access open, or run the restore behind a timed auto-revert (shown at the end) so a lockout undoes itself. The clean rollback is simply to reload a known-good backup file — which is exactly what these backups are for.
Assumed environment: Debian 12 or Ubuntu 22.04, using nftables as the active firewall (the default nft framework), managed as root, with systemd. If you still run legacy iptables, I cover that path separately below. Commands are for the nft and iptables-save/iptables-restore tools shipped by these distributions.
Which framework am I actually running?
Check before you script anything:
# What does nft currently hold?
sudo nft list ruleset | head
# Is the iptables command backed by nft or legacy?
sudo iptables -V # prints "(nf_tables)" or "(legacy)"
On a current Debian/Ubuntu box the answer is almost always nftables. If nft list ruleset returns your real rules, use the nftables path. If your rules only appear under iptables -S and iptables -V says (legacy), use the iptables path further down.
The backup script (nftables)
nft list ruleset prints the complete active ruleset in a form that nft -f can reload. The one thing worth adding is a flush ruleset line at the top of the saved file, so reloading it later is a clean atomic replace rather than an "already exists" error.
Save this as /usr/local/sbin/nft-backup.sh:
#!/usr/bin/env bash
# Dump the live nftables ruleset to a timestamped, reloadable file.
# Read-only: it does not change the firewall.
set -euo pipefail
BACKUP_DIR="/var/backups/nftables" # change to taste
KEEP=30 # how many backups to retain
STAMP="$(date +%Y%m%d-%H%M%S)"
OUT="${BACKUP_DIR}/ruleset-${STAMP}.nft"
mkdir -p "$BACKUP_DIR"
# 'flush ruleset' first makes the file a clean, atomic restore.
{
echo "#!/usr/sbin/nft -f"
echo "flush ruleset"
nft list ruleset
} > "$OUT"
chmod 600 "$OUT" # rules can reveal your network layout
# Keep only the newest $KEEP files, delete older ones.
ls -1t "${BACKUP_DIR}"/ruleset-*.nft 2>/dev/null \
| tail -n +$((KEEP + 1)) \
| xargs -r rm -f
echo "Wrote $OUT"
Make it executable and run it once by hand:
sudo chmod 750 /usr/local/sbin/nft-backup.sh
sudo /usr/local/sbin/nft-backup.sh
You should get a file like /var/backups/nftables/ruleset-20240115-030000.nft. Open it and confirm it begins with flush ruleset and contains your tables and chains.
The rotation here is deliberately simple: keep the newest KEEP files, delete the rest. If you already run a real backup system, point it at /var/backups/nftables and drop the retention step.
Schedule it with a systemd timer
I prefer a systemd timer over cron here because you get status and logs from systemctl/journalctl. Two unit files.
/etc/systemd/system/nft-backup.service:
[Unit]
Description=Back up the live nftables ruleset
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/nft-backup.sh
/etc/systemd/system/nft-backup.timer:
[Unit]
Description=Daily nftables ruleset backup
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
Enable and start the timer:
sudo systemctl daemon-reload
sudo systemctl enable --now nft-backup.timer
# Confirm it is scheduled and see the next run time
systemctl list-timers nft-backup.timer
Persistent=true means a missed run (box was off) fires once at next boot.
Restoring an nftables backup
Because the file starts with flush ruleset, restoring is a single atomic reload:
# Dry-run parse only: checks syntax, does NOT apply anything
sudo nft -c -f /var/backups/nftables/ruleset-20240115-030000.nft
# Apply it (this replaces the entire live ruleset)
sudo nft -f /var/backups/nftables/ruleset-20240115-030000.nft
Always run the -c check first. -c parses and validates without touching the running firewall.
To make the restore survive a reboot on Debian/Ubuntu, the active ruleset is loaded at boot from /etc/nftables.conf by the nftables.service. To persist a restored state, copy your good file into place and reload:
sudo cp /var/backups/nftables/ruleset-20240115-030000.nft /etc/nftables.conf
sudo systemctl enable nftables.service
sudo systemctl restart nftables.service
Check that /etc/nftables.conf starts with the #!/usr/sbin/nft -f shebang line and flush ruleset — the file the script writes already does.
Restore safely on a remote host (timed auto-revert)
If you must restore over SSH and you're worried a bad file will lock you out, stage a known-good backup to reload automatically after a few minutes, apply your change, and cancel the revert only once you're still connected:
# Schedule a rollback to a KNOWN-GOOD file in 5 minutes
echo "nft -f /var/backups/nftables/ruleset-KNOWN-GOOD.nft" | sudo at now + 5 minutes
# Now apply the ruleset you actually want
sudo nft -f /var/backups/nftables/ruleset-NEW.nft
# Still connected and happy? Cancel the pending rollback:
sudo atq # find the job number
sudo atrm <job-number> # remove it
Replace ruleset-KNOWN-GOOD.nft and ruleset-NEW.nft with your real filenames, and <job-number> with the ID from atq. This needs the at package installed. If you get locked out, do nothing and the rollback restores the working ruleset on its own.
The legacy iptables path
If iptables -V reports (legacy), use the matching tools. Back up both the IPv4 and IPv6 tables:
sudo iptables-save > /var/backups/nftables/iptables-$(date +%Y%m%d-%H%M%S).rules
sudo ip6tables-save > /var/backups/nftables/ip6tables-$(date +%Y%m%d-%H%M%S).rules
Restore is the mirror image:
sudo iptables-restore < /var/backups/nftables/iptables-20240115-030000.rules
sudo ip6tables-restore < /var/backups/nftables/ip6tables-20240115-030000.rules
To persist legacy rules across reboots, the standard Debian/Ubuntu tool is the iptables-persistent package (which installs netfilter-persistent); it stores rules in /etc/iptables/rules.v4 and rules.v6. See its package documentation for the netfilter-persistent save workflow rather than editing those files by hand.
Verify it worked
- Backup ran:
systemctl status nft-backup.serviceandjournalctl -u nft-backup.serviceshow a cleanoneshotexit; a new dated file exists in/var/backups/nftables. - Backup is valid:
sudo nft -c -f <file>parses without error. - Restore matched: after a restore, compare live state to the file.
sudo nft list rulesetshould match the tables in the backup. A quick check isdiff <(sudo nft list ruleset) <(tail -n +3 <file>)— small ordering differences are normal, missing tables are not. - Persistence: after
systemctl restart nftables.service, confirm the rules you expect are still present withsudo nft list ruleset.
The undo for any restore is simply reloading an earlier good file with sudo nft -f, which is precisely why the scheduled backups are worth having before you ever need them.
For exact tool syntax, see the nft(8) man page and the netfilter project's nftables wiki, and the iptables-save/iptables-restore man pages for the legacy path.
Runs enterprise networks and security for a living, and writes Shore Up to turn two decades of hands-on Linux, Windows and mail-server work into guides you can actually use.
More about the author →Was this article helpful?
Tap a star — no sign-in needed.
Be the first to rate this article.
