Skip to main content
RunBook Academy

VyOSLVI · Software Images and Production UpgradesUpgrades

FRR compatibility — what an FRR version bump changes on VyOS, and what it does not

Advanced⏱ ~24 minvyosvtyshshow versionshow configuration commandsadd system image

What you'll learn

  • Explain why the VyOS CLI, not FRR's own syntax, is the configuration surface an operator maintains
  • Read the FRR version an image actually carries, rather than inferring it from the VyOS release number
  • Describe what a VyOS config-migration script rewrites, when it runs, and the path that bypasses it
  • Name the three kinds of FRR change that are visible to an operator, only one of which a commit can catch
  • Run an upgrade capture-and-diff that surfaces a silently dropped configuration node

Prerequisites

Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-19

Not yet marked complete on this device.

VyOS 1.5 LTS runs FRRouting as its routing engine, and an image upgrade generally moves FRR forward with it. The natural worry is that an FRR release renames something and the router’s configuration stops being valid.

That worry is aimed at the wrong layer. On VyOS the operator does not write FRR configuration. The configuration surface is the VyOS tree — set protocols bgp neighbor ... — and the image renders that into FRR’s own syntax at commit time. When FRR changes its syntax, the change lands in the image’s rendering templates, which are shipped and tested together with the FRR version they target. It does not land in your config.boot.

What does change under an operator’s feet is a different and less obvious set of things. This lesson separates them: what migrates and when, what an FRR bump can still do to a working router, and the capture-and-diff procedure that catches a change no commit will ever complain about.

Two schemas, one upgrade

flowchart TB
  CB["/config/config.boot<br/>VyOS tree + config-version comment"] -->|"commit renders"| FRRC["FRR running-config<br/>router bgp 64512 / neighbor ..."]
  IMG["New image"] --> MIG["VyOS migration scripts<br/>run once, at first boot"]
  MIG -->|"rewrites"| CB
  IMG --> TPL["Rendering templates<br/>shipped with the image"]
  TPL --> FRRC
  FRRC --> DAEMON["bgpd / ospfd / staticd"]

Two schemas move during an upgrade, and they move by different mechanisms:

  • The VyOS configuration schema. This is the one you own. It is versioned per component, and it is migrated by scripts that ship in the new image and run once, against the stored configuration, on the first boot of that image.
  • FRR’s configuration schema. This is the one you do not own. It is bridged by the image’s rendering templates. An FRR rename is a change to those templates, and it arrives already done.

Confusing them produces the classic wrong question — “which FRR options do I need to rewrite before I upgrade?” The answer is none, and going looking for them wastes the change window that should have been spent on the capture-and-diff below.

Reading the FRR version an image actually carries

Do not infer it. The VyOS release number and the FRR version move on separate schedules, VyOS occasionally carries backported patches on top of an FRR release, and rolling images change more often than any table could track. Read it off the box:

Read-only / SafeThe routing engine's own statement of its version
vyos@vyos:~$ vtysh -c 'show version'
FRRouting 10.2 (vyos).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
configured with:
  '--build=x86_64-linux-gnu' ...

Illustrative output

Two commands, two answers, and you want both in the change record:

show version
vtysh -c 'show version'

The first is the VyOS image. The second is the routing engine inside it. When a routing behaviour changes after an upgrade and the vendor’s answer depends on which FRR you are on, the second command is the one that settles the argument.

What actually migrates: the VyOS tree

Every VyOS configuration file carries a trailing comment recording the schema version of each component:

// Warning: Do not remove the following line.
// vyos-config-version: "bgp@5:cluster@2:config-management@1:conntrack@6:..."
// Release version: 1.5.2

That line is the migration system’s input. Each component has an integer version; the image knows which version it expects; and for every gap between the stored version and the expected one, the image runs the corresponding migration script against the configuration. This happens once, on the first boot of the new image, before the configuration is committed.

The canonical example is the one this course keeps returning to. VyOS 1.4 restructured the BGP tree, so a configuration written on 1.3:

set protocols bgp 64512 neighbor 192.0.2.1 remote-as 64511
set protocols bgp 64512 neighbor 192.0.2.1 address-family ipv4-unicast soft-reconfiguration inbound
set protocols bgp 64512 network 10.0.0.0/24

