VyOS BGP Configuration on a VPS: Dual-Stack Tutorial

12 min read·Matthieu·IP TransitIPv6NetworkingVyOSBGP|

Configure BGP on a VyOS instance running on a VPS to announce your own IPv4 and IPv6 prefixes. Covers prefix-lists, route-maps, session security, and external verification.

Network engineers who work with Junos or IOS daily know the pain of editing flat config files for BIRD2 or FRR. VyOS gives you a proper router CLI on a VPS: hierarchical config, commit/rollback, tab completion. This tutorial walks through a full BGP setup on a Virtua Cloud VPS running VyOS, from interface config to verified dual-stack prefix announcement.

By the end, you will have IPv4 and IPv6 prefixes announced via BGP with prefix-lists, route-maps, MD5 authentication, GTSM, and max-prefix limits in place.

BGP and Bring Your Own IP on a VPS: The Complete Guide

Prerequisites

Before starting, you need:

  1. An ASN registered with a RIR (RIPE NCC, ARIN, APNIC). How to Register an ASN with RIPE NCC
  2. At least one IPv4 /24 and/or IPv6 /48 prefix assigned to your ASN.
  3. Valid ROA objects published in RPKI for each prefix. RPKI ROA Setup for BGP: Create ROAs, Validate Routes in BIRD2 and FRR
  4. A Virtua Cloud VPS with VyOS installed. Order a VPS with the ISO image option, mount the VyOS ISO, and complete the install (install image from the live system). Reboot, unmount the ISO, and you have a persistent VyOS instance.
  5. A BGP session provisioned by your upstream provider. You need: their ASN, the peering IPv4/IPv6 addresses, and the MD5 password (if set).

Throughout this tutorial, we use these placeholder values. Replace them with your own:

Parameter Placeholder Description
Your ASN 64512 Your autonomous system number
Router ID 198.51.100.10 Usually your primary IPv4 address
Upstream ASN 64501 Your provider's AS number
Upstream IPv4 198.51.100.1 Provider's peering IPv4
Your peering IPv4 198.51.100.10 Your side of the point-to-point link
Upstream IPv6 2001:db8::1 Provider's peering IPv6
Your peering IPv6 2001:db8::10 Your side of the IPv6 peering link
Your IPv4 prefix 203.0.113.0/24 The prefix you will announce
Your IPv6 prefix 2001:db8:1000::/48 The IPv6 prefix you will announce
MD5 password (from provider) Shared secret for TCP MD5

How do I access and prepare VyOS on a VPS?

After provisioning, SSH into the VyOS instance. VyOS drops you into an operational mode shell. To make configuration changes, enter configuration mode:

ssh vyos@198.51.100.10
configure

The prompt changes from $ to #, indicating you are in configuration mode. Every set command stages a change. Nothing takes effect until you run commit.

Verify the interface

Check that your network interface has the correct addresses assigned. On a Virtua VPS, the primary interface is typically eth0:

show interfaces ethernet eth0

If your peering addresses are not yet configured (some providers use a separate /30 or /31 for the point-to-point link), add them:

set interfaces ethernet eth0 address 198.51.100.10/24
set interfaces ethernet eth0 address 2001:db8::10/64

How do I set up a BGP session on VyOS?

VyOS BGP configuration starts with set protocols bgp. In VyOS 1.4+ (Sagitta), the AS number is set with system-as, not the deprecated set protocols bgp <ASN> format from older releases.

Set your AS number and router ID:

set protocols bgp system-as 64512
set protocols bgp parameters router-id 198.51.100.10

Configure the IPv4 neighbor

set protocols bgp neighbor 198.51.100.1 remote-as 64501
set protocols bgp neighbor 198.51.100.1 description 'Upstream-v4'
set protocols bgp neighbor 198.51.100.1 update-source 198.51.100.10

Configure the IPv6 neighbor

If your provider peers IPv6 over a separate address (common), add a second neighbor block:

set protocols bgp neighbor 2001:db8::1 remote-as 64501
set protocols bgp neighbor 2001:db8::1 description 'Upstream-v6'
set protocols bgp neighbor 2001:db8::1 update-source 2001:db8::10
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast

For the IPv4 neighbor, enable the ipv4-unicast address family explicitly:

set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast

How do I announce IPv4 and IPv6 prefixes on VyOS?

