Skip to main content

VyOS Home Router — Configuration Documentation

Hostname: vyos-fw Domain: home.lab Timezone: Europe/Berlin VyOS Release: 2025.11


Table of Contents

  1. Network Overview
  2. Physical Interfaces
  3. VLANs & Bridge Interfaces
  4. IP Addressing & Subnets
  5. DHCP Server
  6. DNS Forwarding
  7. Static Host Mappings
  8. Firewall — Groups
  9. Firewall — Zone Policy
  10. Firewall — Named Rules
  11. NAT
  12. VPN — IPsec Site-to-Site
  13. Services
  14. System

Network Overview

Internet

│ eth1 (WAN) — 192.168.178.11/24
│ GW: 192.168.178.1 (Speedport)
┌───┴─────────────────────────────────────────────────┐
│ vyos-fw │
│ │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌──────────┐ │
│ │ eth0 │ │ eth2 │ │ eth3 │ │ eth4 │ │
│ │ Trunk │ │ Trunk │ │Proxmox │ │ AppleTV │ │
│ │ Switch │ │ AP │ │Internal│ │ │ │
│ └────────┘ └────────┘ └────────┘ └──────────┘ │
│ │
│ vti0 (10.255.255.2/30) — IPsec to VPS │
└─────────────────────────────────────────────────────┘

The router separates the home network into 8 security zones using VLANs and bridges, with a zone-based stateful firewall enforcing traffic policy between them. A site-to-site IPsec VPN connects to a remote VPS.

A secondary LTE uplink (Teltonika RUT240) is integrated via VLAN 99 on the eth0 trunk for automatic WAN failover — see LTE Failover (RUT240).


Physical Interfaces

InterfaceMACDescriptionAddress
eth0bc:24:11:4b:f2:93TRUNK to SwitchDHCP (WAN-facing trunk, carrier only)
eth1bc:24:11:d1:b1:14WAN — Speedport192.168.178.11/24
eth2bc:24:11:cd:af:6bTRUNK to AP— (trunk only)
eth3bc:24:11:6c:81:0eProxmox Internalmember of br10
eth4AppleTVmember of br40
loLoopback

eth0 and eth2 have hardware offloads enabled: GRO, GSO, Scatter-Gather, TSO.


VLANs & Bridge Interfaces

ZoneVLAN IDBridgeMembersDescription
MGMT10br10eth0.10, eth2, eth3Management network
SERVERS20eth0.20Server network (no bridge)
HOMELAB30br30eth0.30, eth2.30Home Assistant / Homelab
TRUSTED40br40eth0.40, eth2.40, eth4Trusted devices + AppleTV
IOT50br50eth0.50, eth2.50IoT devices
GUEST60br60eth0.60, eth2.60Guest WiFi
DMZ70eth0.70Public-facing services (no bridge)
VPNvti0IPsec tunnel to VPS
WANeth1Primary uplink (Speedport DSL)
WAN-LTE99eth0.99Failover uplink (RUT240 LTE) — see LTE Failover

Notes:

  • br10, br40, br50, br60 have STP enabled.
  • eth2 (untagged) is a direct member of br10 — the AP's management interface lands on MGMT.
  • SERVERS and DMZ use the VLAN sub-interface directly (no bridge needed).

IP Addressing & Subnets

ZoneIPv4 SubnetGatewayIPv6 PrefixIPv6 Gateway
MGMT10.69.10.0/2410.69.10.1 (br10)
SERVERS10.69.20.0/2410.69.20.1 (eth0.20)
HOMELAB10.69.30.0/2410.69.30.1 (br30)fd00:69:30::/64fd00:69:30::1
TRUSTED10.69.40.0/2410.69.40.1 (br40)fd00:69:40::/64fd00:69:40::1
IOT10.69.50.0/2410.69.50.1 (br50)
GUEST10.69.60.0/2410.69.60.1 (br60)
DMZ10.69.70.0/2410.69.70.1 (eth0.70)
VPN tunnel10.255.255.0/30
VPN local end10.255.255.2

