Configuration Change with NSO
Objective
In this lesson you will use Cisco NSO to make a configuration change on a network device using a safe change-management workflow: perform a dry-run to validate the change, commit the change to the device, and rollback the change if required. This matters in production because orchestration systems like NSO let operators test changes against device models before applying them, preventing outages caused by syntax errors or policy violations. Real-world scenario: pushing a new loopback and static route to a router in a multi-site enterprise where automation must guarantee no disruption to routing and allow fast rollback if an issue is detected.
Quick Recap
Reference the topology used in Lesson 1. No new devices are added for this lesson. We will use the NSO server and Router R1 from the existing lab:
ASCII topology (management network and in-band link shown):
[NSO Server] ncs.lab.nhprep.com
mgmt0: 192.168.100.10/24
|
| 192.168.100.0/24 (mgmt network)
|
[Router R1] R1
Loopback0: 10.0.0.1/32
GigabitEthernet0/0 (mgmt): 192.168.100.11/24
GigabitEthernet0/1 (in-band): 203.0.113.1/24
Device table
| Device | Hostname | Management IP | Device OS/Type | Username |
|---|---|---|---|---|
| NSO server | ncs | 192.168.100.10 | NSO (ncs) | admin |
| Router | R1 | 192.168.100.11 | IOS router | admin |
Credentials used in examples:
- Username: admin
- Password: Lab@123
- Domain used in examples: lab.nhprep.com
- Organization: NHPREP
Tip: The management network (192.168.100.0/24) isolates orchestration traffic from production forwarding. In production deployments you typically use a dedicated management VLAN/subnet exactly for this reason.
Key Concepts
Before making changes with NSO you need to understand these core principles:
- Configuration candidate vs running: NSO edits a candidate configuration (a transactional workspace) and can validate it (dry-run) before committing it to device running-configs. Think of the candidate as a staging area — like drafting an email before sending it.
- Dry-run (validation): A dry-run verifies that the proposed change is syntactically and semantically valid against the device model and, when applicable, against the live device state. It prevents accidental invalid configuration from being pushed.
- Commit and atomicity: A commit in NSO is atomic — either the full change set is applied to all targeted devices, or the operation fails and NSO keeps state consistent. In production this prevents partial deployments.
- Rollback / versions: NSO maintains configuration history; you can rollback to a previous committed state. This is critical for quick recovery when a change causes unexpected behavior.
- Device modeling and NETCONF/CLI: NSO interacts with devices using device adapters (e.g., NETCONF, CLI). Understanding the protocol used matters because behavior (validation, rollback support) differs by adapter.
Real-world note: In production, teams use dry-runs in change windows to ensure a change won’t break routing, and keep rollback steps documented for every change.
Step-by-step configuration
We will: 1) Create a candidate config in NSO that adds a Loopback100 to R1 and a matching static route on the router, 2) perform a dry-run to validate, 3) commit the change, 4) demonstrate a rollback to the previous state.
Step 1: Open NSO CLI and enter configuration mode
What we are doing: Connect to the NSO server CLI and enter NSO configuration mode so we can edit device configurations in the NSO candidate datastore.
ssh admin@192.168.100.10
# password: Lab@123
# once on the NSO server
ncs@ncs:~$ ncs_cli -u admin
admin@ncs> config
admin@ncs(config)>
What just happened:
- The SSH command connects you to the NSO host (192.168.100.10) using the admin account.
ncs_cli -u adminlaunches the NSO command shell.configplaces you into NSO configuration mode where edits are staged in a candidate datastore. Edits here are not yet applied to devices until you commit.
Real-world note: Using NSO configuration mode is equivalent to editing a transactional database — this prevents partial changes from being applied directly to devices.
Verify:
admin@ncs(config)> show configuration
# Expected output shows current NSO configuration and no uncommitted changes.
# Example (complete expected output)
system {
admin {
user admin {
password "$1$xxxxxxxx"; # hashed password
full-name "NSO Admin";
}
}
}
devices {
device R1 {
address 192.168.100.11;
authgroup default;
type cli;
}
}
admin@ncs(config)> show config session
# Expected output:
# No active config sessions or uncommitted changes.
Step 2: Add a Loopback interface to R1 in the candidate
What we are doing: Add a new Loopback100 with IP 10.1.100.1/32 on R1 via NSO candidate configuration. This is a staged change only — NSO will send it to the device only after commit.
admin@ncs(config)> devices device R1 config
admin@ncs(config-device)# interface Loopback100
admin@ncs(config-device-if)# ip address 10.1.100.1 255.255.255.255
admin@ncs(config-device-if)# exit
admin@ncs(config-device)# exit
What just happened:
devices device R1 configselects the device configuration subtree in the NSO candidate.- The
interface Loopback100andip address ...lines create interface configuration under the device configuration subtree. These commands update NSO's candidate datastore, not the router yet. - At protocol level, NSO has recorded the desired config. NSO will prepare device-specific commands for the adapter (CLI or NETCONF) when commit is executed.
Real-world note: Loopbacks are commonly used for stable router identifiers, routing protocols, and management IPs. Adding them through NSO ensures consistent naming and templating across multiple devices.
Verify:
admin@ncs(config)> show configuration devices device R1
# Expected output (complete expected output):
devices {
device R1 {
address 192.168.100.11;
config {
interface {
Loopback100 {
ip {
address 10.1.100.1 {
netmask 255.255.255.255;
}
}
}
}
}
}
}
Step 3: Add a static route on R1 in the candidate
What we are doing: Add a static route for 10.2.0.0/24 via next-hop 203.0.113.254 in the candidate configuration on R1. This demonstrates multi-object changes grouped in one transaction.
admin@ncs(config)> devices device R1 config
admin@ncs(config-device)# ip route 10.2.0.0 255.255.255.0 203.0.113.254
admin@ncs(config-device)# exit
What just happened:
- The static route command was added to NSO's candidate datastore under R1. NSO will apply this route when changes are committed. Grouping interface and routing changes in one candidate ensures that they are applied together atomically.
Real-world note: Many production changes involve multiple related edits (interface + route). NSO’s transaction model guarantees either all or none are applied.
Verify:
admin@ncs(config)> show configuration devices device R1
# Expected output (complete expected output):
devices {
device R1 {
address 192.168.100.11;
config {
interface {
Loopback100 {
ip {
address 10.1.100.1 {
netmask 255.255.255.255;
}
}
}
}
ip {
route {
"10.2.0.0/24" {
next-hop 203.0.113.254;
}
}
}
}
}
}
Step 4: Perform a dry-run (validation)
What we are doing: Run a dry-run commit so NSO validates the candidate against device models and (if supported by the adapter) checks the device will accept the change. This finds issues before touching devices.
admin@ncs(config)> commit dry-run
# Expected output:
# DRY-RUN: Starting dry-run commit for current candidate
# DRY-RUN: Validating device R1 configuration...
# DRY-RUN: Validation successful, no conflicts found. No changes applied to devices.
# DRY-RUN: Completed
What just happened:
commit dry-runinstructs NSO to validate the candidate configuration without pushing it to devices. NSO runs model validations and syntax checks, and may simulate device acceptance based on the adapter. This prevents execution of erroneous commands on production devices.
Real-world note: Always perform a dry-run for changes during maintenance windows and for any change touching multiple devices. Dry-runs are especially important when templates or parameterized configs are used.
Verify:
admin@ncs(config)> show dry-run status
# Expected output:
# Last dry-run: success
# Devices validated: R1
# No changes applied
Step 5: Commit the change to devices
What we are doing: Apply (commit) the validated candidate to the device. NSO will translate the candidate into device-specific commands and push them using the configured adapter (e.g., CLI over SSH).
admin@ncs(config)> commit
# Expected output:
# Committing changes to devices...
# Device R1: connecting to 192.168.100.11...
# Device R1: sending configuration...
# Device R1: commit succeeded
# Commit completed
What just happened:
commitsends the candidate changes to the target device(s). NSO performs the push operation and waits for adapters to report success. The operation is transactional at the NSO level — if a failure occurs on one device in a multi-device commit, NSO will attempt to maintain consistency per its rollback rules.
Real-world note: For devices using pure CLI adapters, NSO sequences CLI commands and checks for expected prompts/outputs. For NETCONF-capable devices, NSO can perform more granular validation and rollback depending on the device’s capabilities.
Verify (on NSO):
admin@ncs(config)> show configuration devices device R1
# Expected output:
devices {
device R1 {
address 192.168.100.11;
config {
interface {
Loopback100 {
ip {
address 10.1.100.1 {
netmask 255.255.255.255;
}
}
}
}
ip {
route {
"10.2.0.0/24" {
next-hop 203.0.113.254;
}
}
}
}
}
}
Verify (directly on Router R1):
ssh admin@192.168.100.11
# password: Lab@123
R1# show running-config interface Loopback100
! Expected complete output:
interface Loopback100
ip address 10.1.100.1 255.255.255.255
!
R1# show ip route 10.2.0.0
! Expected complete output (static route present):
S 10.2.0.0/24 [1/0] via 203.0.113.254
Step 6: Rollback the change
What we are doing: Demonstrate rolling back to the previous configuration commit using NSO’s rollback capability, returning R1 to its prior state.
admin@ncs(config)> show commit-history
# Expected output:
# Commit ID: 1
# User: admin
# Time: 2026-04-02 10:12:00
# Summary: Added Loopback100 and static route
# Commit ID: 0
# User: initial
# Time: 2026-04-02 09:00:00
# Summary: Initial device config
admin@ncs(config)> rollback 0
# Expected output:
# Rolling back to commit 0...
# Device R1: connecting to 192.168.100.11...
# Device R1: applying rollback...
# Device R1: rollback succeeded
# Rollback completed
What just happened:
show commit-historylists NSO commit snapshots with IDs and metadata.rollback 0instructs NSO to restore the device configuration to the state recorded at commit ID 0. NSO applies the necessary commands to remove the changes performed by commit 1.- Rollback is a critical safety net: if a change causes an outage, you can quickly restore a known-good configuration.
Real-world note: Rollbacks can vary in completeness depending on the adapter and device. Some device platforms support atomic rollbacks; others require NSO to compute inverse CLI commands. Always verify the device behavior after a rollback.
Verify (directly on Router R1):
R1# show running-config interface Loopback100
! Expected complete output if rollback succeeded:
% Interface Loopback100 not found
R1# show ip route 10.2.0.0
! Expected complete output:
% Network not in table
Verification Checklist
- Check 1: NSO candidate contained the intended changes — verify with
show configuration devices device R1.- How to verify:
admin@ncs(config)> show configuration devices device R1and confirm Loopback100 and static route are present in the candidate before commit (or present in running config after commit).
- How to verify:
- Check 2: Dry-run succeeded and reported no conflicts.
- How to verify:
admin@ncs(config)> commit dry-runsuccess messages, orshow dry-run status.
- How to verify:
- Check 3: Commit applied changes to R1.
- How to verify: SSH into R1 and run
show running-config interface Loopback100andshow ip route 10.2.0.0.
- How to verify: SSH into R1 and run
- Check 4: Rollback restored the previous state.
- How to verify: Run
show commit-historyin NSO, executerollback <id>, then verify R1 no longer has Loopback100 or the static route.
- How to verify: Run
Common Mistakes
| Symptom | Cause | Fix |
|---|---|---|
| Dry-run reports validation error for interface IP overlap | Candidate IP conflicts with an existing interface or address pool | Check existing device config with show running-config and adjust the candidate IP to avoid overlap |
| Commit fails with authentication/connection error to device | Wrong management IP, credentials, or network reachability | Verify access: ping 192.168.100.11 from NSO and check device credentials; update device entry in NSO authgroup if needed |
| Rollback completes but device still shows config changes | Device adapter does not support atomic rollback or inverse commands failed | Manually inspect device running-config and, if needed, remove the offending config directly on device and record the action in NSO |
| Changes applied unexpectedly to multiple devices | Targeting the wrong device subtree or using a template with broad scope | Re-check the devices device <name> path in NSO candidate and use device-specific templates or constraints |
Key Takeaways
- NSO provides a transactional configuration model: changes are made in a candidate datastore, validated (dry-run), then committed. This reduces risk in production.
- Always perform a dry-run on critical changes — it catches model and syntax errors before devices are affected.
- Commit operations are atomic at the NSO level; treating related changes as a single transaction prevents partial deployments.
- Maintain commit history and test rollback procedures — rollbacks are essential for rapid recovery but may behave differently depending on device adapters.
Final tip: Incorporate NSO dry-runs and commit/rollback steps into your change control runbooks and automation pipelines. In production environments, that practice reduces human error and shortens mean-time-to-repair when issues occur.