To announce a prefix via BGP, two things are required: a network statement under the correct address family, and the prefix must exist in the routing table. The standard approach is to create a static blackhole route (null route) for each prefix.

Create blackhole routes

set protocols static route 203.0.113.0/24 blackhole
set protocols static route6 2001:db8:1000::/48 blackhole

These routes ensure the prefix is always present in the routing table, even when no more-specific routes exist.

Add network statements

set protocols bgp address-family ipv4-unicast network 203.0.113.0/24
set protocols bgp address-family ipv6-unicast network 2001:db8:1000::/48

The network command tells BGP to originate these prefixes. Without the matching blackhole route, BGP will not advertise the prefix.

How do I filter BGP routes with prefix-lists and route-maps on VyOS?

Running BGP without filters is negligent. You should filter both outbound (only announce what you own) and inbound (limit what you accept from the upstream). VyOS uses prefix-list for IPv4 and prefix-list6 for IPv6. This is a common pitfall: using prefix-list with an IPv6 prefix silently fails.

Outbound prefix-lists

Create a prefix-list that permits only your prefixes:

set policy prefix-list EXPORT4 rule 10 action permit
set policy prefix-list EXPORT4 rule 10 prefix 203.0.113.0/24

set policy prefix-list6 EXPORT6 rule 10 action permit
set policy prefix-list6 EXPORT6 rule 10 prefix 2001:db8:1000::/48

An implicit deny-all exists at the end of every prefix-list. Only explicitly permitted prefixes pass.

Inbound prefix-lists

Limit inbound routes to prevent your upstream from flooding your table with a full feed (if you did not request one) or leaking garbage:

set policy prefix-list IMPORT4 rule 10 action permit
set policy prefix-list IMPORT4 rule 10 prefix 0.0.0.0/0
set policy prefix-list IMPORT4 rule 10 le 24

set policy prefix-list6 IMPORT6 rule 10 action permit
set policy prefix-list6 IMPORT6 rule 10 prefix ::/0
set policy prefix-list6 IMPORT6 rule 10 le 48

This accepts any IPv4 prefix up to /24 and any IPv6 prefix up to /48. Adjust le values based on your needs. If you only want a default route, remove the le line and set the prefix to 0.0.0.0/0 or ::/0 with exact match.

Route-maps

Route-maps tie prefix-lists to neighbor sessions:

set policy route-map UPSTREAM-OUT4 rule 10 action permit
set policy route-map UPSTREAM-OUT4 rule 10 match ip address prefix-list EXPORT4

set policy route-map UPSTREAM-OUT6 rule 10 action permit
set policy route-map UPSTREAM-OUT6 rule 10 match ipv6 address prefix-list EXPORT6

set policy route-map UPSTREAM-IN4 rule 10 action permit
set policy route-map UPSTREAM-IN4 rule 10 match ip address prefix-list IMPORT4

set policy route-map UPSTREAM-IN6 rule 10 action permit
set policy route-map UPSTREAM-IN6 rule 10 match ipv6 address prefix-list IMPORT6

Apply route-maps to neighbors

set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map export UPSTREAM-OUT4
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map import UPSTREAM-IN4

set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast route-map export UPSTREAM-OUT6
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast route-map import UPSTREAM-IN6

How do I secure a VyOS BGP session?

Four mechanisms harden a BGP session: TCP MD5 authentication, GTSM (TTL security), maximum prefix limits, and the ebgp-requires-policy setting. Most competitors cover zero of these. All four should be on by default.

MD5 authentication

MD5 (RFC 2385) signs each TCP segment. It does not encrypt traffic but prevents spoofed TCP resets and session hijacks:

set protocols bgp neighbor 198.51.100.1 password 'your-md5-secret'
set protocols bgp neighbor 2001:db8::1 password 'your-md5-secret'

Both sides must use the same password. Get it from your upstream provider during session provisioning.

GTSM (Generalized TTL Security Mechanism)

GTSM (RFC 5082) rejects BGP packets with a TTL lower than expected. For directly connected eBGP peers, set hops to 1:

set protocols bgp neighbor 198.51.100.1 ttl-security hops 1
set protocols bgp neighbor 2001:db8::1 ttl-security hops 1

This drops any BGP packet that traversed more than 1 hop, blocking remote spoofing attempts. GTSM is mutually exclusive with ebgp-multihop. Do not use both on the same neighbor.

Maximum prefix limits