IPv6 Router Advertisements are sent on br40 (TRUSTED) and eth0.30 (HOMELAB). br30 also has IPv6 autoconf enabled.


DHCP Server

All zones use domain-name home.lab. Dynamic pools are .100–.200 unless noted.

ZoneSubnetRangeLeaseNotes
MGMT10.69.10.0/24.100–.20024h2 static mappings
SERVERS10.69.20.0/24.100–.20024h
HOMELAB10.69.30.0/24.100–.20024h2 static mappings
TRUSTED10.69.40.0/24.100–.20024h
IOT10.69.50.0/24.100–.20024h
GUEST10.69.60.0/24.100–.2001hShorter lease
DMZ10.69.70.0/24.100–.20024h

Static DHCP Mappings

HostMACIP
unifi-bridgebc:24:11:df:17:9810.69.10.15
unifi-U6d8:b3:70:d8:2b:cc10.69.10.16
HomeAssistantd8:5e:d3:6f:cb:b710.69.30.100
slzb-mr3u82:b5:4e:57:7f:f010.69.30.50
brother-ads2400nb4:22:00:22:b8:fe10.69.50.10

DNS Forwarding

  • Upstream resolver: 10.69.20.53 (Technitium LXC — forwards over DoT to Quad9 dns.quad9.net / 9.9.9.9:853 + 149.112.112.112:853, IPv4 only, with DNSSEC validation)
  • DNSSEC: set service dns forwarding dnssec validate — the router validates and propagates the ad (authenticated-data) flag to clients. Without validate the forwarder passes traffic but strips ad; validation still happens at Technitium either way (bogus names SERVFAIL end-to-end).
  • Cache size: 10,000 entries (router-side; Technitium has its own cache in addition)
  • Allowed clients: 10.69.0.0/16 (all internal zones)
  • Listen addresses: All zone gateways (.10.1, .20.1, .30.1, .40.1, .50.1, .60.1, .70.1)

Each zone's DHCP server points clients to the router's own IP as their DNS resolver. The router forwards to Technitium, which forwards encrypted to Quad9. Static host mappings (below) are resolved locally by the router before forwarding.

Router's own system name-server remains 1.1.1.1, 9.9.9.9 as a plain-DNS fallback for early-boot resolution (apt/NTP bootstrap) when the forwarder service is not yet running.


Static Host Mappings

The router resolves the following hostnames locally, overriding external DNS. Two patterns coexist:

  1. Shortnames → host IP — for direct SSH access (e.g. ssh podman from the laptop). Managed by Ansible from the homelab inventory; see Ansible — VyOS DNS sync.
  2. Service FQDNs (*.home.helix9.org) → Traefik (10.69.20.40) — internal split-horizon routing for HTTPS service URLs. Currently hand-curated; can be migrated host-by-host into Ansible via the traefik_subdomains host_var.

Ansible-managed shortnames (one entry per managed LXC/VM)

Generated automatically by playbooks/vyos_dns.yml from inventory/hosts.yml. Each managed host gets <inventory_hostname> → <ansible_host>.

GroupHosts (shortname → IP)
Proxmoxpve02 → 10.69.10.20
MGMTpbs01 → 10.69.10.25, unifi → 10.69.10.15
Serverspodman → 10.69.20.10, copyparty → 10.69.20.20, traefik → 10.69.20.40, technitium → 10.69.20.53, pulse → 10.69.20.60, authentik → 10.69.20.68, paperless → 10.69.20.72, uptime-kuma → 10.69.20.75, onedev → 10.69.20.76, docusaurus → 10.69.20.77, metrics → 10.69.20.78
DMZmumble → 10.69.70.10, minecraft → 10.69.70.20, synapse → 10.69.70.30, matrixrtc → 10.69.70.31, hookshot → 10.69.70.40, openclaw → 10.69.70.50

Service FQDNs → Traefik (hand-curated)

