Post

VyOS: Installation, Configuration, and Usage

VyOS is an open-source network operating system built on Debian Linux. It provides the routing, firewall, VPN, and traffic-management capabilities of enterprise routers — Cisco IOS, Juniper JunOS — in a freely available, fully scriptable platform that runs on commodity hardware, virtual machines, and public cloud instances.

Unlike GUI-driven firewalls such as OPNsense or pfSense, VyOS is entirely CLI-configured through a structured hierarchical command language modelled on Juniper’s JunOS. Every configuration change is atomic: you stage changes in a candidate configuration, review them, and commit when satisfied — the running system is only updated at commit time.

VyOS vs Traditional Network Operating Systems

Feature VyOS Cisco IOS-XE Juniper JunOS OPNsense
License Open source (LTS paid, rolling free) Proprietary Proprietary Open source
Config model Hierarchical CLI Flat/hierarchical CLI Hierarchical CLI Web GUI + CLI
Candidate/running Yes (commit model) No Yes No
Scripting / API Full (Bash + Python + HTTP API) Limited Yes (PyEZ) REST API
Routing protocols BGP, OSPF, RIP, IS-IS, BFD Full Full Static + BGP plugin
VPN IPsec, OpenVPN, WireGuard, L2TP, SSTP IPsec, SSL IPsec, SSL IPsec, OpenVPN, WireGuard
Cloud support AWS, Azure, GCP images Marketplace Marketplace Limited
Container/VM friendly Excellent Moderate Moderate Good

Architecture Overview

VyOS wraps standard Linux networking tools — FRRouting, iproute2, nftables/iptables, strongSwan, OpenVPN — behind a unified configuration abstraction:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──────────────────────────────────────────────────────┐
│                 VyOS CLI / HTTP API                  │
│          (vyos-configd / vyos-http-api)              │
├──────────────────────────────────────────────────────┤
│              Configuration Subsystem                 │
│   candidate config ──commit──► running config        │
│       /config/config.boot  ◄──save── running config  │
├──────────┬──────────┬───────────┬────────────────────┤
│ FRRouting│ iproute2 │ strongSwan│ OpenVPN/WireGuard  │
│ (BGP,    │ (routes, │ (IPsec)   │ (VPN tunnels)      │
│ OSPF,    │ VRFs,    │           │                    │
│ IS-IS)   │ bridges) │           │                    │
├──────────┴──────────┴───────────┴────────────────────┤
│              nftables / iptables / conntrack         │
│              (firewall, NAT, traffic shaping)        │
├──────────────────────────────────────────────────────┤
│                   Debian Linux Kernel                │
└──────────────────────────────────────────────────────┘

VyOS Editions

Edition Description Cost
Rolling Latest development build — updated frequently Free
LTS (Long Term Support) Stable, tested releases (e.g. 1.4 Sagitta, 1.5 Circinus) Paid subscription
AWS / Azure / GCP Marketplace images Usage-based

For production environments, use an LTS release. For labs and learning, the rolling release ISO is free and always current.

Download from vyos.io/get (rolling) or via subscription for LTS.


Installation

Bare Metal / VM

Boot from the ISO and log in with vyos / vyos, then run the installer:

1
install image

The installer prompts for:

  1. Disk selection
  2. Partition table (auto recommended)
  3. Image name (e.g. 1.4.0)
  4. Root password

After installation, reboot and remove the installation media.

Install in KVM / VirtualBox / VMware

Create a VM with:

  • RAM: 512 MB minimum (1 GB+ recommended)
  • Disk: 4 GB minimum
  • NICs: at least 2 (WAN + LAN)

Boot from the ISO, run install image, reboot.

Deploy on AWS (CLI)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Find the latest VyOS AMI
aws ec2 describe-images \
  --owners 679593333241 \
  --filters "Name=name,Values=VyOS*" \
  --query 'Images[*].[ImageId,Name,CreationDate]' \
  --output table