is rewritten by the bgp migration script into the 1.4/1.5 form:

set protocols bgp system-as 64512
set protocols bgp neighbor 192.0.2.1 remote-as 64511
set protocols bgp neighbor 192.0.2.1 address-family ipv4-unicast soft-reconfiguration inbound
set protocols bgp address-family ipv4-unicast network 10.0.0.0/24

The operator did not type either the delete or the set. The migration did, at boot, and the bgp@N number in the config-version comment went up to record it.

The three FRR changes an operator does see

An FRR version bump is absorbed at the syntax layer. Three categories get through anyway, and they are ranked here by how likely they are to be noticed at the moment they happen.

1. A behaviour default changed

The configuration is byte-identical, the commit succeeds, and the router behaves differently. FRR’s enforcement of RFC 8212 is the best-known instance: an eBGP session with no inbound and outbound policy attached exchanges no prefixes at all, where an older implementation would have exchanged everything. The session comes up. The prefix counters stay at zero.

Nothing in the configuration is invalid, so nothing warns you. This category is caught only by comparing operational state before and after — prefix counts, neighbour counts, route counts — which is exactly what the capture step exists for.

Check what your own image renders rather than assuming a default: vtysh -c 'show running-config' prints the FRR configuration VyOS generated, including the policy-enforcement knobs it set on your behalf.

2. An output format changed

show ip bgp summary gains a column. A JSON key is renamed. A field that was a string becomes a number. The routing is perfect and the monitoring goes blind.

This is the most common real-world consequence of an FRR bump on a VyOS fleet, and it is invisible to every check that looks at the router. It shows up as an alert that stopped firing, or a dashboard that flatlined at zero, and it is often noticed days later. Anything that scrapes routing output — a Prometheus exporter, a Nagios check, an Ansible fact, a home-grown script parsing columns — is exposed.

The defence is to treat the tooling as part of the upgrade’s blast radius, and to run it against the upgraded lab box before the fleet.

3. A daemon or feature appeared or disappeared

FRR gains a daemon; VyOS may not expose it in the CLI yet, so it is present but unreachable from set. FRR removes or renames a feature; VyOS drops the corresponding node, and the migration deletes it from your configuration.

That second case is the one to watch, because a migration that deletes a node it cannot translate produces a router that commits cleanly and is missing a feature. There is no error. The only evidence is the difference between the configuration you had and the configuration you have.

The upgrade procedure that catches all three

The procedure is a capture, an upgrade, and a diff. The diff is the part that does the work, and it is worthless without the capture.

Before the upgrade

show configuration commands > /config/pre-upgrade-cli.txt
vtysh -c 'show running-config' > /config/pre-upgrade-frr.txt
show ip route summary > /config/pre-upgrade-routes.txt
show ip bgp summary > /config/pre-upgrade-bgp.txt
show ip ospf neighbor > /config/pre-upgrade-ospf.txt

Four of those five are operational state, and they are the baseline for category 1. The first is the configuration, and it is the baseline for category 3.

Copy them off the box as well. A capture that only exists on the router you are about to reboot is a capture you may not have when you need it.

The upgrade

add system image https://downloads.vyos.net/.../vyos-1.5.2-iso-amd64.iso
reboot

After the first boot

show configuration commands > /config/post-upgrade-cli.txt
vtysh -c 'show running-config' > /config/post-upgrade-frr.txt
show ip route summary
show ip bgp summary
show ip ospf neighbor

Then compare, in this order:

  1. The CLI diffdiff /config/pre-upgrade-cli.txt /config/post-upgrade-cli.txt from the shell. Every line the migration rewrote appears here, and so does every line it deleted. Expect changes; the BGP restructure is a large and entirely legitimate diff. What you are looking for is a node that vanished with nothing appearing in its place.
  2. The FRR diff — the same comparison against the rendered FRR configuration. This is where a changed default shows up as a line VyOS now emits, or no longer emits, without your configuration having changed.
  3. The operational counts — neighbours established, prefixes received, routes installed. A prefix count that dropped to zero on a session that is Established is category 1 announcing itself.
  4. The tooling — run the monitoring checks and the automation against the upgraded box before you decide the upgrade succeeded.