HostnameIPNotes
openclaw.helix9.org10.69.20.40via Traefik (split-horizon — external IP is 152.53.173.192)
traefik.home.helix9.org10.69.20.40Traefik reverse proxy
auth.home.helix9.org10.69.20.40via Traefik (Authentik)
dns.home.helix9.org10.69.20.40via Traefik → Technitium web UI
jellyfin.home.helix9.org10.69.20.40via Traefik
seerr.home.helix9.org10.69.20.40via Traefik
radarr.home.helix9.org10.69.20.40via Traefik
sonarr.home.helix9.org10.69.20.40via Traefik
sabnzbd.home.helix9.org10.69.20.40via Traefik
paperless.home.helix9.org10.69.20.40via Traefik
copyparty.home.helix9.org10.69.20.40via Traefik
pulse.home.helix9.org10.69.20.40via Traefik
pbs01.home.helix9.org10.69.20.40via Traefik
pve01.home.helix9.org / pve02.home.helix9.org10.69.20.40via Traefik
onedev.home.helix9.org10.69.20.40via Traefik

Legacy / manual (not Ansible-managed)

HostnameIPNotes
paperless.home.lab, pulse.home.lab, technitium.home.lab, podman.home.lab, pbs01.home.lab, pve01.home.lab, pve02.home.lab, onedev.home.labdirect host IPOlder home.lab aliases — superseded by Ansible-managed shortnames; safe to remove later
pve0110.69.10.5Currently commented in inventory — re-enable once added
netbox / netbox.home.lab10.69.20.70NetBox IPAM (not in Ansible inventory)
vyos-edge / vyos-edge.home.lab159.195.87.143VPS / remote VyOS

Firewall — Groups

Address Groups

GroupAddressPurpose
NETBOX10.69.20.10NetBox IPAM scanner
TRAEFIK10.69.20.40Traefik reverse proxy
PULSE10.69.20.60Pulse Proxmox monitoring
UPTIME-KUMA10.69.20.75Uptime-Kuma monitoring

Network Groups

GroupNetworksPurpose
BLOCKLIST192.0.2.1/32 (placeholder)Aggregated IP blocklist (auto-updated daily)
NET-MGMT10.69.10.0/24MGMT zone
NET-SERVERS10.69.20.0/24SERVERS zone
NET-HOMELAB10.69.30.0/24HOMELAB zone
NET-TRUSTED10.69.40.0/24TRUSTED zone
NET-IOT10.69.50.0/24IOT zone
NET-GUEST10.69.60.0/24GUEST zone
NET-DMZ10.69.70.0/24DMZ zone
RFC191810.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16All private ranges

Port Groups

GroupPortsService
SERVICES-DHCP67-68DHCP
SERVICES-DNS53DNS
SERVICES-MDNS5353mDNS
SERVICES-NTP123NTP

Firewall — Zone Policy

The firewall uses a zone-based model. Every interface belongs to exactly one zone. Traffic between zones is evaluated against the named firewall policy for that direction.

Zone Members

ZoneInterface(s)
LOCALRouter itself (local-zone)
WANeth1, eth0.99
MGMTbr10
SERVERSeth0.20
HOMELABbr30
TRUSTEDbr40
IOTbr50
GUESTbr60
DMZeth0.70
VPNvti0

Zone-to-Zone Policy Matrix

The table shows which firewall policy applies for traffic from (row) to (column). All zones have default-action drop.

