VyOSLIV · API and AutomationAutomation
Change management — ticket, peer review, audit log, post-deploy verification
What you'll learn
- Associate every change with a ticket that describes the intent and the rollback plan
- Require peer review for every change before the apply
- Audit every change in the commit log with the user, the timestamp, and the diff
- Verify the change after deploy with a post-deploy validation step
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
Change management is the discipline that wraps the configuration-as-code pipeline: every change is documented, reviewed, audited, and verified. Without change management, the configuration-as-code pipeline is just a faster way to make undocumented changes.
On VyOS 1.5 LTS, the change management workflow has four stages:
- Ticket — every change is associated with a ticket (Jira, GitHub Issue, ServiceNow) that describes the intent, the implementation, and the rollback plan.
- Peer review — every change is reviewed by a second operator before the apply. The reviewer examines the diff, asks questions, and approves or requests changes.
- Audit log — every commit to the router is recorded with the user, the timestamp, and the diff. The audit log is shipped to a remote syslog server.
- Post-deploy verification — after the apply, the operator verifies that the change had the intended effect. The verification is recorded in the ticket.
This lesson covers each stage, the production patterns for combining them, and the failure modes where change management is missing or skipped.
The ticket
The ticket is the change’s paper trail. It captures:
- Intent — why is the change being made? What problem does it solve?
- Implementation — what configuration changes are required? Which routers are affected?
- Rollback plan — how is the change rolled back if it fails? What is the previous configuration revision?
- Risk — what is the blast radius if the change fails? What is the operator’s mitigation?
# Sample ticket (Jira format)
ticket_id: NET-1234
title: Add BGP peer for new upstream provider
intent: |
Establish eBGP peering with new upstream provider
(AS 65003) to add a third transit path.
implementation: |
- set protocols bgp neighbor 10.0.0.5 remote-as 65003
- set protocols bgp neighbor 10.0.0.5 password (value from vault path net/bgp/as65003)
- set protocols bgp neighbor 10.0.0.5 address-family ipv4-unicast route-map import UPSTREAM-IN
- Applied to edge-01 first, then edge-02
rollback_plan: |
- `delete protocols bgp neighbor 10.0.0.5` on each router, then `commit`
- Verify `show ip bgp summary` no longer lists 10.0.0.5
risk: |
- If the import filter is wrong, internal prefixes may leak
- Mitigation: dry-run in lab first; deploy to edge-01 only initially
The ticket is opened before the operator edits the template. The template edit references the ticket ID; the peer review confirms the implementation matches the ticket; the post-deploy verification confirms the intent was achieved.
Peer review
The peer review is the operator’s defence against a typo, a misunderstood intent, or an unintended side effect. The review examines the diff between the previous and the new configuration:
# Sample peer review comment
"NET-1234: I see the BGP neighbour 10.0.0.5 is added with
remote-as 65003 and password authentication. The import
filter is the existing customer-cone prefix list, which
is correct for the new upstream. One question: should
the import filter be the upstream-prefix-list (which
admits the full table) instead of the customer-cone
prefix list? Let's confirm with the upstream operator
before merging."
The review is recorded in the Git platform (GitHub pull request, GitLab merge request). The review is the operator’s evidence that a second operator examined the change and either approved or requested modifications.
flowchart LR
OP[Operator\nopens PR] --> REVIEW[Peer review]
REVIEW -->|approved| MERGE[Merge to main]
REVIEW -->|changes requested| FIX[Operator fixes]
FIX --> REVIEW
MERGE --> CI[CI/CD pipeline]
CI --> APPLY[Apply]
APPLY --> VERIFY[Post-deploy verification]
VERIFY --> CLOSE[Close ticket]
The diagram shows the review loop: the operator opens a pull request; the reviewer examines and either approves or requests changes; if approved, the change merges and the pipeline applies; the post-deploy verification closes the ticket.
The audit log
The audit log is the operator’s defence against the post-incident question “what happened?”. This is the stage where most change-management designs are written against a router that does not exist, so it is worth being precise about what VyOS actually keeps and what it does not.
What VyOS gives you
A revision history. Every commit archives the
resulting configuration and records who made it and how.
show system commit, from operational mode, lists them
newest first:
show system commit
Each row carries a revision number, a timestamp, the user
and the method the change arrived by — cli for someone
typing, other for an API or a config load, which is how
you tell an Ansible run from a human. The exact column
layout has changed between releases, so read the header
on your box rather than a printed sample.
How far back that list goes is a configuration decision, and the default is smaller than most change-management policies assume:
set system config-management commit-revisions '200'
A commit comment. This is the mechanism that carries the ticket ID onto the router itself, and it is one word longer than the commit everyone types:
commit comment 'NET-1234: add BGP peer for AS 65003'
The comment is stored with the revision and shown by
show system commit. A router where every revision has a
ticket ID in its comment answers “why was this changed”
without anyone opening Git.
A diff between any two revisions. From configuration
mode, compare takes revision numbers:
configure
compare 1 0
That prints the change that revision 0 introduced over
revision 1 — the + and - lines the fabricated log
above pretended to receive by syslog. The archived files
themselves live in /config/archive/.
An off-box copy. commit-archive pushes the
configuration to a remote target after every successful
commit, which is what makes the trail survive the router:
set system config-management commit-archive location 'scp://archive@10.99.0.10/vyos/edge-01'
A syslog stream, sent off-box. On 1.4 and 1.5 the
remote target is remote, not the 1.3 host:
set system syslog remote 10.99.0.10 facility all level info
set system syslog remote 10.99.0.10 protocol 'tcp'
set system syslog remote 10.99.0.10 port '514'
The 1.4 syntax change that lives in old runbooks
The change in the sample ticket above is a BGP one, and BGP is the tree that most often exposes a runbook written against 1.3. The AS number is no longer a level in the path:
# 1.3, and still in a great many runbooks:
# set protocols bgp 64512 neighbor 10.0.0.5 remote-as 65003
# 1.4 and 1.5:
set protocols bgp system-as '64512'
set protocols bgp neighbor 10.0.0.5 remote-as '65003'
set protocols bgp neighbor 10.0.0.5 address-family ipv4-unicast route-map import 'UPSTREAM-IN'
This matters to change management specifically because of how it fails. The 1.3 line does not commit on 1.5 — it is rejected as an invalid path — so the pipeline stops and someone reads the error. That is the good case. The bad case is a rollback plan written in 1.3 syntax and never tested: it sits in the ticket looking like a rollback plan, and the operator discovers it does not parse at the one moment they needed it to. A rollback plan that has not been run on the target release is a sentence, not a plan.
Post-deploy verification
After the apply, the operator verifies that the change had the intended effect. The verification is recorded in the ticket:
# Sample post-deploy verification
ticket_id: NET-1234
deploy_time: 2026-08-15 14:25:00
verification:
- command: show ip bgp summary
expected: "10.0.0.5 ... Established"
actual: "10.0.0.5 ... Established"
- command: show ip route 10.99.0.0/16
expected: "via 10.0.0.5"
actual: "via 10.0.0.5"
result: success
verified_by: operator
verification_time: 2026-08-15 14:30:00
The verification captures the commands run, the expected output, the actual output, and the operator who verified. The verification is the operator’s evidence that the change had the intended effect.
A failed verification triggers the rollback procedure. The operator rolls back the change, updates the ticket, and investigates the cause.
Failure modes
Ticket not opened
The operator makes a change without opening a ticket. The post-incident review cannot find the intent. The change is undocumented.
Diagnostic: the Git commit has no ticket ID; the audit log has no ticket reference.
Fix: open the ticket retroactively. The defensive idiom: the pre-commit hook checks for a ticket ID in the commit message; commits without a ticket ID are rejected.
Peer review skipped
The operator merges the change without a peer review. The change is applied; the post-incident review cannot find the second pair of eyes.
Diagnostic: the Git platform shows the merge was performed by the same operator who opened the pull request; no review was requested.
Fix: enable branch protection rules that require a reviewer approval before merge. The defensive idiom: a branch protection rule is configured in the Git platform; merges without review approval are blocked.
Audit log not shipped remotely
The operator configures the local log but does not configure the remote syslog. The audit trail is on the router’s disk; an attacker can delete it.
Diagnostic: there is no show system syslog operational
command to run — syslog is configuration, so you read it
from the configuration tree:
show configuration commands | match 'system syslog'
An output with system syslog local lines and no
system syslog remote line is the finding. On a 1.3-era
box the node was system syslog host; if you see that on
a 1.5 router, the configuration came through a migration
and is worth checking rather than trusting.
Fix: configure the remote syslog server on the OOB
network, then prove it arrived rather than assuming it —
logger -t audit-test "reachability probe" on the router
and a search for that string on the collector. The
defensive idiom: every router ships its log off-box, and
the shipping is verified at build time, not at incident
time.
The same failure applies to the revision archive, and it
is the one people forget: a router with 20 stored
revisions and no commit-archive target loses its entire
change history the moment the router itself is lost, which
is exactly the incident where you wanted it.
Post-deploy verification skipped
The operator applies the change and closes the ticket without verifying. The change did not produce the intended effect (e.g. BGP session is not Established) but the operator did not notice.
Diagnostic: monitoring detects the BGP session drop; the ticket is closed but the verification is empty.
Fix: require a verification step before closing the ticket. The defensive idiom: the ticket status cannot be set to “closed” without a verification record.
Rollback
A change-management-driven change is reversible through the standard VyOS mechanisms, and it is worth knowing which of them is disruptive before the night you need one.
Undo the specific change. The cleanest revert, when you know what you did:
configure
delete protocols bgp neighbor 10.0.0.5
compare
commit
save
Apply a change with its own revert already armed.
commit-confirm applies the candidate and undoes it
automatically unless a confirm follows within the
window. This is the correct tool for any change to the
path your session rides on:
commit-confirm 5
# ... verify ...
confirm
Reload a known-good file. The archived revisions are
files, and load brings one back into the candidate
config where compare can show you what returning would
do before you commit it:
configure
load /config/archive/config.boot.2026-08-15_14.20.00
compare
commit
Then update the ticket with which mechanism was used, the revision the router returned to, and the verification that it took effect.
The defensive idiom: every change has a documented rollback plan; the plan names a mechanism that has been run on this release; and the rollback is exercised as part of the post-deploy verification rather than being trusted on paper.
Production discipline
Cross-course references
LIV-VyOS-Automation(vyos-liv-03-config-as-code,vyos-liv-04-automated-validation) cover the configuration-as-code pipeline and validation that change management wraps.XLVIII-VyOS-LoggingSyslogcovers the logging and remote syslog configuration that the audit log requires.- The Observability course covers the monitoring that detects a change that did not produce the intended effect.
Quiz
Knowledge check · 4 questions
Q1. What is the role of the ticket in a change management workflow?
Q2. An operator may merge a change without peer review in an emergency, and add the review later.
Q3. An operator applies a BGP configuration change to edge-01. The apply succeeds, but the post-deploy verification shows the BGP session is not Established. The operator closes the ticket anyway because the change was applied successfully. What is the discipline failure?
An operator applies a BGP configuration change. The apply succeeds but the BGP session is not Established. The operator closes the ticket without verifying.
Q4. An incident investigation requires understanding every change made to edge-01 in the last 30 days. The Git commit log shows 12 commits referencing tickets NET-1001 through NET-1012. The router's local audit log shows 18 commits. Five commits are in the router's log but not in Git. What is happening?
The Git commit log shows 12 commits; the router's local audit log shows 18 commits. Five commits are in the router's log but not in Git.
Passing score: 75%. Answers are checked in this browser.