# Launch instance
aws ec2 run-instances \
  --image-id ami-xxxxxxxxxx \
  --instance-type t3.small \
  --key-name my-key \
  --security-group-ids sg-xxxxxxxx \
  --subnet-id subnet-xxxxxxxx

CLI Fundamentals

VyOS has two operational modes:

Mode Prompt Purpose
Operational vyos@vyos:~$ Show status, run diagnostics, ping, traceroute
Configuration vyos@vyos# Edit the candidate configuration

Switching Modes

1
2
3
configure          # Enter configuration mode
exit               # Return to operational mode (discard uncommitted changes)
exit discard       # Explicitly discard and exit

The Commit Model

1
2
3
4
5
6
set interfaces ethernet eth0 address '192.168.1.1/24'   # Stage a change
delete interfaces ethernet eth0 address '192.168.1.1/24' # Stage a deletion
compare            # Show diff: candidate vs running
commit             # Apply staged changes to the running system
save               # Write running config to /config/config.boot (persists across reboots)
rollback 1         # Revert to the previous commit

Critical: Changes made with set are not active until you commit. Changes are not persistent across reboots until you save.

1
2
3
4
5
6
show                          # Show full candidate configuration
show interfaces               # Show interfaces subtree
show interfaces ethernet eth0 # Show one interface
edit interfaces ethernet eth0 # Descend into a subtree
top                           # Return to root of tree
up                            # Go up one level

Completion and Help

1
2
set interfaces ethernet eth0 <Tab>  # Tab completion
set interfaces ethernet eth0 ?      # Show available options with descriptions

Interface Configuration

Ethernet Interfaces

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Static IP
set interfaces ethernet eth0 address '203.0.113.2/30'
set interfaces ethernet eth0 description 'WAN — ISP uplink'
set interfaces ethernet eth0 duplex 'auto'
set interfaces ethernet eth0 speed 'auto'

# DHCP client
set interfaces ethernet eth0 address 'dhcp'

# Multiple IPs on one interface
set interfaces ethernet eth0 address '192.168.1.1/24'
set interfaces ethernet eth0 address '10.0.0.1/24'

# Disable an interface
set interfaces ethernet eth0 disable

Loopback Interface

The loopback (lo) is used as a stable router ID for BGP and OSPF:

1
set interfaces loopback lo address '10.255.0.1/32'

VLAN Sub-interfaces (802.1Q)

1
2
3
4
5
6
7
8
set interfaces ethernet eth1 vif 10 address '10.10.10.1/24'
set interfaces ethernet eth1 vif 10 description 'VLAN10 — Trusted LAN'

set interfaces ethernet eth1 vif 20 address '10.20.20.1/24'
set interfaces ethernet eth1 vif 20 description 'VLAN20 — IoT'

set interfaces ethernet eth1 vif 30 address '10.30.30.1/24'
set interfaces ethernet eth1 vif 30 description 'VLAN30 — DMZ'

Bridge Interface

1
2
3
4
5
6
set interfaces bridge br0 address '192.168.10.1/24'
set interfaces bridge br0 description 'LAN bridge'
set interfaces bridge br0 member interface eth1
set interfaces bridge br0 member interface eth2
set interfaces bridge br0 aging '300'
set interfaces bridge br0 stp 'true'
1
2
3
4
5
6
set interfaces bonding bond0 address '192.168.1.1/24'
set interfaces bonding bond0 mode '802.3ad'
set interfaces bonding bond0 member interface eth1
set interfaces bonding bond0 member interface eth2
set interfaces bonding bond0 mii-mon-interval '100'
set interfaces bonding bond0 lacp-rate 'fast'

Verify Interfaces

1
2
3
4
show interfaces                      # Summary of all interfaces
show interfaces ethernet eth0        # Detail for one interface
show interfaces ethernet eth0 brief  # One-line summary
run ip addr show                     # Linux-level view

Static Routing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Default route (internet gateway)
set protocols static route 0.0.0.0/0 next-hop '203.0.113.1'

