{"id":895,"date":"2026-08-15T23:26:07","date_gmt":"2026-08-15T23:26:07","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=895"},"modified":"2026-08-15T23:26:07","modified_gmt":"2026-08-15T23:26:07","slug":"nftables-firewall-setup-linux-vps","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/","title":{"rendered":"Setting Up nftables on a Linux VPS: A Practical Firewall Guide"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">nftables is the modern replacement for iptables on Linux, and since Debian 10, RHEL 8, and their derivatives, it is the default firewall framework shipped with the kernel. If your VPS still runs an iptables ruleset from 2015, you are maintaining two parallel rule sets \u2014 legacy iptables and the nftables backend that now powers it \u2014 without getting any of nftables&#8217; benefits. This guide walks through a practical nftables setup for a Linux VPS: the syntax you need, a working ruleset you can adapt, and the mistakes that lock people out of their own servers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">nftables vs. iptables: What Actually Changed<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The headline difference is one tool instead of four: where iptables needed separate binaries for IPv4, IPv6, ARP, and bridging, nftables handles all of them through the single <code>nft<\/code> command using an <code>inet<\/code> family table that covers both IP versions. Rules are evaluated more efficiently, and the whole ruleset is replaced atomically \u2014 there is no window where a partially applied chain leaves you exposed.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Aspect<\/th><th>iptables<\/th><th>nftables<\/th><\/tr><\/thead><tbody><tr><td>Binaries<\/td><td>iptables, ip6tables, arptables, ebtables<\/td><td>Single <code>nft<\/code> binary<\/td><\/tr><tr><td>IPv4 + IPv6<\/td><td>Separate rulesets, easy to forget one<\/td><td>One <code>inet<\/code> table covers both<\/td><\/tr><tr><td>Rule updates<\/td><td>Per-rule, with partial-apply risk<\/td><td>Atomic ruleset replacement<\/td><\/tr><tr><td>Sets and maps<\/td><td>Require separate ipset tool<\/td><td>Built-in anonymous and named sets<\/td><\/tr><tr><td>Persistence<\/td><td>iptables-save\/restore scripts<\/td><td><code>nft -f \/etc\/nftables.conf<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">A Minimal Working Ruleset<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Install nftables and enable it on boot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update &amp;&amp; sudo apt install -y nftables   # Debian\/Ubuntu\nsudo systemctl enable --now nftables<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then write your ruleset to <code>\/etc\/nftables.conf<\/code>. A sane default for a web server with SSH management looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/usr\/sbin\/nft -f\nflush ruleset\n\ntable inet filter {\n    chain input {\n        type filter hook input priority filter; policy drop\n        ct state established,related accept\n        iif \"lo\" accept\n        ip protocol icmp icmp type echo-request accept\n        tcp dport 22 accept\n        tcp dport 80 accept\n        tcp dport 443 accept\n        counter drop\n    }\n    chain forward {\n        type filter hook forward priority filter; policy drop\n    }\n    chain output {\n        type filter hook output priority filter; policy accept\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Apply it with <code>sudo nft -f \/etc\/nftables.conf<\/code> and verify with <code>sudo nft list ruleset<\/code>. The <code>ct state established,related accept<\/code> line is what lets return traffic in \u2014 omit it and your server can reach out but never receive replies, which looks exactly like a broken network.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common Mistakes (and How to Avoid Them)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Locking yourself out of SSH.<\/strong> If you are editing remotely, apply rules from a tmux session and keep a second root shell open. Better: test with <code>nft -c -f \/etc\/nftables.conf<\/code> (check-only) before applying, and make sure your SSH port rule comes before any drop policy.<\/li>\n<li><strong>Forgetting the loopback rule.<\/strong> Without <code>iif \"lo\" accept<\/code>, local services talking to each other via 127.0.0.1 get blocked and your database or cache mysteriously &#8220;stops working&#8221; after a reboot.<\/li>\n<li><strong>Using iptables syntax inside nftables.<\/strong> <code>-A INPUT -p tcp --dport 22 -j ACCEPT<\/code> is not valid nft syntax. The nft equivalents are <code>tcp dport 22 accept<\/code> \u2014 no dashes, no <code>-j<\/code>.<\/li>\n<li><strong>Not persisting the ruleset.<\/strong> Rules applied with <code>nft<\/code> at the shell vanish on reboot unless you save them with <code>nft list ruleset &gt; \/etc\/nftables.conf<\/code> (or edit the file directly and enable the service).<\/li>\n<li><strong>Blocking ICMP entirely.<\/strong> Dropping all ICMP breaks path MTU discovery and makes IPv6 connections hang. Allow echo-request and let the rest through.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Going Further: Sets and Rate Limiting<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Named sets let you manage allowlists without editing rules. Define <code>set admin_ips { type ipv4_addr; elements = { 203.0.113.10, 198.51.100.20 } }<\/code> and then reference <code>ip saddr @admin_ips accept<\/code> in the input chain. For brute-force protection, add a dynamic set that drops sources with more than four new SSH connections per minute:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>set ssh_bruteforce {\n    type ipv4_addr\n    flags dynamic\n    timeout 10m\n}\nchain input {\n    tcp dport 22 ct state new add @ssh_bruteforce { ip saddr limit rate over 4\/minute } drop\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Pair this with key-based authentication and fail2ban for defense in depth. Log dropped packets with a rule like <code>log prefix \"nft-drop: \" counter drop<\/code> at the end of the input chain so you can see what is being blocked in <code>journalctl -u nftables<\/code> or the kernel log.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing and Rolling Back Safely<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before you apply anything remotely, validate the file: <code>sudo nft -c -f \/etc\/nftables.conf<\/code> parses the ruleset without loading it and reports syntax errors on the exact line. If a ruleset does break connectivity, do not panic \u2014 reboot the VPS from the provider panel, and because you enabled the <code>nftables<\/code> service, the kernel reloads the last <em>saved<\/em> file. That is why the golden rule is: edit <code>\/etc\/nftables.conf<\/code> first, validate, then apply from that same file. If you instead type rules interactively at the shell, save them immediately with <code>sudo nft list ruleset &gt; \/etc\/nftables.conf<\/code> so a reboot restores what you tested.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">nftables is well worth the syntax shift: one tool, atomic updates, and better performance on the same kernel. If you are coming from iptables, the <a href=\"https:\/\/virtualserversvps.com\/#features\">VPS feature comparison at virtualserversvps.com<\/a> includes notes on which providers give you full kernel-level control for custom firewalls, and the <a href=\"https:\/\/virtualserversvps.com\/#providers\">provider list<\/a> helps you find a host with a modern kernel and up-to-date base images where nftables is the default.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ready to harden your server? <a href=\"https:\/\/cloudways.com\/en\/?id=2010927&amp;data1=virtualserversvps\" rel=\"noreferrer noopener sponsored\" target=\"_blank\">Deploy a Linux VPS with a modern kernel and put this ruleset to work<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>nftables is the modern replacement for iptables on Linux, and since Debian 10, RHEL 8, and their derivatives, it is the default firewall framework shipped with the kernel. If your&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":0,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-895","post","type-post","status-publish","format-standard","hentry","category-security-compliance"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Setting Up nftables on a Linux VPS: A Practical Firewall Guide - Virtual Servers VPS Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Setting Up nftables on a Linux VPS: A Practical Firewall Guide\" \/>\n<meta property=\"og:description\" content=\"Setting Up nftables on a Linux VPS: A Practical Firewall Guide\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-15T23:26:07+00:00\" \/>\n<meta name=\"author\" content=\"Virtual-Servers-Vps-Editor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Virtual-Servers-Vps-Editor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/\",\"name\":\"Setting Up nftables on a Linux VPS: A Practical Firewall Guide - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-08-15T23:26:07+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Setting Up nftables on a Linux VPS: A Practical Firewall Guide\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/\",\"name\":\"Virtual Servers VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\",\"name\":\"Virtual-Servers-Vps-Editor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"caption\":\"Virtual-Servers-Vps-Editor\"},\"sameAs\":[\"https:\/\/virtualserversvps.com\/blog\"],\"url\":\"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Setting Up nftables on a Linux VPS: A Practical Firewall Guide - Virtual Servers VPS Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/","og_locale":"en_US","og_type":"article","og_title":"Setting Up nftables on a Linux VPS: A Practical Firewall Guide","og_description":"Setting Up nftables on a Linux VPS: A Practical Firewall Guide","og_url":"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-08-15T23:26:07+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/","url":"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/","name":"Setting Up nftables on a Linux VPS: A Practical Firewall Guide - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-08-15T23:26:07+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/nftables-firewall-setup-linux-vps\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Setting Up nftables on a Linux VPS: A Practical Firewall Guide"}]},{"@type":"WebSite","@id":"https:\/\/virtualserversvps.com\/blog\/#website","url":"https:\/\/virtualserversvps.com\/blog\/","name":"Virtual Servers VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0","name":"Virtual-Servers-Vps-Editor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","caption":"Virtual-Servers-Vps-Editor"},"sameAs":["https:\/\/virtualserversvps.com\/blog"],"url":"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/"}]}},"_links":{"self":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/895","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/comments?post=895"}],"version-history":[{"count":1,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/895\/revisions"}],"predecessor-version":[{"id":897,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/895\/revisions\/897"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=895"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=895"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=895"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}