Protect your routing table from a peer accidentally sending a full table (900k+ IPv4 prefixes) or a route leak:

set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast maximum-prefix 10000
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast maximum-prefix 5000

The session tears down if the peer exceeds this limit. Set values based on what you expect to receive. For a single upstream with a default route, 10 is enough. For a full table, 1000000.

Enforce eBGP policy

VyOS disables RFC 8212 enforcement by default for backward compatibility. Enable it so BGP refuses to send or accept routes without an explicit policy:

set protocols bgp parameters ebgp-requires-policy

With this enabled, a neighbor without a route-map applied will not exchange any routes. This prevents accidental route leaks if you add a new peer and forget filters.

How do I configure the VyOS firewall for BGP?

BGP runs on TCP port 179. If you run a VyOS firewall (and you should), allow BGP traffic from your upstream's peering addresses only.

IPv4 firewall rules

set firewall ipv4 input filter rule 20 action accept
set firewall ipv4 input filter rule 20 protocol tcp
set firewall ipv4 input filter rule 20 destination port 179
set firewall ipv4 input filter rule 20 source address 198.51.100.1
set firewall ipv4 input filter rule 20 description 'BGP from upstream v4'

set firewall ipv4 input filter rule 21 action accept
set firewall ipv4 input filter rule 21 protocol tcp
set firewall ipv4 input filter rule 21 source port 179
set firewall ipv4 input filter rule 21 source address 198.51.100.1
set firewall ipv4 input filter rule 21 description 'BGP return from upstream v4'

IPv6 firewall rules

set firewall ipv6 input filter rule 20 action accept
set firewall ipv6 input filter rule 20 protocol tcp
set firewall ipv6 input filter rule 20 destination port 179
set firewall ipv6 input filter rule 20 source address 2001:db8::1
set firewall ipv6 input filter rule 20 description 'BGP from upstream v6'

set firewall ipv6 input filter rule 21 action accept
set firewall ipv6 input filter rule 21 protocol tcp
set firewall ipv6 input filter rule 21 source port 179
set firewall ipv6 input filter rule 21 source address 2001:db8::1
set firewall ipv6 input filter rule 21 description 'BGP return from upstream v6'

Rule 21 handles return traffic when the remote side initiates the TCP connection on source port 179. If you have established/related connection tracking enabled in your firewall, rule 21 may be unnecessary. Include it to be safe.

Commit, save, and the VyOS config workflow

VyOS uses a two-stage workflow. commit activates the staged changes in the running config. save writes the running config to disk so it persists across reboots. Forgetting save means a reboot wipes your changes.

commit

If commit succeeds with no errors, save:

save

Expected output:

Saving configuration to '/config/config.boot'...
Done

If commit fails, VyOS shows the error and rolls back. Read the error. Common causes: typos in IP addresses, conflicting options (like ttl-security and ebgp-multihop on the same neighbor), or referencing a prefix-list that does not exist.

To review your staged changes before committing:

compare

This shows a diff between the running config and your pending changes. To discard uncommitted changes:

discard

To roll back to a previous commit:

rollback 1
commit
save

How do I verify my BGP announcements are visible?

Verification happens in two stages: local (on the VyOS instance) and external (from the internet). Exit configuration mode first:

exit

Local verification

Check session status for both address families:

show bgp ipv4 summary

Expected output:

IPv4 Unicast Summary:
BGP router identifier 198.51.100.10, local AS number 64512 vrf-id 0
BGP table version 3
RIB entries 5, using 960 bytes of memory
Peers 1, using 725 KiB of memory

Neighbor         V   AS   MsgRcvd  MsgSent  TblVer  InQ OutQ  Up/Down State/PfxRcd
198.51.100.1     4  64501     142      138       0    0    0 01:15:23            2

The State/PfxRcd column shows a number (prefixes received) when the session is established. If it shows Active, Connect, or OpenSent, the session is not up. See the troubleshooting section.

show bgp ipv6 summary

Verify you are advertising the correct prefixes:

show bgp ipv4 neighbors 198.51.100.1 advertised-routes

Expected output includes your 203.0.113.0/24 prefix. If it is missing, check your network statement and outbound route-map.

show bgp ipv6 neighbors 2001:db8::1 advertised-routes

Verification commands reference

