We’re going to look at OSX Yosemite Port Forwarding for Vagrant. I’ve been using Vagrant for a while now to create and maintain a development environment on my Mac both at home and at work. If you’re looking at this post then you probably already know the benefits of Vagrant and what it offers so I won’t go into it here, instead I’ll focus on the small changes you’ll possibly need to make to your Vagrant file or setup to keep your environment working in Apple’s newest version of OSX, Yosemite and now El Capitan.
If you’ve been using Vagrant on OSX for web development for any amount of time you’ll know that ports below 1024 are privileged on OSX therefore you need to setup port forwarding. The first step for this is within your Vagrantfile and you’ll no doubt see it everywhere.
config.vm.network "forwarded_port", guest: 80, host: 8080 config.vm.network "forwarded_port", guest: 443, host: 4443
For those of you not sure about the above it’s very simple. Our guest machine is the VM you are provisioning with Vagrant, the host machine is your physical machine or OSX in this case. The above is simply setting up port forwarding within your guest machine and saying that any traffic received on port 8080 from your host should be forwarded to port 80 which is the default port for http traffic. Port 443 is the default for for all https traffic or traffic over SSL.
So with the above set you could access web pages served by your guest machine / Vagrant box by visiting http://127.0.0.1:8080.
That’s not great though, you don’t want to be using port 8080 with all of the URL’s for your local web files so we need to setup some port forwarding on your host machine to point all traffic to localhost on port 80 to port 8080.
Pre Yosemite this was easily done (and still is!). Most people were probably setting some rules with IPFW, the UNIX firewall that shipped with OSX. The commands below would temporarily setup firewall rules on your mac that would direct any localhost traffic on port 80 or 443 to either port 8080 or 4443 depending on the scenario. Easy! Now you could access those locally served pages from your Vagrant box by just visiting http://127.0.0.1 with no need to specify a port at the end.
sudo ipfw add 100 fwd 127.0.0.1,8080 tcp from any to any 80 in sudo ipfw add 100 fwd 127.0.0.1,4443 tcp from any to any 443 in
OSX Yosemite Port Forwarding for Vagrant
Unfortunately, or fortunately depending on your uses, IPFW has been deprecated since Mavericks which means Vagrant and port forwarding in OSX Yosemite has seen a slight change. Now even though IPFW was deprecated it still actually worked in Mavericks but this isn’t the case with Yosemite where IPFW has been officially removed. Its replacement, pf, has been shipping with OSX for a while and is equally as easy to use.
Obviously you only need these ports to be forwarded on your host machine when your vagrant box is up and running therefore we are going to also utilise a Vagrant plugin to automate this process for us of port forwarding for us.
The plugin is called vagrant-triggers and essentially it adds a few hooks allowing you to run scripts on your host machine before and or after vagrant commands.
To install vagrant-triggers you should navigate in a terminal window to the folder where your Vagrantfile is kept which is also the folder that you run your vagrant up command from and run the following command.
vagrant plugin install vagrant-triggers
You should check the Github Page for the plugin to see what else you can do.
We’ll use the triggers plugin to enable our port forwarding on our host when we run Vagrant up and then we’ll remove the port forwarding again when we run vagrant halt.
Special thanks and mention to Salvatore Garbesi for his great article on this subject
Add the following to your vagrant file
config.trigger.after [:provision, :up, :reload] do system('echo " rdr pass on lo0 inet proto tcp from any to 127.0.0.1 port 80 -> 127.0.0.1 port 8080 rdr pass on lo0 inet proto tcp from any to 127.0.0.1 port 443 -> 127.0.0.1 port 4443 " | sudo pfctl -ef - > /dev/null 2>&1; echo "==> Fowarding Ports: 80 -> 8080, 443 -> 4443 & Enabling pf"') end config.trigger.after [:halt, :destroy] do system("sudo pfctl -df /etc/pf.conf > /dev/null 2>&1; echo '==> Removing Port Forwarding & Disabling pf'") end
From this you can see that we are binding ports 80 and 443 to ports 8080 and 4443 respectively on Vagrant Provision, up and reload and removing it on halt or destroy. One thing to bare in mind is that pf is not enabled by default on OSX so we pass the -e flag when we add the rules to enable pf and the -d flag to disable it again when we remove the port forwarding.
Now we are all setup and don’t need to worry about constantly typing in any long winded commands and we don’t even need to worry about setting up any aliases for binding our ports and then remember to run them each time! Perfect!
If you’re interested in the rest of my Vagrantfile you can find it here > Dan Purdy’s Vagrantfile.
As usual any questions or comments then leave them below!