Failure modes

A configuration node disappeared in the migration

The upgrade completes, everything commits, and a feature is gone. The migration script encountered a node it had no forward translation for and removed it.

Diagnostic: the CLI diff. This failure has no other symptom until the missing feature is needed.

Fix: re-express the feature in the new schema by hand, if it still exists; if it does not, this is a design change, not a repair, and it belongs in the change record as one.

The session is up and no prefixes are moving

show ip bgp summary shows Established and a prefix count of zero where the baseline showed thousands. The configuration did not change.

Diagnostic: compare the rendered FRR configuration against the pre-upgrade capture, and check whether the session has an inbound and an outbound policy attached. A policy-enforcement default that changed between FRR versions presents exactly like this.

Fix: attach the policies the peer relationship should have had all along. Reaching for a knob that disables the enforcement is the tempting move and the wrong one — a policy-free eBGP session is a route leak waiting for its moment.

Monitoring went quiet after a successful upgrade

Alerts stopped firing; graphs flatlined. The router is healthy.

Diagnostic: run the check by hand against the upgraded box and read its output. A parser that expects a column position or a JSON key that moved fails silently far more often than it errors.

Fix: update the check, and add the check itself to the upgrade validation so the next bump catches it in the lab.

The rollback configuration will not load

The operator saved the configuration after the upgrade, then tried to load that file onto the previous image. It is rejected.

Diagnostic: the vyos-config-version comment in the saved file names schema versions the older image does not know.

Fix: boot the previous image and use the configuration that image already holds. Migration is forward-only; a post-upgrade file is not a rollback artifact.

Rollback

  • Configuration-levelrollback N and commit returns to an earlier revision within the running image’s schema. This handles a change you made after the upgrade; it does not undo the upgrade.
  • Image-level — select the previous image as the default boot target with set system image default-boot and reboot. That image holds its own configuration at its own schema version. If the box will not boot far enough to run a command, choose the previous entry from the GRUB menu.
  • The artifact that makes both survivable — the pre-upgrade config.boot and CLI capture, held somewhere other than the router.

Production discipline

Cross-course references

  • LVI-VyOS-Upgrades (vyos-lvi-01-image-management, vyos-lvi-02-rolling-upgrade) cover the image mechanics and the fleet sequencing this procedure sits inside.
  • III-VyOS-Architecture (vyos-iii-02-frr-and-routing-daemons, vyos-iii-05-generated-runtime) cover the rendering path from the VyOS tree to the FRR running-config that this lesson relies on.
  • III-VyOS-Architecture (vyos-iii-03-configuration-tree) carries the full 1.3-to-1.4 node mapping referenced above.
  • LVI-VyOS-Upgrades (vyos-lvi-04-upgrade-validation) covers the validation procedure in which the capture-and-diff is one step.

Quiz

Knowledge check · 4 questions

  1. Q1. An FRR release renames a configuration command that your BGP setup relies on. What does the VyOS operator have to do about it before upgrading?

  2. Q2. A VyOS configuration migration script runs once, on the first boot of a new image, and translates the stored configuration forward one component version at a time.

  3. Q3. A 1.3-era configuration file is copied onto a freshly installed 1.5 router and rejected. Explain why, and recover the configuration.

    A router failed and was rebuilt from a 1.5.2 ISO. The operator copied the most recent backup of `/config/config.boot` — taken from the old box, which ran VyOS 1.3 — onto the new install and tried to load it. Loading fails on the BGP section: lines of the form `set protocols bgp 64512 neighbor 192.0.2.1 remote-as 64511` are not valid nodes. The rest of the configuration loaded.

  4. Q4. A fleet upgrade completes cleanly, routing is healthy, and the BGP alerting has stopped firing. Identify the failure and the discipline gap.

    An operator upgraded a lab router, verified the configuration migrated cleanly and that `show ip bgp summary` reported every session Established with the expected prefix counts, then rolled the image across the fleet. Three days later, an ISP session was down for six hours before a customer reported it. The alert that should have fired had not. The check is a script that runs `show ip bgp summary` over SSH and parses the columns; it had been returning success for every router since the upgrade.

Passing score: 75%. Answers are checked in this browser.