# Specific static route
set protocols static route 10.50.0.0/16 next-hop '192.168.1.254'

# Blackhole route (null route — drop traffic silently)
set protocols static route 192.0.2.0/24 blackhole

# Route with administrative distance (lower = preferred)
set protocols static route 10.0.0.0/8 next-hop '10.1.1.1' distance '5'

# Static IPv6 route
set protocols static route6 ::/0 next-hop '2001:db8:1::1'

View Routes

1
2
3
4
5
6
7
show ip route                  # Full IPv4 routing table
show ip route bgp              # BGP-learned routes only
show ip route ospf             # OSPF-learned routes only
show ip route static           # Static routes only
show ip route 10.0.0.0/8      # Longest-match for a prefix
show ipv6 route                # IPv6 routing table
run ip route show              # Linux-level routing table

OSPF (Open Shortest Path First)

OSPF is a link-state interior gateway protocol — ideal for routing within an organisation or data centre.

Basic OSPF Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Enable OSPF and set the router ID
set protocols ospf parameters router-id '10.255.0.1'

# Advertise networks into OSPF
set protocols ospf area 0 network '10.10.10.0/24'
set protocols ospf area 0 network '10.20.20.0/24'
set protocols ospf area 0 network '10.255.0.1/32'

# Set interface cost (metric)
set protocols ospf interface eth0 cost '10'
set protocols ospf interface eth1 cost '1'

# Make an interface passive (advertise, but don't form adjacencies)
set protocols ospf passive-interface 'eth2'

# Redistribute static routes into OSPF
set protocols ospf redistribute static metric '20' metric-type '2'

# Redistribute connected networks
set protocols ospf redistribute connected

OSPF Authentication

1
set protocols ospf interface eth0 authentication md5 key-id 1 md5-key 'secret-key'

Multi-Area OSPF

1
2
3
4
5
6
7
8
9
10
# Area 0 — backbone
set protocols ospf area 0 network '10.0.0.0/24'

# Area 1 — stub area
set protocols ospf area 1 network '10.1.0.0/24'
set protocols ospf area 1 area-type stub

# ABR (Area Border Router) — router participates in both areas
set protocols ospf area 0 network '10.0.0.1/32'
set protocols ospf area 1 network '10.1.0.1/32'

Verify OSPF

1
2
3
4
5
show ip ospf neighbor            # Adjacency table
show ip ospf neighbor detail     # Full neighbor info
show ip ospf database            # LSDB (Link State Database)
show ip ospf route               # OSPF-computed routes
show ip ospf interface           # Per-interface OSPF state

BGP (Border Gateway Protocol)

BGP is the routing protocol of the internet — used for inter-AS routing, data centre fabrics (eBGP between spine and leaf), and cloud connectivity.

eBGP (External BGP — ISP Peering)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Local AS number
set protocols bgp system-as '65001'
set protocols bgp parameters router-id '10.255.0.1'

# eBGP peer (ISP)
set protocols bgp neighbor '203.0.113.1' remote-as '64512'
set protocols bgp neighbor '203.0.113.1' description 'ISP uplink'
set protocols bgp neighbor '203.0.113.1' address-family ipv4-unicast

# Advertise a prefix to the ISP
set protocols bgp address-family ipv4-unicast network '198.51.100.0/24'

# Apply route-map on inbound from ISP
set protocols bgp neighbor '203.0.113.1' address-family ipv4-unicast route-map import 'ISP_IN'

iBGP (Internal BGP — Within Your AS)

1
2
3
4
5
6
7
8
# iBGP peer (same AS)
set protocols bgp neighbor '10.255.0.2' remote-as '65001'
set protocols bgp neighbor '10.255.0.2' description 'Core router 2'
set protocols bgp neighbor '10.255.0.2' update-source 'lo'
set protocols bgp neighbor '10.255.0.2' address-family ipv4-unicast

# Route reflector (avoid full iBGP mesh)
set protocols bgp neighbor '10.255.0.2' address-family ipv4-unicast route-reflector-client

