In this post I will install a Juniper vSRX for use with the vagrant-libvirt provider. Prior to installing the vSRX there are some required steps to get the KVM host prepped which I will not cover. These steps are covered in the Juniper documentation here.


I originally covered this topic in December 2017. I have learned alot of lessons since then and there have been some nice additions to Vagrant to make things a bit more seamless. This post is a revamp of that previous post.

For reference the following software will be used in this post.

  • Juniper vSRX - 18.1R1.9
  • Vagrant - Vagrant 2.1.0
  • vagrant-libvirt - 0.0.43
  • Ubuntu - 1604


Juniper does not provide a Vagrant Libvirt box, but they do provide a qcow2 image. You will need to download the qcow2 from the Juniper software download section.


You will need either a valid support contract or rights to download this image. Prior to working in my current role I was able to raise a case with Juniper support requesting access to the vSRX image for the purpose of preparing for my new role.


Create and change into directory for vSRX files. I like to keep my custom vagrant boxes under ~/vagrant/boxes/.


mkdir -p ~/vagrant/boxes/juniper
cd ~/vagrant/boxes/juniper

Copy the qcow2 file downloaded earlier to the ~/vagrant/boxes/juniper directory.


cp ~/Downloads/media-vsrx-vmdisk-15.1X49-D120.3.qcow2 .

The maintainers of the vagrant-libvirt plugin have a script that can be used to convert qcow2 images to a vagrant box. Download the libvirt conversion script.


curl -O

Create a bootstrap configuration file named juniper.conf with following contents that will be applied on boot to the vSRX.


