Skip to main content
RunBook Academy

VyOSLIV · API and AutomationAutomation

Change management — ticket, peer review, audit log, post-deploy verification

Advanced⏱ ~22 mingitgithubgitlabjirashow system commitcomparecommit commentcommit-confirmvyos.vyos.vyos_config

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

Not yet marked complete on this device.

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:

  1. Ticket — every change is associated with a ticket (Jira, GitHub Issue, ServiceNow) that describes the intent, the implementation, and the rollback plan.
  2. 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.
  3. 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.
  4. 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-LoggingSyslog covers 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

  1. Q1. What is the role of the ticket in a change management workflow?

  2. Q2. An operator may merge a change without peer review in an emergency, and add the review later.

  3. 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.

  4. 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.