VyOS Isn't Scary: Building Your First Production-Ready Router

VyOS has a reputation for being intimidating. The CLI-only interface, the commit/save model, the sheer number of configuration options — it can feel overwhelming. But here’s the thing: VyOS isn’t complicated, it’s just explicit. Every setting you’d configure through a consumer router’s web UI exists here too, just visible and version-controllable.

This guide walks through building a basic but production-ready router configuration. We’ll validate each piece before moving to the next. By the end, you’ll have a working router and the confidence to extend it.

The Mental Model

Before touching any commands, understand VyOS’s configuration model:

  1. Configuration tree: Settings are organized hierarchically (like a filesystem)
  2. Edit sessions: Changes are staged, then committed atomically
  3. Rollback capability: Bad commit? Roll back instantly
  4. Show vs Configure mode: show reads running state, configure modifies it
Terminal window
# Enter configuration mode
configure
# Make changes (staged, not active yet)
set interfaces ethernet eth0 address 192.168.1.1/24
# See what would change
compare
# Apply changes atomically
commit
# Persist across reboots
save
# Exit configuration mode
exit

This model prevents half-applied configurations. Either everything commits successfully, or nothing changes.

Initial Setup: Interfaces

Let’s assume a typical setup:

  • eth0: WAN (gets address via DHCP from ISP)
  • eth1: LAN (our internal network, 10.0.0.0/24)
Terminal window
configure
# WAN interface - DHCP from ISP
set interfaces ethernet eth0 description 'WAN'
set interfaces ethernet eth0 address dhcp
# LAN interface - static address, this router is the gateway
set interfaces ethernet eth1 description 'LAN'
set interfaces ethernet eth1 address '10.0.0.1/24'
commit

Validation step: Check interfaces are up and addressed correctly.

Terminal window
show interfaces

You should see eth0 with an address from your ISP and eth1 with 10.0.0.1/24. If eth0 shows no address, check cable and ISP connectivity.

NAT: Making LAN Traffic Reach the Internet

Without NAT, your LAN devices can’t reach the internet — their private IPs aren’t routable. We need source NAT (masquerade) on outbound traffic.

Terminal window
configure
# Source NAT for outbound traffic
set nat source rule 100 outbound-interface name 'eth0'
set nat source rule 100 source address '10.0.0.0/24'
set nat source rule 100 translation address 'masquerade'
commit

Validation step: From a LAN device with manual IP (10.0.0.100, gateway 10.0.0.1), try pinging 8.8.8.8.

Terminal window
# On VyOS, check NAT is working
show nat source statistics

If pings fail, verify:

  1. LAN device has correct gateway (10.0.0.1)
  2. VyOS can ping 8.8.8.8 itself (routing works)
  3. NAT rule matches your LAN subnet

DHCP: Automatic Addressing for LAN Clients

Manual IPs work for testing, but clients need DHCP.

Terminal window
configure
# DHCP server for LAN
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 subnet-id 1
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 range 0 start '10.0.0.100'
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 range 0 stop '10.0.0.254'
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 default-router '10.0.0.1'
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 name-server '10.0.0.1'
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 lease '86400'
commit

Validation step: Release/renew DHCP on a LAN client, verify it gets an address in the 10.0.0.100-254 range.

Terminal window
show dhcp server leases

DNS Forwarding: Local Resolution

Clients point to 10.0.0.1 for DNS. VyOS needs to forward those queries upstream.

Terminal window
configure
# DNS forwarding
set service dns forwarding cache-size '1000'
set service dns forwarding listen-address '10.0.0.1'
set service dns forwarding allow-from '10.0.0.0/24'
# Use ISP's DNS or public resolvers
set service dns forwarding name-server '1.1.1.1'
set service dns forwarding name-server '8.8.8.8'
commit

Validation step: From LAN client, resolve a domain.

Terminal window
# On VyOS
show dns forwarding statistics

At this point, LAN clients should have full internet access with automatic addressing. Test by browsing from a client device.

Firewall: The Foundation

VyOS firewall works on zone/interface pairs. The mental model:

  • Traffic flows between zones (WAN zone, LAN zone)
  • Rules apply to traffic direction (in, out, local)
  • Default policy should be drop (explicit allow)

Modern VyOS (1.4+) uses a zone-based approach. Here’s a clean baseline:

Terminal window
configure
# Create firewall groups for organization
set firewall group network-group LAN-NETS network '10.0.0.0/24'
# WAN to LAN: only established/related connections (no inbound initiation)
set firewall ipv4 name WAN-TO-LAN default-action 'drop'
set firewall ipv4 name WAN-TO-LAN rule 10 action 'accept'
set firewall ipv4 name WAN-TO-LAN rule 10 state 'established'
set firewall ipv4 name WAN-TO-LAN rule 10 state 'related'
# WAN to router itself (local): very restrictive
set firewall ipv4 name WAN-LOCAL default-action 'drop'
set firewall ipv4 name WAN-LOCAL rule 10 action 'accept'
set firewall ipv4 name WAN-LOCAL rule 10 state 'established'
set firewall ipv4 name WAN-LOCAL rule 10 state 'related'
# LAN to WAN: allow all outbound (NAT handles the rest)
set firewall ipv4 name LAN-TO-WAN default-action 'accept'
# LAN to router: allow DHCP, DNS, SSH
set firewall ipv4 name LAN-LOCAL default-action 'drop'
set firewall ipv4 name LAN-LOCAL rule 10 action 'accept'
set firewall ipv4 name LAN-LOCAL rule 10 state 'established'
set firewall ipv4 name LAN-LOCAL rule 10 state 'related'
set firewall ipv4 name LAN-LOCAL rule 20 action 'accept'
set firewall ipv4 name LAN-LOCAL rule 20 protocol 'udp'
set firewall ipv4 name LAN-LOCAL rule 20 destination port '67,68'
set firewall ipv4 name LAN-LOCAL rule 30 action 'accept'
set firewall ipv4 name LAN-LOCAL rule 30 protocol 'udp'
set firewall ipv4 name LAN-LOCAL rule 30 destination port '53'
set firewall ipv4 name LAN-LOCAL rule 40 action 'accept'
set firewall ipv4 name LAN-LOCAL rule 40 protocol 'tcp'
set firewall ipv4 name LAN-LOCAL rule 40 destination port '53'
set firewall ipv4 name LAN-LOCAL rule 50 action 'accept'
set firewall ipv4 name LAN-LOCAL rule 50 protocol 'tcp'
set firewall ipv4 name LAN-LOCAL rule 50 destination port '22'
set firewall ipv4 name LAN-LOCAL rule 50 source group network-group 'LAN-NETS'
# Apply firewall to forward chain (traffic passing through router)
set firewall ipv4 forward filter default-action 'accept'
set firewall ipv4 forward filter rule 10 inbound-interface name 'eth0'
set firewall ipv4 forward filter rule 10 action 'jump'
set firewall ipv4 forward filter rule 10 jump-target 'WAN-TO-LAN'
# Apply firewall to input chain (traffic TO the router)
set firewall ipv4 input filter default-action 'drop'
set firewall ipv4 input filter rule 10 inbound-interface name 'eth0'
set firewall ipv4 input filter rule 10 action 'jump'
set firewall ipv4 input filter rule 10 jump-target 'WAN-LOCAL'
set firewall ipv4 input filter rule 20 inbound-interface name 'eth1'
set firewall ipv4 input filter rule 20 action 'jump'
set firewall ipv4 input filter rule 20 jump-target 'LAN-LOCAL'
commit

Validation step: Test each service still works after firewall is applied.

Terminal window
# Check firewall rule hit counts
show firewall
# From LAN: verify DNS, DHCP, internet access
# From WAN: verify no response to unsolicited connections

Systematic Validation Checklist

Before calling this “done”, verify each component:

ComponentTestExpected Result
WAN connectivityping 8.8.8.8 from VyOSSuccess
DNS on VyOSping google.com from VyOSResolves and pings
LAN addressingshow interfaceseth1 has 10.0.0.1/24
DHCPClient gets addressIP in 10.0.0.100-254
NATClient pings 8.8.8.8Success
DNS forwardingClient resolves domainsSuccess
Firewall (LAN→WAN)Client browses internetSuccess
Firewall (WAN→LAN)External port scanAll filtered

The Complete Configuration

Here’s everything in one block for reference:

Terminal window
# Interfaces
set interfaces ethernet eth0 description 'WAN'
set interfaces ethernet eth0 address dhcp
set interfaces ethernet eth1 description 'LAN'
set interfaces ethernet eth1 address '10.0.0.1/24'
# NAT
set nat source rule 100 outbound-interface name 'eth0'
set nat source rule 100 source address '10.0.0.0/24'
set nat source rule 100 translation address 'masquerade'
# DHCP
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 subnet-id 1
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 range 0 start '10.0.0.100'
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 range 0 stop '10.0.0.254'
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 default-router '10.0.0.1'
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 name-server '10.0.0.1'
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 lease '86400'
# DNS
set service dns forwarding cache-size '1000'
set service dns forwarding listen-address '10.0.0.1'
set service dns forwarding allow-from '10.0.0.0/24'
set service dns forwarding name-server '1.1.1.1'
set service dns forwarding name-server '8.8.8.8'
# Firewall (see detailed rules above)
# ... firewall rules ...
# System basics
set system host-name 'router'
set system name-server '1.1.1.1'
set system time-zone 'UTC'
# SSH access (LAN only via firewall)
set service ssh port '22'

What’s Next

This configuration handles basic routing, but there’s more to explore:

  • IPv6: Modern networks should support it (covered in the next article)
  • VLANs: Segment your network further
  • VPN: WireGuard or IPsec for remote access
  • Monitoring: Logs and metrics for visibility

The key lesson from this exercise: build the foundation first, validate each piece, then extend. VyOS rewards methodical configuration. When something breaks later, you’ll know exactly which commit introduced the problem.

Save your configuration, export it (show configuration commands > config.txt), and version control it. Your router is now reproducible.