Welcome to Part 3 in my series of posts teaching Cisco IOS engineers how to use Juniper’s Junos! Have you travelled far to get here? It’s awfully cold/warm outside (delete as appropriate). Please, take a cold/hot cup of milk/beer (delete as appropriate), put your feet/tentacles up (delete as appropriate), rest your weary head/brain-in-a-jar (delete as appropriate), and give me £50000000/£50000000 (delete as appropriate).

If my inbox is anything to go by, there’s a growing hunger right now from folks who are already clued up on networking theory and the Cisco IOS command-line, who want to be confident with multiple vendors – but who don’t know where to start. That’s exactly where this series comes in, and it’s why in Part 1 we begun with the basics of how to actually read a typical Junos configuration, using OSPF as an example.

Then in part 2 we learned what to do when we’re in configuration mode. We saw the way Junos organises its configuration into a predictable hierarchy; we read about the active and candidate configuration; we learned that none of our changes go live until we save them; and we also found out that we can type “rollback” to scrap all of our proposed changes, so we can safely and cleanly start again without having a single impact on the production network.

If you’re new here then be sure to go back and read those posts, because today we’re going to learn how to actually save our config – and as we’ll see, Junos gives us a lot more power than the average vendor’s CLI. Let’s check it out!



In Part 2 we really hammered home something about Junos that is an absolute game-changer compared to Cisco IOS: the ability to make as many changes as we want, without those changes going live the moment we type them. Junos allows us to review our work before we commit our changes into production – and indeed, Junos allows us to commit all our changes in one single hit. Let’s quickly remind ourselves how we do that.

I’ve made a few changes to a router in my lab. In particular, I’ve taken a GigEthernet interface (ge-0/0/2), I’ve put a single logical sub-interface on it (unit 0), and I’ve given that logical sub-interface and IPv4 and an IPv6 address. This interface is currently blank in the active configuration, and has the below proposed changes in our candidate configuration.

We’ll be covering interfaces in detail in a later post. For now, let’s remind ourselves how we review our proposed changes using the “show | compare” command:

root@Router1# show | compare
[edit interfaces]
+   ge-0/0/2 {
+       unit 0 {
+           family inet {
+               address;
+           }
+           family inet6 {
+               address 2001:db8:0:14::1/64;
+           }
+       }
+   }

At the end of Part 2 I taught you how to save your work: use “commit and-quit” to leave configuration mode, and go back to regular operational mode.

root@Router1# commit and-quit
commit complete
Exiting configuration mode


Alternatively, if I wanted to stay in configuration mode, I simply type “commit“. If I’d used that command instead, it would have looked like this:

root@Router1# commit
commit complete


The ability to save all our changes at once is already so much more reassuring than a CLI where each individual command goes live as-and-when we type it. Now, let’s take it to the next level.



During your Cisco IOS studies you might have been given advice along these lines:

“If you’re configuring a box remotely and you’re worried you might accidentally configure something that either makes you lose management access to the box or causes an outage, make sure you type “reload in 5” before you start your changes. This command automatically reboots the box after five minutes, which gets rid of your running-but-not-yet-saved config. That way, if the worst case scenario comes to light and you do indeed lose access, no worries: the box will reboot, and you’ll go back to the working configuration that was on the box before you started making your changes.”

Now, OBVIOUSLY no-one is denying that rebooting a box, and causing a potentially huge outage while you wait for said reboot to finish, is an absolutely brilliant way to undo your change. Truly fantastic. An indisputably great process. The definition of “best practice”. Everyone loves downtime! Excellent and perfect advice, and not in any way terrible or awful, or bad. You won’t find an engineer in the world who thinks this is anything other than the most ideal way to deal with this situation.

But: what if there was A Better Way™? My friends: there is.

If you’re making a configuration change and you suspect in any way that your change might cause a problem, commit your work with the command “commit confirmed“. This tells Junos to automatically roll back to the previous configuration after 10 minutes, unless we save our work again. Thanks to this command, if you do accidentally make a mistake that takes away your management access, then at least the box can carry on being operational and processing traffic while you wait for your changes to be undone.

And hey: if it turns out that your change was more severe than you thought, and you did actually cause an outage, then again, at least you only have to wait for the change to be undone, instead of fully rebooting the box.

Perhaps ten minutes is too long to wait? Let’s be honest: it often is. In that case, type “commit confirmed 3“, or however many minutes you like, from 1 all the way up to 65,535, to get the quickest rollback suitable for your change. Though why you’d want to wait 65,535 minutes for your change to roll back is anyone’s guess. Some people like to live dangerously, I suppose. Anyway, here’s what it looks like:

root@Router1# commit confirmed 3
commit confirmed will be automatically rolled back in 3 minutes unless confirmed
commit complete

# commit confirmed will be rolled back in 3 minutes

