Using Your own Configurations with Juniper vMX Devices

  • September 19, 2016


Every time you spin up a new topology at, you get a fresh clean install with minimal configuration. This tutorial walks through how to load previously backed up configurations onto Juniper vMX devices. We'll show how to do this with Ansible as well as with Juniper's PyEZ library.


This tutorial was written using the Juniper vMX 5-node topology.

Build Custom Configuration Files

For this test, you can simply copy and paste the existing configurations into their own file using the filenames vmx[1-5].conf stored in a sub-directory called configs. You can load your own configs as well, just make sure you don't over-ride the management (fxp0) interface and default static route! Once you do this, you would have 5 config files named vmx1.conf1, vmx2.conf, vmx3.conf, vmx4.conf, and vmx5.conf all located in /home/ntc/configs.

Setup Ansible Inventory

We are going to setup an Ansible inventory file that has a single group called junos and only four of the five vmx devices. Additionally, we'll create two group based variables called un and pwd that are set to the username and password of the vMX devices, namely ntc and ntc123 as can be seen below.

This inventory file should be saved with the filename inventory in your home directory.



Note: we don't have vmx5 in the list because we are going to push that configuration with PyEZ later in this tutorial.

Verify Reachability

Verify you can ping all nodes:

ping vmx1
ping vmx2
ping vmx3
ping vmx4
ping vmx5

Create Ansible Playbook to Push Configurations

This playbook will load and commit the configurations that you copied from each device (make changes as you wish). In order to accomplish this, we'll use the Juniper junos_install_config Ansible module.

Save the playbook as junos-push.yml in your home directory.


  hosts: junos
  connection: local
  gather_facts: False


  - name: PUSH CONFIG
      file: "configs/{{ inventory_hostname }}.conf"
      user: "{{ un }}"
      passwd: "{{ pwd }}"
      host: "{{ inventory_hostname }}"
      overwrite: true

Remember to set overwrite to true in this example as we are fully replacing the existing configuration files.

Execute the Playbook

ntc@ntc:~$ ansible-playbook -i inventory junos-push.yml 

PLAY [PUSH FULL CONFIGS TO JUNOS DEVICES] **************************************

TASK [PUSH CONFIG] *************************************************************
changed: [vmx1]
changed: [vmx3]
changed: [vmx2]
changed: [vmx4]

PLAY RECAP *********************************************************************
vmx1                       : ok=1    changed=1    unreachable=0    failed=0
vmx2                       : ok=1    changed=1    unreachable=0    failed=0
vmx3                       : ok=1    changed=1    unreachable=0    failed=0
vmx4                       : ok=1    changed=1    unreachable=0    failed=0


Now all four devices have brand new configurations loaded. Note, these show as changed because did manually make changes to each file being pushed. If you simply copied and pasted each config into the configs in the configs directory, these would show as ok and not changed as the module is idempotent.

Feel free to SSH into any of these three devices to verify their new configuration.

Use PyEZ to Push Configurations

In the first part of this tutorial, we looked at loading and committing new configurations using Ansible. We'll now take a quick look at how to use PyEZ to accomplish the same task.

We will do this specifically for vmx5.

First, import the required device and config objects.

>>> from jnpr.junos.device import Device as JUNIPER
>>> from jnpr.junos.utils.config import Config

Establish a NETCONF session to the device and ensure it's connected.

>>> vmx5 = JUNIPER(host='vmx5', user='ntc', password='ntc123')
>>> vmx5.connected

We're now ready to load a configuration on vmx5, but first we need to instantiate and create a new Config object.

>>> config = Config(vmx5)

Now use the load method to load (copy) the configuration onto the device.

Note: The option overwrite is set to True, otherwise it would be a merge meaning a FULL configuration is NOT being loaded onto the device. This is analogous to what we saw earlier with Ansible.

>>> config.load(path='configs/vmx5.conf', format='text', overwrite=True)
<Element load-configuration-results at 0x7f6fe6e37638>

At this point, the configuration is loaded onto vmx5, but not committed. The config is loaded as a candidate configuration.

Feel free to view the diffs that will be applied to the device, i.e. diffs between the candidate and running configuration.

>>> diffs = config.diff()
>>> print diffs
>>> #### output omitted

Finally, we can perform a commit operation.

>>> config.commit()

The True shows that the configuration was successfully committed.

You've now successfully deployed new configurations onto 5 Juniper vMX routers.

If you frequently use the On Demand Labs at, this workflow will help with optimizing the time spent setting up a base network to your specific configuration.