FROM \ TOLOCALWANMGMTSERVERSHOMELABTRUSTEDIOTGUESTDMZVPN
LOCALALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALL
WANWAN-LOCALALLOW-ESTALLOW-ESTALLOW-ESTALLOW-ESTALLOW-ESTALLOW-ESTWAN-DMZ
MGMTMGMT-LOCALALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALLALLOW-ALL
SERVERSSERVERS-LOCALALLOW-INTERNETALLOW-ESTSERVERS-MGMTALLOW-ESTSERVERS-SCANSERVERS-SCANSERVERS-VPN
HOMELABHOMELAB-LOCALALLOW-INTERNETALLOW-ESTALLOW-ESTHOMELAB-TRUSTEDALLOW-ESTALLOW-ESTALLOW-EST
TRUSTEDTRUSTED-LOCALALLOW-ALLALLOW-ALLALLOW-ALLTRUSTED-HOMELABALLOW-ALLALLOW-ALLALLOW-ALL
IOTIOT-LOCALALLOW-INTERNETALLOW-ESTIOT-SERVERSALLOW-ESTALLOW-ESTALLOW-ESTALLOW-EST
GUESTGUEST-LOCALALLOW-INTERNETALLOW-ESTGUEST-SERVERSALLOW-ESTALLOW-ESTALLOW-ESTALLOW-EST
DMZDMZ-LOCALALLOW-INTERNETALLOW-ESTALLOW-ESTALLOW-ESTALLOW-ESTALLOW-ESTALLOW-ESTDMZ-VPN
VPNVPN-LOCALVPN-SERVERSVPN-DMZ

ALLOW-EST = ALLOW-ESTABLISHED (only return traffic, default drop)


Firewall — Named Rules

Generic Policies

ALLOW-ALL — default accept

  • Rule 10: accept established/related
  • Rule 20: drop invalid
  • Default: accept

ALLOW-ESTABLISHED — default drop

  • Rule 10: accept established/related
  • Rule 20: drop invalid
  • Default: drop

ALLOW-INTERNET — default accept (with RFC1918 block)

  • Rule 10: accept established/related
  • Rule 20: drop invalid
  • Rule 25: drop source 10.69.50.10 (brother-ads2400n — no internet access)
  • Rule 30: drop destinations matching RFC1918 (prevents cross-zone pivot via internet policy)
  • Default: accept

DROP-ALL — default drop

  • Rule 10: accept established/related
  • Rule 20: drop invalid
  • Default: drop

Zone-to-LOCAL Policies

These control what internal zones can access on the router itself.

MGMT-LOCAL — default accept

Full access. MGMT is fully trusted for router management.

TRUSTED-LOCAL — default accept

Full access. TRUSTED devices can reach all router services.

SERVERS-LOCAL — default drop

RuleActionDescription
10acceptEstablished/related
20dropInvalid
100acceptDNS (TCP/UDP 53)
110acceptDHCP (UDP 67–68)
120acceptNTP (UDP 123)

HOMELAB-LOCAL — default drop

RuleActionDescription
10acceptEstablished/related
20dropInvalid
100acceptDNS
110acceptDHCP
120acceptNTP
130acceptmDNS (UDP 5353)

IOT-LOCAL — default drop

Same as SERVERS-LOCAL (DNS, DHCP, NTP only).

GUEST-LOCAL — default drop

Same as SERVERS-LOCAL (DNS, DHCP, NTP only).

DMZ-LOCAL — default drop

Same as SERVERS-LOCAL (DNS, DHCP, NTP only).

VPN-LOCAL — default drop

RuleActionDescription
10acceptEstablished/related
20acceptICMP (ping)
30acceptAll traffic from VPN tunnel

Full access from VPN — the remote VPS side is fully trusted for router access.

WAN-LOCAL — default drop

RuleActionDescription
10acceptEstablished/related
20dropInvalid

No unsolicited inbound from WAN.


Cross-Zone Specific Policies

SERVERS-MGMT — default drop

Allows Traefik (10.69.20.40) and Pulse (10.69.20.60) to access management UIs:

RuleActionSourceDestinationPortDescription
10acceptEstablished/related
20dropInvalid
100acceptTRAEFIK8006/TCPTraefik → Proxmox Web UI
110acceptTRAEFIK443/TCPTraefik → MGMT HTTPS
120acceptTRAEFIK8007/TCPTraefik → PBS Web UI
130acceptPULSE10.69.10.208006/TCPPulse → pve02 API
140acceptPULSE10.69.10.258007/TCPPulse → pbs01 API
150acceptPULSE10.69.10.58006/TCPPulse → pve01 API

