Quick Start: VyOS Up and Running in 5 Minutes
I run a homelab with Proxmox VE managing 12 VMs and containers — it’s my playground for testing everything before pushing to production. After needing to simulate complex network environments a few times — multi-VLAN, static/dynamic routing, IPsec tunnels — I decided to give VyOS a shot. I’ve been hooked ever since: the Juniper JunOS-style syntax feels closer to real hardware than any virtual router I’ve worked with.
VyOS is a fork of Vyatta — free, no feature limitations, available in both rolling release and LTS. Download the rolling ISO (recommended for lab use) from the official site and create a VM with these minimum specs:
- CPU: 1–2 vCPU
- RAM: 512MB (1GB if you need to run multiple VPN tunnels)
- Disk: 4GB
- Network: at least 2 vNICs — one WAN (connected to the external network), one LAN (connected to the internal network)
Create a VM on KVM with virt-install
virt-install \
--name vyos-lab \
--ram 1024 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/vyos-lab.qcow2,size=4 \
--cdrom /tmp/vyos-rolling.iso \
--network bridge=br0 \
--network bridge=br1 \
--os-variant debian11 \
--noautoconsole
On Proxmox, use the GUI: create a VM and assign 2 Network Devices to 2 different bridges (e.g., vmbr0 for WAN, vmbr1 for LAN).
Install and Configure Initial Network Settings
Boot into the ISO, log in with vyos/vyos, and run the install command:
install image
Follow the wizard and reboot. Once back up, enter configure mode and set up the interfaces:
configure
set interfaces ethernet eth0 address dhcp
set interfaces ethernet eth0 description 'WAN'
set interfaces ethernet eth1 address 192.168.10.1/24
set interfaces ethernet eth1 description 'LAN'
set system name-server 8.8.8.8
set system name-server 8.8.4.4
commit
save
The golden rule with VyOS: commit applies the config to the running state, while save writes it to startup config. Forget to save and reboot — and your entire config is gone. I learned this the hard way.
Zone-Based Firewall: Think in Traffic Flows, Not Chains
VyOS doesn’t use the INPUT/OUTPUT/FORWARD model like raw iptables. Instead, each interface belongs to a zone, and traffic between two zones must pass through an explicitly assigned ruleset. This approach is much cleaner when your lab has multiple network segments.
I use 3 zones: WAN, LAN, and LOCAL (the VyOS router itself).
configure
# === Ruleset: WAN -> LOCAL (allow SSH and return traffic only) ===
set firewall name WAN-to-LOCAL default-action drop
set firewall name WAN-to-LOCAL rule 10 action accept
set firewall name WAN-to-LOCAL rule 10 state established enable
set firewall name WAN-to-LOCAL rule 10 state related enable
set firewall name WAN-to-LOCAL rule 20 action accept
set firewall name WAN-to-LOCAL rule 20 protocol tcp
set firewall name WAN-to-LOCAL rule 20 destination port 22
# === Ruleset: WAN -> LAN (return traffic only, block new connections) ===
set firewall name WAN-to-LAN default-action drop
set firewall name WAN-to-LAN rule 10 action accept
set firewall name WAN-to-LAN rule 10 state established enable
set firewall name WAN-to-LAN rule 10 state related enable
# === Ruleset: LAN -> WAN (allow all outbound traffic from LAN) ===
set firewall name LAN-to-WAN default-action accept
# === Ruleset: LAN -> LOCAL (SSH into router from LAN) ===
set firewall name LAN-to-LOCAL default-action drop
set firewall name LAN-to-LOCAL rule 10 action accept
set firewall name LAN-to-LOCAL rule 10 state established enable
set firewall name LAN-to-LOCAL rule 10 state related enable
set firewall name LAN-to-LOCAL rule 20 action accept
set firewall name LAN-to-LOCAL rule 20 protocol tcp
set firewall name LAN-to-LOCAL rule 20 destination port 22
# === Assign interfaces to zones ===
set zone-policy zone WAN interface eth0
set zone-policy zone LAN interface eth1
set zone-policy zone LOCAL local-zone
# === Apply rulesets between zones ===
set zone-policy zone LOCAL from WAN firewall name WAN-to-LOCAL
set zone-policy zone LOCAL from LAN firewall name LAN-to-LOCAL
set zone-policy zone LAN from WAN firewall name WAN-to-LAN
set zone-policy zone WAN from LAN firewall name LAN-to-WAN
commit
save
NAT: Masquerade and Port Forwarding
With the firewall in place, LAN machines still can’t reach the internet — NAT is missing. VyOS calls this Source NAT with masquerade translation.
configure
# Masquerade: hide the entire LAN 192.168.10.0/24 behind the WAN IP
set nat source rule 100 outbound-interface eth0
set nat source rule 100 source address 192.168.10.0/24
set nat source rule 100 translation address masquerade
commit
save
Port forwarding (Destination NAT) — expose a LAN web server to the outside:
configure
# DNAT: WAN port 80 -> 192.168.10.100:80
set nat destination rule 10 inbound-interface eth0
set nat destination rule 10 protocol tcp
set nat destination rule 10 destination port 80
set nat destination rule 10 translation address 192.168.10.100
set nat destination rule 10 translation port 80
commit
save
Site-to-Site VPN with IPsec IKEv2
This is the main reason I stopped going back to pfSense for my lab. I’ll simulate 2 sites connected via an IPsec IKEv2 tunnel — the same configuration logic you’d encounter on a Cisco ASA or Juniper SRX in production.
Topology:
- VyOS-A: WAN
10.0.0.1, LAN192.168.10.0/24 - VyOS-B: WAN
10.0.0.2, LAN192.168.20.0/24
Configure VyOS-A
configure
# IKE group (phase 1)
set vpn ipsec ike-group IKE-DEFAULT key-exchange ikev2
set vpn ipsec ike-group IKE-DEFAULT lifetime 28800
set vpn ipsec ike-group IKE-DEFAULT proposal 1 dh-group 14
set vpn ipsec ike-group IKE-DEFAULT proposal 1 encryption aes256
set vpn ipsec ike-group IKE-DEFAULT proposal 1 hash sha256
# ESP group (phase 2)
set vpn ipsec esp-group ESP-DEFAULT lifetime 3600
set vpn ipsec esp-group ESP-DEFAULT mode tunnel
set vpn ipsec esp-group ESP-DEFAULT proposal 1 encryption aes256
set vpn ipsec esp-group ESP-DEFAULT proposal 1 hash sha256
# Interface to listen for IPsec
set vpn ipsec ipsec-interfaces interface eth0
# Peer and tunnel
set vpn ipsec site-to-site peer 10.0.0.2 authentication mode pre-shared-secret
set vpn ipsec site-to-site peer 10.0.0.2 authentication pre-shared-secret 'Lab@Secret#2024'
set vpn ipsec site-to-site peer 10.0.0.2 ike-group IKE-DEFAULT
set vpn ipsec site-to-site peer 10.0.0.2 default-esp-group ESP-DEFAULT
set vpn ipsec site-to-site peer 10.0.0.2 local-address 10.0.0.1
set vpn ipsec site-to-site peer 10.0.0.2 tunnel 1 local prefix 192.168.10.0/24
set vpn ipsec site-to-site peer 10.0.0.2 tunnel 1 remote prefix 192.168.20.0/24
commit
save
Configure VyOS-B (mirror of VyOS-A)
configure
set vpn ipsec ike-group IKE-DEFAULT key-exchange ikev2
set vpn ipsec ike-group IKE-DEFAULT lifetime 28800
set vpn ipsec ike-group IKE-DEFAULT proposal 1 dh-group 14
set vpn ipsec ike-group IKE-DEFAULT proposal 1 encryption aes256
set vpn ipsec ike-group IKE-DEFAULT proposal 1 hash sha256
set vpn ipsec esp-group ESP-DEFAULT lifetime 3600
set vpn ipsec esp-group ESP-DEFAULT mode tunnel
set vpn ipsec esp-group ESP-DEFAULT proposal 1 encryption aes256
set vpn ipsec esp-group ESP-DEFAULT proposal 1 hash sha256
set vpn ipsec ipsec-interfaces interface eth0
set vpn ipsec site-to-site peer 10.0.0.1 authentication mode pre-shared-secret
set vpn ipsec site-to-site peer 10.0.0.1 authentication pre-shared-secret 'Lab@Secret#2024'
set vpn ipsec site-to-site peer 10.0.0.1 ike-group IKE-DEFAULT
set vpn ipsec site-to-site peer 10.0.0.1 default-esp-group ESP-DEFAULT
set vpn ipsec site-to-site peer 10.0.0.1 local-address 10.0.0.2
set vpn ipsec site-to-site peer 10.0.0.1 tunnel 1 local prefix 192.168.20.0/24
set vpn ipsec site-to-site peer 10.0.0.1 tunnel 1 remote prefix 192.168.10.0/24
commit
save
Verify the Tunnel
# Check SA (Security Association) status
show vpn ipsec sa
# Ping through the tunnel from VyOS-A to VyOS-B's LAN
ping 192.168.20.1 source-address 192.168.10.1 count 5
If the output shows ESTABLISHED along with bytes/packets flowing, the tunnel is up. If you see CONNECTING stuck indefinitely, it’s almost certainly the firewall blocking UDP 500 or ESP (protocol 50) — check that first.
Practical Tips for Running VyOS
Back Up Config Before Every Change
# Save backup with timestamp
save /config/backup-$(date +%Y%m%d-%H%M).conf
# Copy to external location
scp [email protected]:/config/backup-20240620-1430.conf ./
Roll Back a Bad Commit
VyOS maintains a commit history — rolling back is straightforward:
# View commit history
show system commit
# Roll back to the previous commit (index 1)
rollback 1
commit
save
Debug Firewall and Traffic
# View hit counters for each rule
show firewall name WAN-to-LAN statistics
# Monitor traffic in real time
monitor traffic interface eth0
# View firewall log (if logging is enabled)
show log firewall name WAN-to-LAN
One thing I learned after getting locked out of the router: always run monitor traffic in a separate SSH session while testing firewall rules in another. You can see packets passing or being dropped in real time — no guesswork.
VyOS is ideal for labs that need BGP, OSPF, or multi-tunnel IPsec — features pfSense has too, but with syntax that’s far from real hardware. If you just need simple NAT for a small network, pfSense/OPNsense is still much more user-friendly. But if your goal is to build muscle memory for CLI network engineering, there’s no better virtual router on Proxmox/KVM for hands-on practice than VyOS.
