BIG-IP in a Vagrant Virtualbox Box...part 2

If you followed me through the first part of this set of articles, you will now be faced with a shiny new box containing your BIG-IP VE image. You're chomping at the bit to get it fired up in vagrant, so let's do it!

The Vagrantfile

Vagrant uses a configuration file called the Vagrantfile to boot up your environment and provision your devices as you have specified. A Vagrantfile is written in Ruby, but you (generally) are not required to know Ruby to be able to use it. Granted, if you want to do magical things with the Vagrant file, you need to know Ruby. For what we're doing, you will not.
Vagrant looks for these Vagrantfiles in your current working directory. I'll get straight to the point here and give you the Vagrantfile you need to boot your BIG-IP. Then, we'll walk through what it does.
Here's the business end of the article.
# -*- mode: ruby -*-
# vi: set ft=ruby :


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.define "big-ip01.internal" do | v | = "/path/to/box/"

    config.vm.synced_folder ".", "/vagrant", disabled: true :forwarded_port, guest: 443, host: 10443

    v.vm.provider :virtualbox do |p|
      p.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
      p.customize ["modifyvm", :id, "--memory", 2048]
      p.customize ["modifyvm", :id, "--cpus", 2]
      p.customize ["modifyvm", :id, "--name", "big-ip01.internal"]

      p.customize ["modifyvm", :id, "--nic1", "nat"]
      p.customize ["modifyvm", :id, "--nictype1", "virtio"]
      p.customize ["modifyvm", :id, "--nic2", "hostonly"]
      p.customize ["modifyvm", :id, "--nictype2", "virtio"]
      p.customize ["modifyvm", :id, "--hostonlyadapter2", "vboxnet2"]

    v.vm.provision "shell", inline: 

OK! Lots of stuff going on there!
The first couple of lines can be overlooked as they are specific to Vagrant itself. In the "
" line, we tell Vagrant where to find out box we created.
Next, the "
" line, is important because BIG-IP did not have the Virtual box Guest Additions installed on it. You can't install them because the kernel headers do not exist on your VE. So there is not ability to mount a shared folder using Vagrant's build in commands. Since vagrant tries to do this by default, we simply turn that feature off for this box.
In the
line we Vagrant to accept connections to the host on port 10443 and forward them to port 443 on the BIG-IP. This allows us to reach the web UI. Why port 10443? Well, I make the assumption here that most folks will not be running vagrant as root. As such, you are not going to be able to bind to ports less than 1024. So I just follow a simple convention and add 10,000 to any port I want to add. This gets you out of the range of most common services and you're allowed to bind to these ports as a normal user.
Next we get into the BIG-IP specific details of the Vagrantfile. Remember back to the packer template we made? Well, we are going to use similar configurations here to make sure that BIG-IP has everything it needs to boot properly.
Among those things is setting the RAM and CPU count. Additionally we give the VM in Virtualbox a name so that we can know what it is just by looking. Vagrant provides a way to set the hostname on a device, but we cannot use it on a BIG-IP because the return code from doing so is greater than zero, ie, an error that looks like this.
==> big-ip01.internal: Setting hostname...

The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!


Stdout from the command:

Stderr from the command:

logname: no login name
Use the TMOS shell utility to make changes to the system configuration.
For more information, see "tmsh help sys global-settings."
Not very graceful.
After that, you can see that we once again create the first interface for mgmt and specify that it is a NAT
interface. This means that Vagrant will serve DHCP on that interface and, of course, BIG-IP will receive a
lease when it boots.
It's important to note that you specify the NIC type as "
". This is important because BIG-IP doesn't
have drivers for the other types of card provided by Virtualbox. If you specify the default, you're likely to
not have an interface for it when BIG-IP boots.
In the section section you can see me specifying another interface and connecting it to a private network
) that is provided by Virtualbox.
This is a convenient time to answer the question
Vagrant provides convenience tools for this such as private_network, why not use those?
The answer is because of
. If you did use the
command, the problem is that
controls all of your interfaces after the device boots. Adding configuration to the standard linux locations
is futile because tmm controls these and you have to use tmsh to set Self-IPs and VLANs so that the
configuration will land in mcpd and be read by
Wow, that's a lot.
So what's with that final block? Well, this is my hack to assure that BIG-IP is "ready to go" so-to-speak.
If this pause and loop were not here, then Vagrant would boot the device and be like "ok here you go!" but
the system and its services would still be in the middle of starting up and configuring themselves. So that's
a problem.
With this poor-mans version of a spin-lock, we ensure that Vagrant won't bless the VM as ready-to-go until
, and all the other things are ready to go.
So that's it! Crazy.
Now, an aside here, what if you want to do any pre-configuration automatically so that you do not need to
perform it in the web UI? This is a trivial addition. You would add another block that resembles the following
    v.vm.provision "shell", inline: 
Or whatever you want to do. The above will turn off the standard setup screen and license the box for you.
With that all in place, fire it up!
vagrant up
Wait a little bit and when you're done, there it is in Virtualbox ready to be used as any other Vagrant box
would be.
I've included the full Vagrantfile in the References section below.
This concludes our trip through vagrant land. Hope it has provided insight into how to use the tool with a BIG-IP VE image. Lemme know if the comments what you think and if you would be interested in other oddball technical articles about BIG-IP.


Updated Jun 06, 2023
Version 2.0

Was this article helpful?


  • David_Holmes_12's avatar
    Historic F5 Account
    This is so cool! Thanks for putting this together. So what are you going to do with it now that it's in Vagrant? Just curious.
  • Every now-and-then I need a throw-away BIG-IP to test something, so it's handy for that. For example, testing the ansible modules I pick at without sending them through a whole test suite. We have some other tools for "bigger" setups, but this is handy for ad-hoc configs
  • Thomas_A__McGon's avatar
    Historic F5 Account

    Hi Tim, I have been fooling around with your two articles on packer and vagrant. I want to use them for some ansible testing. Vagrant is specifying port 10443, how do you tell the ansible BigIP modules to use this port. I am not sure how to do this. Your help as always is greatly appreciated. -Tom


  • @Tom


    You can use the server_port argument that is available in all of the BIG-IP modules


  • Thomas_A__McGon's avatar
    Historic F5 Account


    Thanks for replying so quickly, sorry I missed that option. Just tested it. Worked like a charm. FYI, to get sudo working in packer, I had to:

    ln -s
        ln -s
    Also, in order to get the vboxnet interface working I had to:

    VBoxManage hostonlyif create
    and then

    sudo "/Library/Application Support/VirtualBox/LaunchDaemons/" restart

    Thanks again for your help! -Tom