SERVERS-SCAN — default drop

Allows NetBox (10.69.20.10) to scan/poll other zones, and Pulse to send webhooks to DMZ:

RuleActionSourceDestinationPortDescription
100acceptNETBOXNetBox ICMP (ping scanning)
110acceptNETBOX161/UDPNetBox SNMP polling
120acceptNETBOX22/TCPNetBox SSH
130acceptNETBOX443/TCPNetBox HTTPS
140acceptNETBOX80/TCPNetBox HTTP
150acceptPULSE10.69.70.409000/TCPPulse webhook → hookshot
155acceptUPTIME-KUMA10.69.70.409000/TCPUptime-Kuma webhook → hookshot
160acceptTRAEFIK10.69.70.5018789/TCPTraefik → openclaw gateway
170acceptUPTIME-KUMA10.69.70.1064738/TCP+UDPUptime-Kuma → mumble (gamedig queries over UDP)
180acceptUPTIME-KUMA10.69.70.2025565/TCPUptime-Kuma → minecraft
190acceptUPTIME-KUMA10.69.70.30443,8448/TCPUptime-Kuma → synapse
195acceptUPTIME-KUMAICMPUptime-Kuma ICMP scan DMZ
200accept10.69.20.78 (metrics)9100/TCPPrometheus node_exporter scrape
210accept10.69.20.78 (metrics)10.69.70.409000/TCPAlertmanager → hookshot
250acceptTRAEFIK10.69.70.308008,8088/TCPTraefik → synapse + element-web
260acceptTRAEFIK10.69.70.318080,7880/TCPTraefik → matrixrtc (lk-jwt + livekit)

SERVERS-VPN — default drop

RuleActionDescription
20acceptSERVERS (10.69.20.0/24) → VPN tunnel (10.255.255.0/30)

VPN-SERVERS — default drop

RuleActionDescription
20acceptHTTP/HTTPS (TCP 80,443) to Traefik
30acceptVPS → Traefik 10.69.20.40 TCP 443,8448 (matrix client + federation)

VPN-DMZ — default drop

Specific services reachable from VPS via VPN:

RuleActionDestinationPortService
100accept10.69.70.1064738 TCP/UDPMumble
110accept10.69.70.2025565 TCPMinecraft

Matrix traffic (formerly rules 120/130/140 → 10.69.70.30) now enters Traefik via VPN-SERVERS rule 30. See Matrix Homeserver.

GUEST-SERVERS — default drop

Allows guest clients to reach the Technitium block page when DNS blocking is active:

RuleActionSourceDestinationPortDescription
10acceptEstablished/related
20dropInvalid
100accept10.69.20.5380,443/TCPTechnitium block page

IOT-SERVERS — default drop

Replaces ALLOW-EST for IOT→SERVERS to permit scanner access to copyparty:

RuleActionSourceDestinationPortDescription
10acceptEstablished/related
20dropInvalid
100accept10.69.50.1010.69.20.7222/TCPScanner SFTP to paperless

DMZ-VPN — default drop

Only established/related traffic from DMZ back into VPN.

WAN-DMZ — default drop

RuleActionDestinationPortDescription
10acceptEstablished/related
20dropInvalid
200accept10.69.70.3150000-60000/UDPLiveKit media → matrixrtc
210accept10.69.70.317881/TCPLiveKit ICE/TCP fallback → matrixrtc

Unsolicited inbound from WAN to DMZ is otherwise dropped. Rules 200/210 are the only home-line ingress on the box — they pair with the pppoe0 destination NAT (see NAT) to deliver Element Call media directly over the home line (79.246.151.97), bypassing the VPS. See MatrixRTC backend.

TRUSTED-HOMELAB — default accept

Full access from TRUSTED into HOMELAB.

HOMELAB-TRUSTED — default drop

RuleActionDescription
10acceptEstablished/related
100acceptmDNS to 224.0.0.251:5353 (UDP)

HOMELAB can only reply and send mDNS multicast into TRUSTED.