BGP Route Maps and Prefix Lists

1
2
3
4
5
6
7
8
9
10
11
12
# Prefix list — match specific prefixes
set policy prefix-list ALLOW_DEFAULT rule 10 action 'permit'
set policy prefix-list ALLOW_DEFAULT rule 10 prefix '0.0.0.0/0'

# Route map — apply actions based on match conditions
set policy route-map ISP_IN rule 10 action 'permit'
set policy route-map ISP_IN rule 10 match ip address prefix-list 'ALLOW_DEFAULT'
set policy route-map ISP_IN rule 10 set local-preference '100'

# Route map to set MED outbound
set policy route-map ISP_OUT rule 10 action 'permit'
set policy route-map ISP_OUT rule 10 set metric '50'

BGP Communities

1
2
3
4
5
set protocols bgp neighbor '203.0.113.1' address-family ipv4-unicast \
    route-map export 'ISP_OUT'

set policy route-map ISP_OUT rule 10 action 'permit'
set policy route-map ISP_OUT rule 10 set community '64512:100'

Verify BGP

1
2
3
4
5
6
show bgp summary                         # Peer table with state and prefix counts
show bgp neighbors                       # Detailed peer information
show bgp neighbors 203.0.113.1 received-routes  # Routes received from peer
show bgp neighbors 203.0.113.1 advertised-routes # Routes sent to peer
show bgp ipv4 unicast                    # Full BGP RIB
show bgp ipv4 unicast 0.0.0.0/0         # Specific prefix

Firewall

VyOS uses a zone-based firewall model. Interfaces are grouped into zones, and firewall policies define what traffic is permitted between zones. This is more scalable than per-interface rules.

Define Zones

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# WAN zone
set firewall zone WAN default-action 'drop'
set firewall zone WAN interface 'eth0'
set firewall zone WAN description 'Internet'

# LAN zone
set firewall zone LAN default-action 'drop'
set firewall zone LAN interface 'eth1'
set firewall zone LAN description 'Trusted LAN'

# DMZ zone
set firewall zone DMZ default-action 'drop'
set firewall zone DMZ interface 'eth2'
set firewall zone DMZ description 'DMZ servers'

# LOCAL zone — traffic destined for the router itself
set firewall zone LOCAL default-action 'drop'
set firewall zone LOCAL local-zone

Create Firewall Rule Sets

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Rule set: LAN → WAN (allow all outbound from LAN)
set firewall ipv4 name LAN-WAN default-action 'drop'
set firewall ipv4 name LAN-WAN rule 10 action 'accept'
set firewall ipv4 name LAN-WAN rule 10 state established 'enable'
set firewall ipv4 name LAN-WAN rule 10 state related 'enable'
set firewall ipv4 name LAN-WAN rule 20 action 'accept'
set firewall ipv4 name LAN-WAN rule 20 description 'Allow all LAN to WAN'

# Rule set: WAN → LAN (block everything from internet)
set firewall ipv4 name WAN-LAN default-action 'drop'
set firewall ipv4 name WAN-LAN rule 10 action 'accept'
set firewall ipv4 name WAN-LAN rule 10 state established 'enable'
set firewall ipv4 name WAN-LAN rule 10 state related 'enable'

# Rule set: WAN → LOCAL (allow ICMP and SSH from trusted IPs only)
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 'enable'
set firewall ipv4 name WAN-LOCAL rule 10 state related 'enable'
set firewall ipv4 name WAN-LOCAL rule 20 action 'accept'
set firewall ipv4 name WAN-LOCAL rule 20 protocol 'icmp'
set firewall ipv4 name WAN-LOCAL rule 30 action 'accept'
set firewall ipv4 name WAN-LOCAL rule 30 protocol 'tcp'
set firewall ipv4 name WAN-LOCAL rule 30 destination port '22'
set firewall ipv4 name WAN-LOCAL rule 30 source address '203.0.113.0/24'

Apply Rule Sets to Zones