Did your change go well? You’re still in configuration mode – so just type “commit” to truly save your changes. Committing your config cancels the automatic rollback. Alternatively, if you do indeed want to roll back and reverse your changes, just wait 3 minutes and your command prompt will show you this output below. Hit return when you see it to get back to the CLI.


Broadcast Message from root@Router1
        (no tty) at 0:39 UTC...

Commit was not confirmed; automatic rollback complete.

Now imagine this scenario: what could you do if your change didn’t go according to plan, but you still had access to the box? Instead of waiting for this automatic rollback to kick in, how can you quickly undo your change? Ideally you want to get back to the previous configuration as soon as possible, not in 3 or 10 or 65535 minutes time. Is it possible?

Yes, and it’s very easy indeed: you simply have to type  “rollback 1” to reload the previous configuration into your candidate config, then “commit” to save it.

Did you notice we introduced a new command there? In the last post we learned “rollback” on its own, to scrap our changes. But “rollback 1” is new. What does it mean? Hold that thought for now – because in a moment we’re going to look at our commit history, at which point it will be a lot clearer.



What if we want to verify that our configuration is good before we save it?

Well, as it happens, Junos checks our configuration in real-time. Every single new word we type is verified for correct and proper syntax, as we type it. In other words, if we intended to type “show system uptime“, but instead typed “show ststem uptime“, the CLI would never get past the 2nd word.

This is in contrast to Cisco IOS, where we can get to the very end of typing a looong line of configuration, only to find out that we typed the very first word incorrectly. Don’t be confused if you’re trying to type a command in Junos but can’t get past a certain word: it’s Junos helping you to spot a problem.

It’s really important to understand that Junos is only checking your syntax as you type. To show you what I mean, I’m going to quickly tell you that the Junos equivalent of an access-list is called a firewall filter. You make a named filter, and then apply it wherever you need to. In a future post we’ll compare access lists to firewall filters. Spoiler alert: when you see how they work, I think you’re going to prefer how Junos does it.

What if we tried adding a named firewall filter to an interface, when we haven’t actually configured the firewall rule itself yet? Would Junos allow this? Or would the real-time checking throw us an error?

Actually, Junos allows you to type this successfully. Why? Because (with an extremely small number of exceptions) Junos doesn’t force you to type individual commands into the candidate configuration in a particular order. If you want to put a filter on an interface, and then configure the filter itself, that’s fine! All that matters is that all the correct configuration is present at the time that you want to commit.

And if we did indeed try to commit a configuration with a non-existent firewall rule on an interface, Junos would fail the commit. Let’s see that in action:

root@Router1# set interfaces ge-0/0/1 unit 0 family inet filter input FAKE_FIREWALL_FILTER

root@Router1# commit
[edit interfaces ge-0/0/1 unit 0 family inet]
    Referenced filter 'FAKE_FIREWALL_FILTER' is not defined
error: configuration check-out failed

Now that you see how helpful Junos can be, let’s consider a scenario.

Imagine that you’d written out 30 lines of new configuration, in advance, for a change that evening. Firewall filters, routing policies, BGP peerings – clearly a config with a lot of new moving parts. You’re not going to actually deploy this new configuration until later on. Still though, you’d love to be able to check in advance that your configuration actually makes sense, and won’t cause any errors when it’s deployed.

This ability to verify your work without actually saving it sounds very handy: it would certainly prevent problems at 2am when the engineer tasked with entering your change suddenly finds that your configuration isn’t quite correct!

Of course, in IOS it would be very difficult indeed to do these checks. After all, you can hardly paste your commands into the CLI to check them: the commands would all go live right away!

By contrast, in Junos these checks are entirely possible. First of all, you can safely add all your configuration without it going live, due to the concept of the candidate configuration. Then, instead of typing commit, you can type “commit check“.

As you’d imagine, this command checks your candidate configuration for errors, without actually committing the config. Typing this command will give you exactly the same error as we saw in the previous example, which means you can safely go away and fix your config, without having made a single change to the actual production network. What a life-saver! Just remember to type “rollback” to scrap all those changes before you leave configuration mode.

Just to be clear: if you’ve configured an incorrect IP address on an interface, “commit check” won’t spot that. There’s no way for a box to know if was actually supposed to be Junos is good, but it isn’t a mind-reader. Though there are rumours that mind-reading functionality may be coming in a 2021 Junos release. Stay tuned, and ask your account manager for more information.

But forget I said that: “commit check” is perfect for verifying that you haven’t accidentally told BGP to use a routing policy that doesn’t exist, or that you haven’t mistakenly configured an interface as both a layer 2 switchport and a layer 3 routed port. I use that last example on purpose, because on some more advanced Juniper boxes it’s actually possible to do exactly that! It just needs to be done in the right way, and “commit check” will readily tell you if you’ve done it properly.



