Allowing Access to Vagrant Instances from the Internet

Allowing Access to Vagrant Instances from the Internet

aka: “how do I use Vagrant with ngrok”

I’ve been working with a client whose developers use both Vagrant and ngrok very heavily. Here is what the developers like about both of them:

Vagrant:

  1. provides ability to spin up/down local development instances very quickly and consistently.
  2. the vagrant instances also run configuration management (in this case, Puppet) ensuring that the configuration is production-like

Ngrok:

  1. tunnels ports from the public internet (typically ports 80 and 443) to a given port on your own host, allowing connectivity to development instances from other hosts and devices. An example would be connecting an iOS or Android device to a vagrant instance.

Problem: accessibility, efficiency and consistency

  1. The developers were running into problems connecting hosts (typically iPhones and Android devices) to their local vagrant development instances
  2. Although easy to use, ngrok configuration was performed manually and usage wasn’t consistent developer to developer

Solution: vagrant with foodshow plugin

I solved both of these problems using a the vagrant plugin vagrant-foodshow – this vagrant plugin modifies vagrant port forwarding so that the host port also becomes the destination port of an ngrok tunnel. As all of the developers share one vagrant file, this also had the benefit of automating ngrok configuration and ensuring consistency of ngrok use. A screenshot of the results are below:

vagrant-foodshow-ngrok - Running in Chrome
Connectivity to a vagrant virtual machine from the public internet.
vagrant-foodshow-ngrok - Bootup
vagrant bootup with foodshow plugin configured.

 

Solution: the code

The Vagrantfile used to accomplish this below, and has also been checked into my snippets GitHub repository at https://github.com/colinbjohnson/snippets:

vagrantfile_api_version = "2"
if Vagrant.has_plugin?('vagrant-foodshow')
 ngrok_enabled = true
else
 ngrok_enabled = false
end
Vagrant.configure(vagrantfile_api_version) do |config|
config.vm.network "private_network", ip: "192.168.2.2"

if ngrok_enabled == true
 print "Ngrok enabled.\n"
 config.foodshow.enabled = true
 # using config.foodshow.subdomain will host your vagrant instance at the
 # given subdomain - for instance, you could host at my_subdomain.ngrok.com
 # instead of 94f3bdd.ngrok.com
 # config.foodshow.subdomain = 'my_subdomain'
 # config.foodshow.authtoken is required if using config.foodshow.subdomain
 # add your authtoken below
 # config.foodshow.authtoken = 'my_authtoken'
 config.vm.network :forwarded_port, guest: 80, host: 8080, ngrok_proto: "http+https"
 else
 $stderr.print "Ngrok not enabled.\n"
 end
config.vm.box = "ubuntu/precise64"
end

Two final notes:

  1. The above configuration exposes your vagrant instance to the public instance. If this is a concern, ngrok supports authentication to protect the destination service.
  2. My hope is to find time to create a private network shared amongst only the host OS, guest OS and the additional host, if it is an iOS or Android device.

2 thoughts on “Allowing Access to Vagrant Instances from the Internet

  1. Thanks Colin,

    This is excellent solution and has been working great for me. What happens when I want to work with other developers though? Since the ngrok subdomain would have to point to a single vagrant instance, do you just have to communicate who is using it when or is there a more elegant solution around this? I would prefer not to have to use multiple subdomains because we have to register those with other services in order to utilize API access and webhook integrations but it seams I may have to anyway.

  2. A few things I tried:
    1. Running with different port numbers and the same domain (didn’t work).

    A couple of suggestions:
    1. Run your own server and use the custom port number. For instance, you could do this now for the “ngrok.com” domain by doing ./ngrok -proto=tcp 192.168.0.1:81 and ./ngrok -proto=tcp 192.168.0.2:81. If the ngrok self-hosted option uses a domain name (say ngrok.cloudavail.com) – then you’ve a given url + unique port number mapped to each different instance – so requests for ngrok.cloudavail.com:56747 would map to 192.168.0.1:81 and ngrok.cloudavail.com:56734 would map to 192.168.0.2:82.
    2. Put in a feature request at https://github.com/inconshreveable/ngrok/issues – I spoke with the developer of ngrok briefly through an “Olark” chat on the ngrok website – he did understand the need, so he might be open to a feature request.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s