1
2
3
set firewall zone WAN from LAN firewall name 'LAN-WAN'
set firewall zone LAN from WAN firewall name 'WAN-LAN'
set firewall zone LOCAL from WAN firewall name 'WAN-LOCAL'

Address Groups and Port Groups

1
2
3
4
5
6
7
8
9
10
11
12
# Address group
set firewall group address-group TRUSTED_MGMT address '10.0.0.0/8'
set firewall group address-group TRUSTED_MGMT address '192.168.0.0/16'

# Port group
set firewall group port-group WEB_PORTS port '80'
set firewall group port-group WEB_PORTS port '443'

# Use in a rule
set firewall ipv4 name WAN-DMZ rule 100 action 'accept'
set firewall ipv4 name WAN-DMZ rule 100 destination port 'WEB_PORTS'
set firewall ipv4 name WAN-DMZ rule 100 protocol 'tcp'

View Firewall State

1
2
3
4
5
6
show firewall                        # Summary of all rule sets
show firewall name LAN-WAN           # Detail for one rule set
show firewall name LAN-WAN statistics # Hit counters per rule
show firewall group                  # Address and port groups
show firewall zone-policy            # Zone assignments
run show conntrack table ipv4        # Active connection state table

NAT (Network Address Translation)

Masquerade / Source NAT (Outbound)

1
2
3
4
5
6
7
8
9
10
# Masquerade all LAN traffic leaving WAN
set nat source rule 100 description 'LAN to WAN masquerade'
set nat source rule 100 outbound-interface name 'eth0'
set nat source rule 100 source address '192.168.1.0/24'
set nat source rule 100 translation address 'masquerade'

# Static source NAT (map to a specific public IP)
set nat source rule 200 outbound-interface name 'eth0'
set nat source rule 200 source address '10.10.10.0/24'
set nat source rule 200 translation address '203.0.113.5'

Destination NAT / Port Forwarding (Inbound)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Forward external TCP 443 to an internal web server
set nat destination rule 100 description 'HTTPS to web server'
set nat destination rule 100 inbound-interface name 'eth0'
set nat destination rule 100 protocol 'tcp'
set nat destination rule 100 destination port '443'
set nat destination rule 100 translation address '192.168.1.50'
set nat destination rule 100 translation port '443'

# Forward external TCP 2222 to internal SSH on port 22
set nat destination rule 110 inbound-interface name 'eth0'
set nat destination rule 110 protocol 'tcp'
set nat destination rule 110 destination port '2222'
set nat destination rule 110 translation address '192.168.1.10'
set nat destination rule 110 translation port '22'

Verify NAT

1
2
3
4
show nat source rules              # Source NAT rules
show nat destination rules         # Destination NAT rules
show nat source translations       # Active source NAT sessions
show nat destination translations  # Active destination NAT sessions

DHCP Server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# DHCP for the LAN subnet
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 \
    option default-router '192.168.1.1'
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 \
    option name-server '192.168.1.1'
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 \
    option domain-name 'lan.example.com'
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 \
    lease '86400'
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 \
    range 0 start '192.168.1.100'
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 \
    range 0 stop '192.168.1.200'

# Static mapping (MAC reservation)
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 \
    static-mapping server01 ip-address '192.168.1.50'
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 \
    static-mapping server01 mac '00:11:22:33:44:55'
1
2
show dhcp server leases        # Active leases
show dhcp server statistics    # Pool utilisation

DNS Forwarding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Use Unbound as a forwarding resolver
set service dns forwarding system
set service dns forwarding listen-address '192.168.1.1'
set service dns forwarding listen-address '10.10.10.1'
set service dns forwarding allow-from '192.168.1.0/24'
set service dns forwarding allow-from '10.10.10.0/24'

# Forward queries to upstream resolvers
set service dns forwarding name-server '1.1.1.1'
set service dns forwarding name-server '8.8.8.8'

# Forward a specific domain to an internal DNS server
set service dns forwarding domain 'corp.example.com' \
    name-server '10.0.0.53'