Global Forward/Input Filter

Applied to all forwarded and router-destined traffic before zone rules:

  • Forward rule 5: Drop sources matching BLOCKLIST
  • Forward rule 15: MSS clamp TCP SYN packets going out vti0 to 1360 bytes (VPN MTU compensation)
  • Forward rule 100/110: Accept all traffic in/out of vti0
  • Input rule 5: Drop sources matching BLOCKLIST

NAT

Source NAT (masquerade)

Single masquerade rule for all outbound traffic:

RuleSourceInterfaceTranslation
10010.69.0.0/16eth1 (WAN)masquerade

All internal subnets share the WAN IP for internet access.

Destination NAT (pppoe0 inbound)

The home line normally has no inbound DNAT (all ingress goes via the VPS). The sole exception is Element Call media, forwarded directly over the home line for call quality:

RuleProtoDest portTranslationDescription
200UDP50000-6000010.69.70.31LiveKit media → matrixrtc
210TCP788110.69.70.31LiveKit ICE/TCP fallback → matrixrtc

Paired with WAN-DMZ rules 200/210. See MatrixRTC backend.


VPN — IPsec Site-to-Site

Connects home router (vyos-fw) to the VPS (vyos-edge) over IKEv2.

ParameterHomeVPS
Local IDhome.helix9.orgvps.helix9.org
Public IP192.168.178.11 (behind NAT)159.195.87.143
Tunnel IP10.255.255.2/3010.255.255.1/30
Interfaceeth1
VTIvti0

IKE Profile (IKE-VPS)

SettingValue
VersionIKEv2
EncryptionAES-256
HashSHA-256
DH Group14 (2048-bit MODP)
Lifetime28800s (8h)
DPD actionrestart
DPD interval30s / timeout 120s
Close actionnone

ESP Profile (ESP-VPS)

SettingValue
EncryptionAES-256
HashSHA-256
PFSDH Group 14
Lifetime3600s (1h)

Authentication: Pre-shared key (PSK ID: helix9). Connection type: initiate — home router always initiates. MTU on vti0: 1400 bytes (with MSS clamp to 1360 in forward firewall).


Services

SSH

  • Listen: 10.69.10.1 (MGMT), 10.69.40.1 (TRUSTED) only
  • Port: 22
  • Password auth: disabled
  • Auth method: Public key only
  • Key: sk-ssh-ed25519@openssh.com (YubiKey hardware-backed)

mDNS Repeater

Bridges mDNS between br30 (HOMELAB) and br40 (TRUSTED), allowing service discovery between Home Assistant devices and trusted clients.

NTP

Clients allowed: All RFC1918 ranges + 10.69.0.0/16. Upstream servers:

  • time.cloudflare.com
  • time1.vyos.net, time2.vyos.net, time3.vyos.net

Blocklist Auto-Update

A scheduled task runs daily to update the BLOCKLIST network group:

  • Script: /opt/vyos-blocklist/update-blocklists.sh
  • Interval: 1 day
  • Effect: Dropped at forward and input filter before zone rules are evaluated

System

SettingValue
Hostnamevyos-fw
Domainhome.lab
TimezoneEurope/Berlin
ConsolettyS0 at 115200 baud
Config revisions kept100
Reboot on upgrade failureafter 5 minutes
Upstream DNS (system)1.1.1.1, 9.9.9.9
Sysloglocal, all facilities at info; local7 at debug

Login

Two users:

  • vyos — primary admin
    • Password authentication (encrypted, stored)
    • YubiKey SSH public key (sk-ssh-ed25519@openssh.com)
    • Password login over SSH disabled (key-only)
  • ansible — automation user used by the vyos_dns Ansible role
    • SSH key only (ed25519 from pve02:/root/.ssh/id_ed25519_ansible.pub)
    • VyOS 1.4+ grants login users sudo + vyattacfg automatically (no level admin needed)
    • Reachable from MGMT (10.69.10.0/24) → TRUSTED (10.69.40.1) per zone policy