Running a business network today requires more than just a router: a proper firewall is mandatory, especially since remote work, cloud services and internal servers all need to be separated safely. VyOS is an open-source router operating system based on Debian that puts the full Linux netfilter stack (iptables/nftables) behind one consistent command line – a solid replacement or companion for classic all-in-one appliances.
VyOS is not a stripped-down desktop Linux with router features, but a network operating system purpose-built for running as a router and firewall – fully controlled through a coherent command line, without a web interface. In an age of admin UIs, that is often its real strength:
commit makes changes effective, save writes them permanently. VyOS keeps a commit history that lets you compare configurations and roll back to the last working version. Automation via Ansible is standard (collection vyos.vyos).VyOS takes on quite different roles in businesses – the CLI and the mindset always stay the same:
The “one configuration base for devices and sites” aspect is what makes VyOS valuable in day-to-day operations: what applies at the BGP router in the data centre works unchanged at a 50-person office – and vice versa.
VyOS is open source – the source code is published on GitHub under the GPL-2.0. That answers the fundamental questions quickly: no per-domain pricing, no “more bandwidth if you pay for a more expensive licence”, no hidden feature unlocks. If you like, you can build images yourself from the source code at any time. Instead, the project is funded by subscriptions that sell the convenience: ready-made images, updates and support.
The release types and entry points at a glance:
current development state – nightly or as regular snapshots. Always the latest state with all features, but with no stability guarantees. Ideal for development, labs and feature testing.Our practical recommendation for companies: use an LTS subscription for productive sites – support and SLA are worth their weight in gold when things go wrong – while the free rolling and stream images are perfectly sufficient for testing and lab environments.
In this article we focus on the firewall – the foundation of every site. The concepts we build here are the same ones the other scenarios are built on.
Classic firewall configurations are collections of rules per interface: every new interface means new, often copy-and-pasted rules. A zone-based firewall turns this around: instead of attaching rules to interfaces, you group interfaces with the same role into a zone and define the policy between zones.
Internet ──eth0──> ┌───────────────┐ <──eth1── LAN (192.168.1.0/24)
│ VyOS Router │
│ Zones: WAN/LAN │
└───────────────┘
This benefits small and medium businesses in particular:
VyOS versions 1.4 and 1.5 fully support zone-based firewalls, configured under set firewall zone ….
According to the official documentation, VyOS requires at least a 64-bit x86 CPU (Intel or AMD), 4 GB RAM and 10 GB of storage. For production use you should plan more generously: extra RAM and cores pay off above all with large routing tables (BGP), VPP and many tunnel instances.
VyOS provides images for x86-64 as ISO, QCOW2, OVA, RAW, VHD and XVA – so it runs on bare metal just as well as in KVM/Proxmox, VMware or Xen; for the clouds (AWS, Azure, GCP, …) there are matching, cloud-init-capable variants. If you want a verified device, you will find the official Hardware Compatibility List at vyos.io/hcl – it lists all appliances validated by VyOS or the vendors.
Initial installation is done from the ISO (live boot, then install image); later upgrades are applied as new images rather than package updates.
VyOS is deliberately CLI-only software – anyone used to Linux or Cisco command lines finds their way around immediately. Two modes matter:
vyos@vyos$): everyday commands such as ping, tracepath, show version or show system commit.configure, prompt vyos@vyos#): where the configuration is built – set, delete, commit and co. exist only here. From this mode, run <command> starts an operational command.The configuration is a tree. set inserts values, delete removes them – all discoverable via tab-completion and the ? menu, no memorised syntax needed. show displays the intermediate configuration, compare the diff against the active configuration; uncommitted changes are dropped with discard.
A typical session:
vyos@vyos$ configure
vyos@vyos# set system host-name "gw01"
vyos@vyos# set interfaces ethernet eth0 address dhcp
vyos@vyos# set interfaces ethernet eth1 description 'LAN'
vyos@vyos# compare
vyos@vyos# commit
vyos@vyos# save
vyos@vyos# exit
commit makes it effective, save makes it permanent: changes take effect only after commit; only save writes them permanently to /config/config.boot. For risky operations – the first firewall rule-set is a classic – commit-confirm helps: the change is applied temporarily and must be confirmed with confirm within 10 minutes (configurable, e.g. commit-confirm 5) – otherwise the system automatically reverts to the previous revision (reboot by default, switchable to reload).
Configuration versioning: VyOS automatically creates a revision on every commit; the last 100 are kept (expandable via set system config-management commit-revisions 1000). Every change can thus be traced:
vyos@vyos$ show system commit
vyos@vyos$ show system commit diff 5
vyos@vyos$ show system commit file 3
Rollback and backup: rollback <revision> restores an older state (currently tied to a reboot – first check the target with compare). Alternatively, load <file> fetches a saved configuration – local or via SCP/HTTP and co. – and makes it active again with commit. If you want automatic archiving, export every revision to a TFTP/FTP/SCP/SFTP server: set system config-management commit-archive "scp://user:password@server/directory".
The most important commands at a glance:
| Command | Mode | Effect |
|---|---|---|
configure | Operational | Switch to configuration mode |
set … | Config | Set a value in the configuration tree |
delete … | Config | Remove a value from the configuration tree |
show | Config | Display pending changes |
compare | Config | Diff against the active configuration (or a revision) |
discard | Config | Discard uncommitted changes |
commit | Config | Make changes effective |
commit-confirm [n] / confirm | Config | Apply a risky change temporarily / confirm it |
save | Config | Permanently save to /config/config.boot |
load <file> | Config | Load a configuration from a file (local, SCP, HTTP, …) |
rollback <rev> | Config | Restore an earlier revision (with reboot) |
run <command> | Config | Run an operational command from config mode |
show system commit | Operational | Show the commit history of revisions |
We start from a freshly installed VyOS instance on an x86 appliance with at least two network cards – one towards the internet (eth0), one towards the LAN (eth1). This is the classic branch-office router. All steps use the CLI concepts just introduced.
configure
set system host-name firewall
set interfaces ethernet eth0 address dhcp
set interfaces ethernet eth1 address 192.168.1.1/24
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 range start 192.168.1.100 stop 192.168.1.199
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 default-router 192.168.1.1
commit
save
eth0 receives its address from the provider via DHCP, eth1 is the LAN gateway. If you do not want the router to run DHCP, simply omit the three dhcp-server lines.
A zone groups interfaces with the same task. In our scenario:
WAN – the untrusted outside world: eth0LAN – the internal network: eth1LOCAL – the router itself: sessions destined for the firewall (e.g. SSH, NTP, OSPF)Important with VyOS: an interface may only belong to one zone, and traffic within a zone flows freely by default. The security boundary is the transition between zones.
configure
set firewall zone LAN interface eth1
set firewall zone LAN default-action drop
set firewall zone WAN interface eth0
set firewall zone WAN default-action drop
set firewall zone LOCAL local-zone
set firewall zone LOCAL default-action drop
commit
save
For every zone pair you define two rule-sets – one per direction (the firewall follows the same flow as routing). We stick to the VyOS documentation’s <Source>-<Destination>-v4 naming convention.
We need four rule-sets:
LAN-WAN-v4 – outbound internet trafficWAN-LAN-v4 – inbound traffic from the internetLAN-LOCAL-v4 – access to the router (e.g. SSH, DNS)WAN-LOCAL-v4 – attempts from outside to reach the router (should fail)Rule-sets are attached to the destination zone, listing the source zone – so set firewall zone LAN from WAN firewall name WAN-LAN-v4 for inbound traffic from WAN to LAN. Concrete examples follow; first, the principle: the rule-set decides what is allowed to cross the zone boundary.
For our example (IPv4):
configure
# LAN → WAN: allow everything
set firewall ipv4 name LAN-WAN-v4 default-action accept
# WAN → LAN: only replies and follow-up packets of existing connections
set firewall ipv4 name WAN-LAN-v4 default-action drop
set firewall ipv4 name WAN-LAN-v4 rule 10 action accept
set firewall ipv4 name WAN-LAN-v4 rule 10 state established
set firewall ipv4 name WAN-LAN-v4 rule 20 action accept
set firewall ipv4 name WAN-LAN-v4 rule 20 state related
# Attach the rule-sets to the zones
set firewall zone LAN from WAN firewall name WAN-LAN-v4
set firewall zone WAN from LAN firewall name LAN-WAN-v4
commit
save
That gives us the most important rule of all: the LAN can reach the internet, nothing from outside gets in. Connections initiated from inside are let through as replies thanks to connection tracking (state established/state related).
Access to the router itself is handled through LOCAL. SSH from the LAN only, with default-drop:
configure
set firewall ipv4 name LAN-LOCAL-v4 default-action drop
set firewall ipv4 name LAN-LOCAL-v4 rule 10 action accept
set firewall ipv4 name LAN-LOCAL-v4 rule 10 protocol tcp
set firewall ipv4 name LAN-LOCAL-v4 rule 10 destination port 22
set firewall ipv4 name WAN-LOCAL-v4 default-action drop
set firewall zone LOCAL from LAN firewall name LAN-LOCAL-v4
set firewall zone LOCAL from WAN firewall name WAN-LOCAL-v4
commit
save
Any additional services the router should offer (DNS answers into the LAN, NTP, DynDNS updates) are added as further accept rules before the drop default – preferably with a description.
Without source NAT the LAN cannot reach the internet using the public address of eth0 – reply packets would not know where to go. Classic configuration: all packets from 192.168.1.0/24 leaving via eth0 get the WAN address as their source:
configure
set nat source rule 100 outbound-interface eth0
set nat source rule 100 source address 192.168.1.0/24
set nat source rule 100 translation address masquerade
commit
save
From here it is just one step to port forwards (destination NAT) – we will pick those up in one of the follow-up articles for services such as Vaultwarden.
The larger the network, the more important firewall groups become – reusable lists of addresses, networks, ports, domains or MAC addresses. Instead of repeating five IPs in five rules, define a group once and reference it:
configure
set firewall group network-group NET-MGMT network 192.168.1.0/24
set firewall group network-group NET-MGMT network 192.168.2.0/24
set firewall group address-group HOSTS-DNS address 10.0.0.53
set firewall group address-group HOSTS-DNS address 10.0.0.54
set firewall group port-group INCOMING-SERVICES port 443
set firewall group port-group INCOMING-SERVICES port 8443
set firewall ipv4 name WAN-LAN-v4 rule 30 action accept
set firewall ipv4 name WAN-LAN-v4 rule 30 protocol tcp
set firewall ipv4 name WAN-LAN-v4 rule 30 destination group port-group INCOMING-SERVICES
set firewall ipv4 name WAN-LAN-v4 rule 30 source group address-group HOSTS-MANAGEMENT
commit
save
If the list changes later, only a single place needs editing – group members can even be negated with ! (“everything except …”).
IPv6 packets do not pass through IPv4 rule-sets. If you use IPv6, you need parallel rule-sets under set firewall ipv6 name … and set firewall zone … from … firewall ipv6-name …, with the naming convention ending in -v6 (LAN-WAN-v6). The easiest approach is to start with default-action drop and only add what is really needed.
Before “firing” each rule-set, active logging is gold. You can set log per rule or default-log for the whole set – evaluation happens in operation mode:
show firewall zone-policy
show firewall ipv4 summary
monitor log firewall
A look at show firewall zone-policy reveals which interfaces each zone has and which rule-sets are attached at the transitions. If a rule unexpectedly drops packets, the firewall log shows it immediately in the rising drop counter.
Two practical notes from the VyOS documentation that you would otherwise ignore until you trip over them:
default-action, base chains (input/forward/output) accept everything by default. Zones and rule-sets, on the other hand, drop by default. Never rely on that – always set default-action drop explicitly.Links to continue directly:
A zone-based firewall with VyOS is manageable, transparent and thousands of euros cheaper than many commercial licenses – with full control over the configuration. Applied consistently with a “default-drop plus explicit exceptions” mindset, it gives you a solid foundation for any number of sites. In the next articles we will cover the obvious extensions: site-to-site VPN and dual-WAN failover. And since every firewall achieves more when combined with your own identity management, take a look at our kanidm article as well. We set up VyOS firewalls, routers and complete branch networks for you – from concept to rollout, including maintenance.