A JNCIA practice lab needs a Junos device to configure, something to route between, and a way to prove each step. Two vJunos routers give you all three for free. This lab starts with addresses only, and you add the rest by hand: commits and rollbacks, static routes, OSPF, a routing policy and a firewall filter that breaks things on purpose.
All output below comes from one real run on vJunos-router 26.2R1.7. The topology is in our public juniper-labs repository.
JNCIA-Junos exam facts
From Juniper's certification page:
- Exam: JN0-106, 65 multiple-choice questions, 90 minutes, delivered by Pearson VUE
- Software version: Junos OS 21.2
- Prerequisite: none
- Validity: three years
- Role: the baseline for the Enterprise and Service Provider routing and switching tracks, so JNCIS comes after it
JN0-105 ended on April 5, 2026, so a guide that names it is out of date. The exam is written, so this lab is practice for understanding, never a copy of the test. It also matters where you get your hands-on time: Juniper's free Open Learning course has recorded lab demonstrations but no labs, and vLabs is being retired.
What this lab covers
| JN0-106 objective | Covered here | Tested in this lab |
|---|---|---|
| Networking Fundamentals | ⚠️ In passing | Addressing, longest match |
| Junos OS Fundamentals | ✅ Yes | Routing table against forwarding table |
| User Interfaces | ✅ Most | CLI modes, candidate and active config, compare, rollback |
| Configuration Basics | ⚠️ Part | Initial addressing, interfaces, rescue config |
| Operational Monitoring and Maintenance | ⚠️ Part | Show commands, ping, traceroute |
| Routing Fundamentals | ✅ Yes | Route preference, static routes, OSPF |
| Routing Policy and Firewall Filters | ✅ Yes | Export policy, filter terms, counters, implicit discard |
Not tested in this run: J-Web, user accounts and login classes, configuration groups, NTP and syslog, software upgrades, root password recovery and unicast RPF.
The lab
h1 --- ge-0/0/1 [r1] ge-0/0/0 --- ge-0/0/0 [r2] ge-0/0/1 --- h2
10.1.1.10 10.1.1.1 10.0.12.1/30 10.0.12.2 10.2.2.1 10.2.2.10Two routers and two Linux hosts. Loopbacks are 10.255.0.1 and 10.255.0.2. The startup config holds addresses and nothing else.
On NetPilot, upload the vJunos-router image under Images once, then ask for it:
Build two vJunos routers joined by one link with a Linux host behind each. Give them addresses only. I will configure routing myself by hand.
The agent writes the topology and addresses, deploys, and waits out the boot. To run it yourself, clone the repository and follow Run vJunos in containerlab.
Budget time before you start. Each router boots a VM inside a VM. Ours took 31 to 37 minutes to read Online, on a VM that was also running other labs, and about 18 minutes is what we have measured for one to three nodes in earlier runs. Start the lab, then go read a chapter.
Exercise 1: candidate, compare, commit, rollback
Junos never changes the running device while you type. You edit a candidate configuration, then commit it. Try it with an interface description:
admin@r2> configure
Entering configuration mode
[edit]
admin@r2# set interfaces ge-0/0/0 description to-r1
[edit]
admin@r2# show | compare
[edit interfaces ge-0/0/0]
+ description to-r1;
[edit]
admin@r2# commit check
configuration check succeeds
[edit]
admin@r2# commit comment "describe r1 link"
commit completeNow undo it. rollback 1 loads the previous commit into the candidate. It changes nothing until you commit:
[edit]
admin@r2# rollback 1
load complete
[edit]
admin@r2# show | compare
[edit interfaces ge-0/0/0]
- description to-r1;
[edit]
admin@r2# commit and-quit
commit complete
Exiting configuration modeRead the commit history in operational mode:
admin@r2> show system commit | match "^[0-2] "
0 2026-10-30 21:09:26 UTC by admin via cli
1 2026-10-30 21:07:55 UTC by admin via cli
2 2026-10-30 20:53:44 UTC by root via otherLine 2 is the startup config, loaded at boot. A question worth knowing: operational commands fail inside configuration mode. show configuration interfaces ge-0/0/0 at the [edit] prompt gives syntax error. Prefix it with run, or use show interfaces ge-0/0/0, which reads the candidate.
Exercise 2: static routes
r1 has no route to r2's LAN yet, so show route 10.2.2.0/24 prints nothing. Add one in each direction, with the loopbacks:
admin@r1> configure
admin@r1# set routing-options static route 10.2.2.0/24 next-hop 10.0.12.2
admin@r1# set routing-options static route 10.255.0.2/32 next-hop 10.0.12.2
admin@r1# commit and-quitOn r2, use 10.1.1.0/24 and 10.255.0.1/32 with next hop 10.0.12.1. Then check:
admin@r1> show route protocol static
inet.0: 7 destinations, 7 routes (7 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
10.2.2.0/24 *[Static/5] 00:00:02
> to 10.0.12.2 via ge-0/0/0.0
10.255.0.2/32 *[Static/5] 00:00:02
> to 10.0.12.2 via ge-0/0/0.0The 5 is the route preference, the Junos word for what Cisco calls administrative distance. Prove it from a host:
$ docker exec clab-jncia-lab-h1 ping -c 3 -i 0.3 10.2.2.10
3 packets transmitted, 3 received, 0% packet loss, time 602ms
$ docker exec clab-jncia-lab-h1 traceroute -n -w 1 -q 1 10.2.2.10
1 10.1.1.1 1.043 ms
2 10.0.12.2 2.071 ms
3 10.2.2.10 1.804 msExercise 3: OSPF and route preference
Add OSPF on both routers and leave the static routes in place. The LAN and the loopback are passive, so they are advertised with no neighbor on them:
admin@r1# set protocols ospf area 0.0.0.0 interface ge-0/0/0.0 interface-type p2p
admin@r1# set protocols ospf area 0.0.0.0 interface lo0.0 passive
admin@r1# set protocols ospf area 0.0.0.0 interface ge-0/0/1.0 passive
admin@r1# commit and-quitadmin@r1> show ospf neighbor
Address Interface State ID Pri Dead
10.0.12.2 ge-0/0/0.0 Full 10.255.0.2 128 32Now the routing table holds two routes to the same prefix, and preference picks one:
admin@r1> show route 10.2.2.0/24 exact
inet.0: 8 destinations, 10 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
10.2.2.0/24 *[Static/5] 00:02:29
> to 10.0.12.2 via ge-0/0/0.0
[OSPF/10] 00:00:02, metric 2
> to 10.0.12.2 via ge-0/0/0.0The star marks the active route. Static at 5 beats internal OSPF at 10, and the lower number wins.
Exercise 4: routing table and forwarding table
Delete the statics on both routers. OSPF takes over with no change to the path:
admin@r1# delete routing-options static route 10.2.2.0/24
admin@r1# delete routing-options static route 10.255.0.2/32
admin@r1# commit and-quitadmin@r1> show route 10.2.2.0/24 exact
inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
10.2.2.0/24 *[OSPF/10] 00:00:43, metric 2
> to 10.0.12.2 via ge-0/0/0.0
admin@r1> show route forwarding-table destination 10.2.2.0/24 table default
Routing table: default.inet
Internet:
Destination Type RtRef Next hop Type Index NhRef Netif
10.2.2.0/24 user 0 10.0.12.2 ucst 593 4 ge-0/0/0.0That is the control plane and forwarding plane split the exam asks about. The first command reads the Routing Engine's table of every route it knows. The second reads what was pushed down for forwarding, the winners only.
Exercise 5: an export policy
Take r2's LAN out of OSPF. r1 loses the route, and show route 10.2.2.0/24 exact prints nothing:
admin@r2# delete protocols ospf area 0.0.0.0 interface ge-0/0/1.0
admin@r2# commit and-quitBring it back with policy. A direct route does not enter OSPF by itself, so name it and export it:
admin@r2# set policy-options policy-statement export-lan term lan from protocol direct
admin@r2# set policy-options policy-statement export-lan term lan from route-filter 10.2.2.0/24 exact
admin@r2# set policy-options policy-statement export-lan term lan then accept
admin@r2# set protocols ospf export export-lan
admin@r2# commit and-quitadmin@r2> show ospf database external
OSPF AS SCOPE link state database
Type ID Adv Rtr Seq Age Opt Cksum Len
Extern *10.2.2.0 10.255.0.2 0x80000001 6 0x22 0xe9ae 36On r1 it now arrives as an external route at preference 150:
admin@r1> show route 10.2.2.0/24 exact
inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
10.2.2.0/24 *[OSPF/150] 00:00:07, metric 0, tag 0
> to 10.0.12.2 via ge-0/0/0.0Same prefix, same next hop, different route type. That is the effect of a policy on the routing table, in one line.
Exercise 6: a firewall filter, then break it on purpose
Build a filter that drops and counts ICMP, with a term that accepts the rest. Apply it outbound toward h2:
admin@r2# set firewall family inet filter block-ping term icmp from protocol icmp
admin@r2# set firewall family inet filter block-ping term icmp then count ping-drops
admin@r2# set firewall family inet filter block-ping term icmp then discard
admin@r2# set firewall family inet filter block-ping term rest then accept
admin@r2# set interfaces ge-0/0/1 unit 0 family inet filter output block-ping
admin@r2# commit and-quit
[edit interfaces ge-0/0/1 unit 0 family inet filter]
'output'
warning: requires 'L2 and L3 Filters' license
commit completeIgnore that warning. Juniper's vJunos docs say the license check messages can be ignored, and the filter works:
$ docker exec clab-jncia-lab-h1 ping -c 4 -i 0.3 -W 1 10.2.2.10
4 packets transmitted, 0 received, 100% packet loss, time 912msadmin@r2> show firewall filter block-ping
Filter: block-ping
Counters:
Name Bytes Packets
ping-drops 336 4Four pings, four counted. Now the lesson that sticks. Remove the accept term and put the filter on the OSPF link. A filter ends with an implicit discard, so this drops everything. Use commit confirmed so Junos saves you:
admin@r2# delete firewall family inet filter block-ping term rest
admin@r2# set interfaces ge-0/0/0 unit 0 family inet filter input block-ping
admin@r2# commit confirmed 2 comment "filter with no accept term"
commit confirmed will be automatically rolled back in 2 minutes unless confirmed
commit complete
# commit confirmed will be rolled back in 2 minutesOne minute later on r1, the adjacency has fallen and the route is gone:
admin@r1> show ospf neighbor
Address Interface State ID Pri Dead
10.0.12.2 ge-0/0/0.0 Init 10.255.0.2 128 35
admin@r1> show route 10.2.2.0/24 exact
Init means r1 hears r2's hellos, but r2 no longer hears r1, because its inbound filter drops them. Do nothing. Junos reverts by itself:
Broadcast Message from root@r2
(no tty) at 21:23 UTC...
Commit was not confirmed; automatic rollback complete.
admin@r2> show system commit | match "^[0-2] "
0 2026-10-30 21:23:15 UTC by root via other
1 2026-10-30 21:19:45 UTC by admin via cli commit confirmed, rollback in 2mins
2 2026-10-30 21:18:02 UTC by admin via cli
admin@r2> show ospf neighbor
Address Interface State ID Pri Dead
10.0.12.1 ge-0/0/0.0 Full 10.255.0.1 128 38Asked for two minutes, this rollback landed 3 minutes 30 seconds after the commit. Commits are slow on a busy vJunos and our configuration session was still open, so leave yourself margin. On a real router, commit confirmed is what stops a bad filter from locking you out. If the change is good, run commit inside the window to keep it.
Exercise 7: a rescue configuration
Save a known good config you can load in one step:
admin@r1> request system configuration rescue save
Rescue configuration operation on re0
Success
admin@r1> show system configuration rescue | match "host-name|area"
host-name r1;
area 0.0.0.0 {To end, remove the filter from ge-0/0/1 and confirm the hosts can talk:
$ docker exec clab-jncia-lab-h1 ping -c 4 -i 0.3 -W 1 10.2.2.10
4 packets transmitted, 4 received, 0% packet loss, time 902msHave the agent drill you
Once the lab runs, the same VM works as a study partner. On NetPilot, ask:
Break one thing in this lab without telling me what, then let me find it from the CLI. Check my answer against the devices.
You stay on the CLI, and the console to each router is always there. To compare notes across vendors, our BGP multi-vendor lab puts Junos next to Cisco and Arista.
After the JNCIA
JNCIA-Junos is the base for JNCIS-ENT and JNCIS-SP. For switching topics such as VLANs, IRB and LACP, you want vJunos-switch rather than vJunos-router. The same two-node shape works. Juniper's own guidance is on the certification page.
FAQ
Is there a lab on the JNCIA-Junos exam?
No. JN0-106 is a written exam with 65 multiple-choice questions in 90 minutes, delivered by Pearson VUE. Hands-on practice still helps, because many objectives ask what a command does or how a configuration behaves.
Can I practice for the JNCIA without Juniper hardware?
Yes. vJunos-router is a free virtual Junos router from Juniper, and two of them cover the CLI, commit model, routing, policy and firewall filter objectives. They need a host with KVM, or a hosted lab. This post runs every exercise on vJunos-router 26.2R1.7.
Does Juniper's free JNCIA course include labs?
No. Juniper's Open Learning FAQ says there are no hands-on labs for that course, only recorded lab demonstrations. Lab access comes with the paid On-Demand course. Juniper vLabs was the usual free option, and a notice on its site says it will be retired on October 31.
What replaced the JN0-105 exam?
JN0-106. Juniper's certification news says JN0-105 reached end of life on April 5, 2026, and the new exam started on April 6, 2026. The certification keeps the JNCIA-Junos name, and the program is now called the HPE Networking Certification Program.
Does a filter with no accept term block everything?
Yes. A Junos firewall filter ends with an implicit discard, so traffic that matches no term is dropped. In this lab a filter with one discard term on the OSPF link took the adjacency down, and commit confirmed rolled it back.