Command What it shows
show bgp ipv4 summary Session state, prefixes received per peer
show bgp ipv6 summary Same for IPv6
show bgp ipv4 neighbors <ip> advertised-routes Prefixes you are sending
show bgp ipv4 neighbors <ip> received-routes Prefixes received from peer
show bgp ipv4 neighbors <ip> Full neighbor detail (timers, capabilities, counters)
show ip route bgp BGP routes installed in the routing table
show bgp ipv4 Full IPv4 BGP table

External verification

Local checks only confirm what your router thinks. Verify from the internet that your prefixes are actually propagating.

bgp.tools: Open https://bgp.tools/prefix/203.0.113.0/24 in a browser. It shows which ASes see the prefix, the AS path, and any RPKI validation status. If the prefix does not appear, wait 5-10 minutes for propagation and recheck.

RIPE Stat: Open https://stat.ripe.net/203.0.113.0/24 for routing status, visibility across route collectors, and RPKI validation state.

Looking glass: Many transit providers offer looking glass tools. Query your upstream's looking glass to confirm they see your announcement.

If your prefix shows RPKI-invalid on bgp.tools, your ROA is wrong. Fix it in the RIPE portal before continuing. RPKI ROA Setup for BGP: Create ROAs, Validate Routes in BIRD2 and FRR

VyOS CLI vs BIRD2 vs FRR: quick comparison

All three can run BGP on a Linux VPS. The choice depends on your workflow preference.

Task VyOS CLI BIRD2 config file FRR vtysh
Set AS number set protocols bgp system-as 64512 protocol bgp { local 64512 as 64512; } router bgp 64512
Add neighbor set protocols bgp neighbor 1.2.3.4 remote-as 64501 neighbor 1.2.3.4 as 64501; inside protocol block neighbor 1.2.3.4 remote-as 64501
Announce prefix set protocols bgp address-family ipv4-unicast network 203.0.113.0/24 protocol static { route 203.0.113.0/24 blackhole; } + export filter network 203.0.113.0/24
Prefix-list set policy prefix-list NAME rule 10 ... define PFXLIST = [ 203.0.113.0/24 ]; ip prefix-list NAME permit ...
Apply changes commit / save birdc configure write memory
Rollback rollback N + commit Restore backup config file No built-in rollback
Config format Hierarchical CLI Custom DSL (C-like) IOS-like CLI
Underlying daemon FRR (bundled) BIRD FRR

VyOS bundles FRR internally but wraps it in a commit/rollback workflow. If you want atomic config changes and rollback without writing scripts, VyOS is the right choice. If you want maximum control over filter logic, BIRD2 gives you a full programming language. BIRD2 BGP Configuration on a Linux VPS FRRouting BGP Configuration on a Linux VPS

What are common VyOS BGP troubleshooting steps?

When a session does not come up or prefixes are not visible, work through these checks systematically.

Symptom Likely cause Fix
State stuck on Active TCP connection failing. Firewall blocking port 179, wrong neighbor IP, or the remote side is not configured. Check firewall rules. Verify neighbor IP matches what the upstream configured. Try ping to the peer address.
State stuck on OpenSent TCP connects but BGP OPEN is rejected. AS number mismatch or capability negotiation failure. Verify system-as matches what the upstream expects. Check show bgp ipv4 neighbors <ip> for "Notification received".
State stuck on OpenConfirm MD5 password mismatch. TCP connects (SYN/ACK works without MD5 check) but BGP messages fail authentication. Confirm the password matches on both sides. MD5 is case-sensitive.
Session established but 0 prefixes received Upstream is not sending routes, or your inbound route-map is denying everything. Check show bgp ipv4 neighbors <ip> received-routes. If empty, ask your upstream. If routes show there but not in the table, check your import route-map.
Your prefix not visible externally Outbound route-map blocking, missing network statement, or no blackhole route. Run show bgp ipv4 neighbors <ip> advertised-routes. If the prefix is missing, check the outbound route-map and network statement. Verify the blackhole route exists with show ip route 203.0.113.0/24.
RPKI Invalid on bgp.tools ROA mismatch. The origin AS or max-length in the ROA does not match your announcement. Fix the ROA in the RIPE portal. Ensure the origin AS matches system-as and max-length covers /24.
Session flapping MTU issues, unstable link, or max-prefix limit hit. Check show log for BGP messages. If max-prefix triggered, increase the limit or investigate why the peer is sending excess routes.

Read the logs

VyOS logs BGP events through the system journal:

show log | match bgp

For real-time monitoring:

monitor log | match bgp

On the underlying system (if you need more detail):

journalctl -u frr -f

This tails the FRR daemon logs directly. Look for NOTIFICATION messages, which contain the BGP error code and subcode.

Complete configuration reference

Here is the full configuration block for reference. Copy, replace placeholder values, paste into configuration mode, commit, and save:

# Enter configuration mode
configure

# BGP core
set protocols bgp system-as 64512
set protocols bgp parameters router-id 198.51.100.10
set protocols bgp parameters ebgp-requires-policy

# Blackhole routes for prefix origination
set protocols static route 203.0.113.0/24 blackhole
set protocols static route6 2001:db8:1000::/48 blackhole

# Network statements
set protocols bgp address-family ipv4-unicast network 203.0.113.0/24
set protocols bgp address-family ipv6-unicast network 2001:db8:1000::/48

# IPv4 neighbor
set protocols bgp neighbor 198.51.100.1 remote-as 64501
set protocols bgp neighbor 198.51.100.1 description 'Upstream-v4'
set protocols bgp neighbor 198.51.100.1 update-source 198.51.100.10
set protocols bgp neighbor 198.51.100.1 password 'your-md5-secret'
set protocols bgp neighbor 198.51.100.1 ttl-security hops 1
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast maximum-prefix 10000
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map export UPSTREAM-OUT4
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map import UPSTREAM-IN4

# IPv6 neighbor
set protocols bgp neighbor 2001:db8::1 remote-as 64501
set protocols bgp neighbor 2001:db8::1 description 'Upstream-v6'
set protocols bgp neighbor 2001:db8::1 update-source 2001:db8::10
set protocols bgp neighbor 2001:db8::1 password 'your-md5-secret'
set protocols bgp neighbor 2001:db8::1 ttl-security hops 1
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast maximum-prefix 5000
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast route-map export UPSTREAM-OUT6
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast route-map import UPSTREAM-IN6

# Outbound prefix-lists (only announce what you own)
set policy prefix-list EXPORT4 rule 10 action permit
set policy prefix-list EXPORT4 rule 10 prefix 203.0.113.0/24
set policy prefix-list6 EXPORT6 rule 10 action permit
set policy prefix-list6 EXPORT6 rule 10 prefix 2001:db8:1000::/48

# Inbound prefix-lists
set policy prefix-list IMPORT4 rule 10 action permit
set policy prefix-list IMPORT4 rule 10 prefix 0.0.0.0/0
set policy prefix-list IMPORT4 rule 10 le 24
set policy prefix-list6 IMPORT6 rule 10 action permit
set policy prefix-list6 IMPORT6 rule 10 prefix ::/0
set policy prefix-list6 IMPORT6 rule 10 le 48

# Route-maps
set policy route-map UPSTREAM-OUT4 rule 10 action permit
set policy route-map UPSTREAM-OUT4 rule 10 match ip address prefix-list EXPORT4
set policy route-map UPSTREAM-OUT6 rule 10 action permit
set policy route-map UPSTREAM-OUT6 rule 10 match ipv6 address prefix-list EXPORT6
set policy route-map UPSTREAM-IN4 rule 10 action permit
set policy route-map UPSTREAM-IN4 rule 10 match ip address prefix-list IMPORT4
set policy route-map UPSTREAM-IN6 rule 10 action permit
set policy route-map UPSTREAM-IN6 rule 10 match ipv6 address prefix-list IMPORT6

# Firewall - allow BGP from upstream only
set firewall ipv4 input filter rule 20 action accept
set firewall ipv4 input filter rule 20 protocol tcp
set firewall ipv4 input filter rule 20 destination port 179
set firewall ipv4 input filter rule 20 source address 198.51.100.1
set firewall ipv4 input filter rule 20 description 'BGP from upstream v4'
set firewall ipv6 input filter rule 20 action accept
set firewall ipv6 input filter rule 20 protocol tcp
set firewall ipv6 input filter rule 20 destination port 179
set firewall ipv6 input filter rule 20 source address 2001:db8::1
set firewall ipv6 input filter rule 20 description 'BGP from upstream v6'

# Apply
commit
save

Further reading


Copyright 2026 Virtua.Cloud. All rights reserved. This content is original work by the Virtua.Cloud team. Reproduction, republication, or redistribution without written permission is prohibited.