So, what was that “rollback 1” command from earlier? Let’s find out.

By default, on modern Juniper boxes, Junos keeps 50 – fifty! – previous versions of your configuration. When more than 50 versions exist, the box simply discards the oldest one. If that’s not enough for you, you can configure your Junos box to automatically save every configuration to an external server, so you can keep a full history of every change ever made to the box.

To see all the currently stored historical configurations, type “show system commit“. The output below is from a real production box. There is also an outside chance that some of the usernames in the logs below may have been edited by me. I’ll leave it to you to decide.

chris.parker@Production_Box> show system commit
0   2020-04-17 13:24:38 BST by ryan.gosling via cli
1   2020-04-17 13:24:16 BST by ryan.gosling via cli commit confirmed, rollback in 10mins
2   2020-04-16 15:21:53 BST by brad.pitt via cli
3   2020-04-16 15:21:38 BST by brad.pitt via cli commit confirmed, rollback in 10mins
4   2020-04-14 11:53:30 BST by chris.parker via cli
5   2020-04-14 11:47:45 BST by chris.parker via cli commit confirmed, rollback in 10mins
6   2020-04-08 16:32:52 BST by beyonce via cli
7   2020-04-08 16:32:37 BST by beyonce via cli commit confirmed, rollback in 10mins
8   2020-04-08 16:12:10 BST by ryan.gosling via cli
9   2020-04-08 16:11:04 BST by ryan.gosling via cli commit confirmed, rollback in 10mins
10  2020-04-08 10:44:35 BST by beyonce via cli
11  2020-04-08 10:44:20 BST by beyonce via cli commit confirmed, rollback in 10mins
12  2020-04-07 12:07:09 BST by chris.parker via cli
13  2020-04-07 12:06:40 BST by chris.parker via cli commit confirmed, rollback in 2mins
14  2020-04-07 11:38:30 BST by brad.pitt via cli
15  2020-04-07 11:33:21 BST by brad.pitt via cli commit confirmed, rollback in 10mins

In the output above you can see the date that the configuration was deployed (make sure your system time is accurate!), and the name of the engineer who made the change. If any comments were added at the time of commit, you’ll see them here too.

Notice that configuration 0 is the most recent configuration – in other words, your active configuration. Configuration number 1 is the previous config; configuration number 2 is the one before that; and so on. Typing “rollback” is really the equivalent of typing “rollback 0”. And as you might have guessed, you can roll back to any of these configurations simply by saying the number you want to roll back to.

Notice as well that whenever you do a “commit confirm”, and then follow it up with a final “commit”, each of these individual commands creates a new backup configuration.

Seeing these configuration numbers, it perhaps makes sense now why we used “rollback 1” earlier to undo our “commit confirm“. To be clear: by typing “rollback 1” we are taking the previous saved config, and loading it into the candidate config – at which point you can commit once again.

What if I want to leave a comment on the actual configuration that I’m saving, perhaps so I can leave a note to say what changes I made when my colleagues are looking at this list of configurations? Sounds like a good thing to make a best-practice in your organization! Type “commit comment XYZ” to leave a comment that says XYZ. Replace “XYZ” with anything you like! Or don’t. Do whatever you like, I’m not your Dad.

root@Router1# commit comment "Chris Parker, adding BGP to the box"
commit complete

Let’s look at our commit history again, and see the results of this comment. Notice my comment underneath revision 0 of the config:

root@Router1> show system commit
0   2019-12-19 00:52:39 UTC by root via cli
    Chris Parker, adding BGP to the box
1   2019-12-19 00:39:06 UTC by root via other
2   2019-12-19 00:35:12 UTC by root via cli commit confirmed, rollback in 3mins
3   2019-12-19 00:32:12 UTC by root via cli
{output edited for brevity}

This is really handy for quickly identifying what changes were made in a particular commit. There really isn’t a reason not to do this every time you commit a change on a production box.

As we’ve seen, it’s possible to roll back to any of these configurations – and if you’ve added comments, you’ll find it extremely easy to know precisely which configuration you want to roll back to.

Just to make it explicit: let’s imagine that I wanted to roll back to configuration number 5. Is it difficult? No way, madam! In configuration mode, simply type this:

root@Router1# rollback 5
load complete

That’s it! That’s literally it. It’s as easy as that.

It’s important to understand that simply typing “rollback 5” doesn’t actually push the 5th oldest config into production. Instead, this command just loads configuration number 5 into the candidate configuration. This means you can do your friendly neighborhood “show | compare” command to see precisely what changes are going to be made – and in addition, you can of course add or remove anything you like before you actually save your work.