system {
    host-name vsrx;
    root-authentication {
        encrypted-password "$1$nq.N1UsY$JxA/ESAj3KuXseXE597gg0"; ## SECRET-DATA
        ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"; ## SECRET-DATA
    login {
        user vagrant {
            uid 2000;
            class super-user;
            authentication {
                ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"; ## SECRET-DATA
    services {
        ssh {
            root-login allow;
        netconf {
    syslog {
        user * {
            any emergency;
        file messages {
            any any;
            authorization info;
        file interactive-commands {
            interactive-commands any;
    license {
        autoupdate {
interfaces {
    fxp0 {
        unit 0 {
            family inet {
security {
    forwarding-options {
        family {
            inet6 {
                mode packet-based;
            mpls {
                mode packet-based;


I am creating this VM in packet-mode. This essentially makes the vSRX a router. To use the vSRX as a firewall omit the security > forwarding-options stanza.

Place the juniper.conf file in a directory named iso_dir.


ls -l iso_dir
# output

total 4
-rw-rw-r-- 1 bradmin bradmin 2050 Nov 29 23:13 juniper.conf

Create an iso image named bootstrap.iso.


mkisofs -l -o bootstrap.iso iso_dir

# output
I: -input-charset not specified, using utf-8 (detected in locale settings)
Total translation table size: 0
Total rockridge attributes bytes: 0
Total directory bytes: 0
Path table size(bytes): 10
Max brk space used 0
176 extents written (0 MB)

Now lets build the vSRX VM.


virt-install \
    --name vsrx \
    --os-type linux \
    --os-variant rhel7 \
    --cpu host \
    --vcpus=2 \
    --hvm \
    --arch=x86_64 \
    --ram 4096 \
    --disk path=junos-media-vsrx-x86-64-vmdisk-18.1R1.9.qcow2,size=16,device=disk,bus=ide,format=qcow2 \
    --disk path=bootstrap.iso,device=cdrom,bus=ide \
    --boot hd \
    --network=network:vagrant-libvirt,model=virtio \
    --graphics none \

A virtual console will be connected to the VM and you will be able to see the VM boot up. Once the VM is booted login with the username root and password Juniper and check the IP address assigned to the fxp0.0 interface.


vsrx (ttyd0)

login: root

--- JUNOS 18.1R1.9 Kernel 64-bit  JNPR-11.0-20180308.0604c57_buil
root@vsrx% cli
root@vsrx> show interfaces terse | match fxp0.0

# output
fxp0.0                  up    up   inet

From another host terminal confirm that it is possible to SSH to the VM with the Vagrant insecure_private_key.


# from host shell
ssh vagrant@ -i ~/.vagrant.d/insecure_private_key

# now logged into guest vsrx
--- JUNOS 18.1R1.9 Kernel 64-bit  JNPR-11.0-20180308.0604c57_buil

If you can successfully SSH to the vSRX with the Vagrant insecure_private_key its time to package the VM into a Vagrant box. First shutdown the VM.


request system power-off

# output
Power Off the system ? [yes,no] (no) yes

*** FINAL System shutdown message from vagrant@vsrx ***

System going down IMMEDIATELY

To exit the console use one of these key combinations (Assuming English keyboard).

  • CTRL + ]
  • CTRL + 5
  • Press and hold CTRL and SHIFT while pressing 6 then ]

Create a metadata.json file with the following contents.



Use the previously downloaded script to make a Vagrant box from the qcow2 image.


bash junos-media-vsrx-x86-64-vmdisk-18.1R1.9.qcow2

# output
==> Creating box, tarring and gzipping
Total bytes written: 4768798720 (4.5GiB, 24MiB/s)
==> created
==> You can now add the box:
==>   'vagrant box add --name junos-media-vsrx-x86-64-vmdisk-18.1R1.9'

Create a metadata file called vsrx.json so that the box is added with the correct version number.


  "name": "juniper/vsrx",
  "description": "Juniper vSRX",
  "versions": [
      "version": "18.1R1.9-packetmode",
      "providers": [
          "name": "libvirt",
          "url": "file:///home/bradmin/vagrant/boxes/juniper/"

Add the box to Vagrant using the vsrx.json file.


vagrant box add vsrx.json

# output
==> box: Loading metadata for box 'vsrx.json'
    box: URL: file:///home/bradmin/vagrant/boxes/juniper/vsrx.json
==> box: Adding box 'juniper/vsrx' (v18.1R1.9-packetmode) for provider: libvirt
    box: Unpacking necessary files from: file:///home/bradmin/vagrant/boxes/juniper/
==> box: Successfully added box 'juniper/vsrx' (v18.1R1.9-packetmode) for 'libvirt'!

Confirm the vsrx box was added successfully.


vagrant box list

# output
CumulusCommunity/cumulus-vx   (libvirt, 3.6.0)
. <snip>
juniper/vsrx                  (libvirt, 12.1X47-D15.4-packetmode)
juniper/vsrx                  (libvirt, 12.1X47-D15.4)
juniper/vsrx                  (libvirt, 18.1R1.9-packetmode)


Use this Vagrantfile to test out the new vSRX Vagrant box.


# -*- mode: ruby -*-
# vi: set ft=ruby :

cwd = Dir.pwd.split("/").last

Vagrant.configure("2") do |config|

  config.vm.define "rt01" do |node|
    hostname = "rt01" = "juniper/vsrx"
    node.vm.box_version = "18.1R1.9-packetmode"
    node.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true

    node.ssh.insert_key = false

    # Limit CPU once Box has finished booting.
    node.trigger.after :up do |trigger| = "Finished Message" = "Machine is up! : #{cwd}_#{hostname}" = {inline: "virsh schedinfo #{cwd}_#{hostname} --set vcpu_quota=33000"}

    node.vm.provider :libvirt do |domain|
      domain.nic_adapter_count = 1
      domain.disk_bus = "ide"
      domain.cpus = 2
      domain.memory = 4096



You may get 100% CPU on the host machine, the only way I could get this down without drastically affecting the box performance was to reduce the CPU scheduler access to 33% using the virsh schedinfo command. I am using a new feature in Vagrant 2.1.0 called triggers to execute the required command automatically once the box has booted up.


Lets vagrant up and make sure we can connect to the vSRX.


vagrant up

# output
Bringing machine 'rt01' up with 'libvirt' provider...
==> rt01: Checking if box 'juniper/vsrx' is up to date...
==> rt01: Uploading base box image as volume into libvirt storage...
==> rt01: Creating image (snapshot of base box volume).
==> rt01: Creating domain with the following settings...
==> rt01:  -- Name:              vsrx_rt01
==> rt01:  -- Domain type:       kvm
==> rt01:  -- Cpus:              2
==> rt01:
==> rt01:  -- Feature:           acpi
==> rt01:  -- Feature:           apic
==> rt01:  -- Feature:           pae
==> rt01:  -- Memory:            4096M
==> rt01:  -- Management MAC:
==> rt01:  -- Loader:
==> rt01:  -- Base box:          juniper/vsrx
==> rt01:  -- Storage pool:      disk1
==> rt01:  -- Image:             /var/lib/libvirt/images/vsrx_rt01.img (16G)
==> rt01:  -- Volume Cache:      default
==> rt01:  -- Kernel:
==> rt01:  -- Initrd:
==> rt01:  -- Graphics Type:     vnc
==> rt01:  -- Graphics Port:     -1
==> rt01:  -- Graphics IP:
==> rt01:  -- Graphics Password: Not defined
==> rt01:  -- Video Type:        cirrus
==> rt01:  -- Video VRAM:        9216
==> rt01:  -- Sound Type:
==> rt01:  -- Keymap:            en-us
==> rt01:  -- TPM Path:
==> rt01:  -- INPUT:             type=mouse, bus=ps2
==> rt01: Creating shared folders metadata...
==> rt01: Starting domain.
==> rt01: Waiting for domain to get an IP address...
==> rt01: Waiting for SSH to become available...
==> rt01: Configuring and enabling network interfaces...
    rt01: SSH address:
    rt01: SSH username: vagrant
    rt01: SSH auth method: private key
==> rt01: Running triggers after up ...
==> rt01: Running trigger: Finished Message...
==> rt01: Machine is up! : vsrx_rt01
    rt01: Running local: Inline script
    rt01: virsh schedinfo vsrx_rt01 --set vcpu_quota=33000
    rt01: Scheduler      : posix
    rt01: cpu_shares     : 1024
    rt01: vcpu_period    : 100000
    rt01: vcpu_quota     : 33000
    rt01: emulator_period: 100000
    rt01: emulator_quota : -1

Now SSH into vSRX.


# from host shell
vagrant ssh

# now in vSRX shell
Last login: Sat May 12 04:39:58 2018
--- JUNOS 18.1R1.9 Kernel 64-bit  JNPR-11.0-20180308.0604c57_buil
vagrant@vsrx> show version
Hostname: vsrx
Model: vsrx
Junos: 18.1R1.9

Now that we are able to connect now lets clean up the box.


# from host shell
vagrant destroy -f

# output
==> rt01: Removing domain...

Remove the original KVM image.


rm -f junos-media-vsrx-x86-64-vmdisk-18.1R1.9.qcow2
virsh undefine vsrx

# output
Domain vsrx has been undefined


The vSRX is a staple platform in the Juniper product line. If you made it this far you will have a modern Juniper vSRX Vagrant box configured for use with the vagrant-libvirt provider. Now it's time to go out and build some Juniper labs.


vagrant juniper libvirt