VPN

WireGuard

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Generate keys
run generate pki wireguard key-pair install interface wg0

# Configure the WireGuard interface
set interfaces wireguard wg0 address '10.200.0.1/24'
set interfaces wireguard wg0 port '51820'
set interfaces wireguard wg0 private-key '<base64-private-key>'
set interfaces wireguard wg0 description 'WireGuard VPN'

# Add a peer (remote client)
set interfaces wireguard wg0 peer laptop \
    public-key '<client-public-key>'
set interfaces wireguard wg0 peer laptop \
    allowed-ips '10.200.0.2/32'

# Add a site-to-site peer with a keepalive
set interfaces wireguard wg0 peer site-b \
    public-key '<site-b-public-key>'
set interfaces wireguard wg0 peer site-b \
    address '203.0.113.50'
set interfaces wireguard wg0 peer site-b \
    port '51820'
set interfaces wireguard wg0 peer site-b \
    allowed-ips '10.20.0.0/24'
set interfaces wireguard wg0 peer site-b \
    persistent-keepalive '25'

IPsec (Site-to-Site IKEv2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# IKEv2 proposal
set vpn ipsec ike-group IKEv2 proposal 1 dh-group '14'
set vpn ipsec ike-group IKEv2 proposal 1 encryption 'aes256'
set vpn ipsec ike-group IKEv2 proposal 1 hash 'sha256'
set vpn ipsec ike-group IKEv2 ikev2-reauth 'no'
set vpn ipsec ike-group IKEv2 key-exchange 'ikev2'

# ESP proposal
set vpn ipsec esp-group ESP proposal 1 encryption 'aes256gcm128'
set vpn ipsec esp-group ESP proposal 1 pfs 'dh-group14'

# Tunnel
set vpn ipsec site-to-site peer '203.0.113.50' \
    authentication mode 'pre-shared-secret'
set vpn ipsec site-to-site peer '203.0.113.50' \
    authentication pre-shared-secret 'StrongRandomSecret!'
set vpn ipsec site-to-site peer '203.0.113.50' \
    ike-group 'IKEv2'
set vpn ipsec site-to-site peer '203.0.113.50' \
    local-address '203.0.113.1'
set vpn ipsec site-to-site peer '203.0.113.50' \
    tunnel 1 esp-group 'ESP'
set vpn ipsec site-to-site peer '203.0.113.50' \
    tunnel 1 local prefix '192.168.1.0/24'
set vpn ipsec site-to-site peer '203.0.113.50' \
    tunnel 1 remote prefix '10.0.0.0/24'

OpenVPN (Road Warrior)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Generate CA and server certificate first
run generate pki ca install ca-root
run generate pki certificate sign ca-root install server

# OpenVPN server
set interfaces openvpn vtun0 mode 'server'
set interfaces openvpn vtun0 protocol 'udp'
set interfaces openvpn vtun0 local-port '1194'
set interfaces openvpn vtun0 tls ca-cert-file '/config/auth/ca.pem'
set interfaces openvpn vtun0 tls cert-file '/config/auth/server.pem'
set interfaces openvpn vtun0 tls key-file '/config/auth/server.key'
set interfaces openvpn vtun0 tls dh-params-file '/config/auth/dh.pem'
set interfaces openvpn vtun0 server subnet '10.100.0.0/24'
set interfaces openvpn vtun0 server push-route '192.168.1.0/24'

Verify VPN

1
2
3
4
show vpn ipsec sa              # IPsec security associations
show vpn ipsec status          # Tunnel status
show interfaces wireguard wg0  # WireGuard interface and peers
run wg show                    # Native WireGuard status

QoS — Traffic Shaping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Define a traffic policy
set traffic-policy shaper WAN-SHAPER bandwidth '100mbit'

# Class for VoIP — guaranteed 10 Mbps, priority queue
set traffic-policy shaper WAN-SHAPER class 10 bandwidth '10%'
set traffic-policy shaper WAN-SHAPER class 10 priority '1'
set traffic-policy shaper WAN-SHAPER class 10 match VOIP \
    ip protocol 'udp'
set traffic-policy shaper WAN-SHAPER class 10 match VOIP \
    ip dscp 'ef'

# Default class — best effort
set traffic-policy shaper WAN-SHAPER default bandwidth '90%'
set traffic-policy shaper WAN-SHAPER default queue-type 'fair-queue'

# Apply the shaper to the WAN interface (outbound)
set interfaces ethernet eth0 traffic-policy out 'WAN-SHAPER'

VRF (Virtual Routing and Forwarding)

VRFs create multiple isolated routing tables on one device — essential for multi-tenant environments and MPLS VPNs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Create a VRF
set vrf name CUSTOMER-A table '100'
set vrf name CUSTOMER-B table '200'

# Assign interfaces to VRFs
set interfaces ethernet eth2 vrf 'CUSTOMER-A'
set interfaces ethernet eth3 vrf 'CUSTOMER-B'

# Configure addresses within a VRF
set interfaces ethernet eth2 address '10.100.0.1/24'
set interfaces ethernet eth3 address '10.200.0.1/24'

# Static route within a VRF
set protocols static vrf CUSTOMER-A route 0.0.0.0/0 \
    next-hop '10.100.0.254'

# BGP within a VRF
set protocols bgp vrf CUSTOMER-A system-as '65001'
set protocols bgp vrf CUSTOMER-A neighbor '10.100.0.2' remote-as '65100'

System Management

SSH Access

1
2
3
set service ssh port '22'
set service ssh listen-address '192.168.1.1'
set service ssh disable-password-authentication  # Key-based auth only

User Management

1
2
3
4
5
6
7
8
# Create an admin user with SSH key
set system login user admin full-name 'Network Admin'
set system login user admin authentication plaintext-password 'StrongPass!'
set system login user admin authentication public-keys mykey type 'ssh-rsa'
set system login user admin authentication public-keys mykey key 'AAAAB3...'

# Set privilege level
set system login user admin level 'admin'

System Hostname and NTP

1
2
3
4
5
6
set system host-name 'vyos-core-01'
set system domain-name 'core.example.com'

set system ntp server 'pool.ntp.org'
set system ntp server '0.ubuntu.pool.ntp.org'
set system ntp allow-client address '192.168.1.0/24'

Syslog

1
2
3
4
5
# Log to a remote syslog server
set system syslog host '192.168.1.200' facility 'all' level 'info'

# Log locally with rotation
set system syslog file messages facility 'all' level 'notice'

SNMP

1
2
3
4
5
6
set service snmp community 'public' authorization 'ro'
set service snmp community 'public' client '192.168.1.0/24'
set service snmp location 'Data Centre Rack 12'
set service snmp contact 'noc@example.com'
set service snmp v3 user monitor auth plaintext-key 'authkey123'
set service snmp v3 user monitor privacy plaintext-key 'privkey456'

Configuration Management

Save and Backup

1
2
3
save                           # Write to /config/config.boot
save scp://user@backup-server/configs/vyos-$(date +%Y%m%d).conf
save ftp://192.168.1.200/backups/vyos.conf

Configuration Archive (Auto-Backup on Commit)

1
2
3
set system config-management commit-archive location \
    'scp://backup@192.168.1.200/vyos-backups'
set system config-management commit-revisions '20'

VyOS stores the last N committed configurations locally and pushes to the remote archive on every commit.

Load and Compare Configurations

1
2
3
load scp://user@backup-server/configs/vyos-20251201.conf
compare                        # Show diff between loaded and running
commit

Rollback

1
2
3
4
show system commit log         # List commit history with timestamps
rollback 2                     # Roll back to 2 commits ago
commit
save

Operational Diagnostics

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Connectivity
ping 8.8.8.8                          # ICMP ping
ping 8.8.8.8 count 100 size 1400      # Ping with count and packet size
traceroute 8.8.8.8                    # Traceroute
mtr 8.8.8.8                          # Combined ping + traceroute

# Interface and routing
show interfaces                       # All interface state
show ip route                         # Routing table
show ip route summary                 # Route count by protocol
show arp                              # ARP table
show ipv6 neighbors                   # IPv6 NDP table

# Packet capture
tcpdump interface eth0                # Capture on eth0
tcpdump interface eth0 filter 'host 8.8.8.8 and tcp port 443'

# Flow information
show ip bgp summary                   # BGP peer summary
show ip ospf neighbor                 # OSPF adjacency table
show vpn ipsec sa                     # IPsec tunnels
show nat source translations          # Active NAT sessions
show conntrack table ipv4             # Firewall state table
show firewall name LAN-WAN statistics # Firewall rule hit counts

Common Issues and Solutions

Problem Cause Solution
Config change has no effect Not committed Run commit
Config lost after reboot Not saved Run save after commit
Routing not working Missing or wrong default route show ip route — check for 0.0.0.0/0
Firewall blocking legitimate traffic Rule order or missing return traffic rule Add state established enable + state related enable rule at top
BGP peer stuck in Active TCP 179 blocked or wrong remote-AS Check firewall; verify remote-as matches peer’s AS
OSPF adjacency stuck in Exstart MTU mismatch between routers set protocols ospf interface eth0 mtu-ignore
IPsec tunnel not establishing Pre-shared key mismatch or proposal mismatch Verify PSK and IKE/ESP proposals match on both ends
WireGuard peer not connecting Allowed-IPs mismatch Ensure allowed-ips covers the traffic you want to send
High CPU Route flap or BGP prefix storm Check show log and BGP peer stability

Quick Reference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Mode switching
configure          # Enter configuration mode
exit / exit discard

# Core config operations
set <path> <value>
delete <path>
compare
commit
save
rollback <n>

# Interface
set interfaces ethernet eth0 address '192.168.1.1/24'
set interfaces ethernet eth0 address 'dhcp'
set interfaces ethernet eth1 vif 10 address '10.10.10.1/24'

# Routing
set protocols static route 0.0.0.0/0 next-hop '1.2.3.4'
set protocols ospf area 0 network '10.0.0.0/24'
set protocols bgp system-as '65001'
set protocols bgp neighbor '1.2.3.4' remote-as '64512'

# Firewall
set firewall zone WAN interface 'eth0'
set firewall zone LAN interface 'eth1'
set firewall ipv4 name LAN-WAN rule 10 action 'accept'
set firewall zone WAN from LAN firewall name 'LAN-WAN'

# NAT
set nat source rule 100 outbound-interface name 'eth0'
set nat source rule 100 source address '192.168.1.0/24'
set nat source rule 100 translation address 'masquerade'

# VPN
set interfaces wireguard wg0 address '10.200.0.1/24'
set interfaces wireguard wg0 port '51820'

# Show commands
show interfaces
show ip route
show bgp summary
show ip ospf neighbor
show firewall
show nat source translations
show vpn ipsec sa

Conclusion

VyOS brings the structured, commit-based configuration model of enterprise routing platforms to an open-source, Debian-based foundation. Every feature — BGP, OSPF, IPsec, WireGuard, VRFs, zone firewalls — is configured through the same hierarchical CLI and behaves predictably across bare metal, virtual machines, and cloud instances.

The key discipline VyOS instils is infrastructure as configuration: every routing decision, firewall policy, and NAT rule is explicitly stated, versioned, and rollback-able. That mindset maps directly to Terraform, Ansible, and GitOps workflows — the same configuration file that runs on your lab VM can be committed to Git, reviewed, and promoted to production.

The natural progression from here is VyOS automation: using the HTTP API or Ansible’s vyos_config module to manage configurations programmatically, and integrating VyOS with BGP route reflectors, EVPN/VXLAN data centre fabrics, or SD-WAN overlays.

Additional Resources


This post is licensed under CC BY 4.0 by the author.