It’s great that we can roll back to older configs. But if a config doesn’t have comments on it, we might find it tricky to know exactly which config to roll back to. Is it possible to compare our current active configuration to an older configuration, without first importing it into the candidate configuration? Absolutely. Simply type “show configuration | compare rollback 6” to compare your current active configuration with – you guessed it – the 6th previous version of the configuration! The plus signs below mean that the config is present in the current active configuration, but missing from the 6th oldest config.

root@Router1# show | compare rollback 6
[edit interfaces]
+   ge-0/0/2 {
+       unit 0 {
+           family inet {
+               address;
+           }
+           family inet6 {
+               address 2001:db8:0:14::1/64;
+           }
+       }


Every single post in this series makes it clearer and clearer what a chasmic difference there is between Cisco IOS and Juniper Junos – and I’ve got to say, those differences give me so much more confidence when I use a Juniper device. When I type on the Cisco CLI, I’m scared. When I type on the Junos CLI, I feel like a grand conductor that has full control over the entire network. This can be a very stressful industry, and having a good CLI definitely helps to relieve that stress!

Has “commit confirmed” ever saved your career? If you’ve got any stories of horrors that this command has helped you to avoid, please do let me know in the comments below!

If you’re on Mastodon, follow me to find out when I make new posts. (2024 edit: I’m also on BlueSky nowadays too. I was once on Twitter, but I’ve given up on it, on account of… well, I don’t need to finish that sentence, do I.)

If you know any pals who might get value out of this series, I’d love it if you’d share this post on your favourite social media of choice, or maybe even message your friends directly with a link to this post.

And if you fancy some more learning, take a look through my other posts. I’ve got plenty of cool new networking knowledge for you on this website, especially covering Juniper tech and service provider goodness.

It’s all free for you, although I’ll never say no to a donation. This website is 100% a non-profit endeavour, in fact it costs me money to run. I don’t mind that one bit, but it would be cool if I could break even on the web hosting, and the licenses I buy to bring you this sweet sweet content.


  • July 6, 2020 at 12:59 pm

    Hi Chris,

    lovely commands – aren’t they? There’s also one that can compare two configurations other than the current one (‘show system rollback compare’):

    root@unnamed_router-RE0> show system commit
    0 2020-07-03 11:13:27 -03 by AAAAA via cli commit synchronize
    1 2020-07-03 11:06:41 -03 by AAAAA via cli commit synchronize
    2 2020-07-03 10:58:29 -03 by BBBBB via cli commit synchronize
    Confirmando commit
    3 2020-07-03 10:55:48 -03 by BBBBB via cli commit confirmed, rollback in 20mins synchronize
    Ajuste anuncio para o SWLAB01 do trafego movel
    4 2020-07-02 13:39:56 -03 by CCCCC via cli commit synchronize
    5 2020-07-02 13:33:40 -03 by CCCCC via cli commit synchronize
    6 2020-07-01 18:19:34 -03 by CCCCC via cli commit synchronize
    7 2020-07-01 17:19:50 -03 by BBBBB via cli commit synchronize
    Alteracao de VLANs na interface agregada com o UGW
    8 2020-07-01 17:11:05 -03 by BBBBB via cli commit synchronize
    Ajuste cosmetico – description interface ge-0/3/0
    9 2020-07-01 16:16:13 -03 by BBBBB via cli commit synchronize
    Troca de conexao direta com UGW pela falta de interfaces em 10G no lado da
    10 2020-07-01 16:01:29 -03 by AAAAA via cli commit synchronize
    11 2020-07-01 16:00:27 -03 by BBBBB via cli commit synchronize
    12 2020-07-01 15:58:32 -03 by AAAAA via cli commit synchronize

    root@unnamed_router-RE0> show system rollback compare ?
    Possible completions:
    Rollback number to compare (0..49)
    root@unnamed_router-RE0> show system rollback compare 10 12
    [edit interfaces ge-x/y/z]
    – disable;
    [edit policy-options prefix-list PREFIX-IPV4-ABC]

    Best Regards

  • July 6, 2020 at 7:10 pm

    Hi Chris,

    also – “commit check” while on the “commit confirmed” timer, confirms the commit.

    (I know – sounded convoluted 🙂 )

    Best Regards,
    — Rafael

  • July 7, 2020 at 5:44 pm

    Hi Chris,

    not sure if any of this is news to you but, a “commit check”, issued while the “commit confirmed” timer is running, actually confirms the commit.

    (Convoluted, but works 🙂 )

    Best regards,

    • July 7, 2020 at 8:38 pm

      Wow that’s odd, I just tried that in my lab and it does indeed work. I actually don’t know if I like that. It’s not intuitive that it would cancel the rollback. Still, good to know. And not the end of the world if the user didn’t intend to cancel the commit, because they can always just “rollback 2” to get back to the config before the “commit confirm”.

      Nice spot, thank you!


Leave a Reply

Your email address will not be published. Required fields are marked *