Rules you add with the iptables command take effect at once, but they live only in memory. Reboot the server and they are gone. This guide shows you how to save your rules to a file and load them at boot on both Debian-based and RHEL-based systems, then confirm they come back.
Before you start
- A Linux VPS running Ubuntu 22.04/24.04, Debian 12, or AlmaLinux/Rocky Linux 8 or 9.
- A working iptables ruleset that you have already tested. If you are starting from scratch, read iptables basics first.
- Root access or a user with
sudo. - No other firewall manager active. UFW and firewalld load their own rules at boot and will clash with saved iptables rules.
Warning: Whatever you save is exactly what loads after the next reboot. If the saved rules block SSH, you will not be able to log in over SSH after a restart. Confirm SSH works with the live rules before saving. If it goes wrong, the browser console in your VPS provider's control panel still works.
Check the live rules first
Print the current rules in save format:
sudo iptables -S
sudo ip6tables -SMake sure you see an ACCEPT rule for your SSH port, for example -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT, before any DROP policy. Open a second SSH session to prove it works.
Ubuntu and Debian: netfilter-persistent
The iptables-persistent package installs a small service, netfilter-persistent, that restores saved rules at boot.
- Install it:
sudo apt update
sudo apt install iptables-persistentThe installer asks whether to save the current IPv4 and IPv6 rules. Choose Yes for both if your live rules are correct.
- Save the rules any time you change them:
sudo netfilter-persistent saveThis writes two files:
/etc/iptables/rules.v4/etc/iptables/rules.v6
- Make sure the service starts at boot:
sudo systemctl enable netfilter-persistentTo reload the saved files without rebooting:
sudo netfilter-persistent reloadNote: On Ubuntu, installing iptables-persistent removes UFW if it is installed, because the two conflict. That is expected.
AlmaLinux and Rocky Linux: iptables-services
On RHEL-based systems, firewalld is the default. To manage iptables directly, swap firewalld for the iptables-services package.
- Install the package:
sudo dnf install iptables-services- Stop and disable firewalld so it does not overwrite your rules:
sudo systemctl disable --now firewalldDisabling firewalld removes its rules. Load your own ruleset straight after, in the same session.
- Enable the iptables services:
sudo systemctl enable --now iptables
sudo systemctl enable --now ip6tablesThe iptables service loads /etc/sysconfig/iptables at start. The package ships a default file that allows SSH and rejects most other traffic.
- Add your own rules, test them, then save:
sudo service iptables save
sudo service ip6tables saveIf the service... save form is not available, write the files directly:
sudo sh -c 'iptables-save > /etc/sysconfig/iptables'
sudo sh -c 'ip6tables-save > /etc/sysconfig/ip6tables'Tip: Most RHEL-family users are better served by firewalld. Switch to plain iptables only if you have an existing ruleset or a tool that needs it. See Set up firewalld on AlmaLinux and Rocky Linux.
Save and restore by hand
On any distribution you can export and import rules with two commands. This is useful for backups before a big change:
sudo iptables-save > ~/fw-$(date +%F).rules
sudo iptables-restore < ~/fw-2026-11-09.rulesThe file is plain text. You can edit it, then test the syntax without applying it:
sudo iptables-restore --test < /etc/iptables/rules.v4No output means the file parses correctly.
Check it works
- Note the number of rules now:
sudo iptables -S | wc -l- Reboot the server from the shell or your VPS provider's power controls:
sudo reboot- Log back in over SSH and count again. The number should match.
- Confirm the loader service ran cleanly:
systemctl status netfilter-persistent # Debian/Ubuntu
systemctl status iptables # AlmaLinux/RockyLook for active (exited) with no errors.
Troubleshooting
- Rules are empty after reboot: the save step was skipped, or the service is not enabled. Run the save command again and
systemctl enablethe service. - Old rules come back after you changed them: you changed the live rules but did not save. Saving is a separate step every time.
- Service fails with a line number error: the rules file has a syntax mistake. Test it with
iptables-restore --testand fix the line it names. - Docker containers lose network access after reboot: Docker adds its own chains at start. Avoid flushing everything in your saved file, and restart Docker after the firewall loads, or keep custom rules in the
DOCKER-USERchain. - Locked out after reboot: use the browser console, run
sudo iptables -P INPUT ACCEPT, fix the SSH rule and save again.
Next steps
- Add a safety net before risky changes: Test firewall changes safely with an automatic rollback.
- If you ever lose access: Locked out by your firewall? How to get back in.
- Plan a move to the modern tool: Migrate iptables rules to nftables.
