Moonshine + Vagrant = Local Deployment Goodness!

Written By : Kevin Lawver

Deployment and configuration management is difficult - in some ways more difficult than writing the app itself. There are bugs just like with any software project, but they often have much larger consequences than a bug in the app (your database stops working, for example). That’s why all of our managed customers have staging environments, so we can test those changes before they go to production and possibly impact users and revenue. But even with staging, things still break, there’s sometimes contention for staging, time wasted waiting for someone else to finish testing their changes and cases where staging gets out of sync because of repeated experiments on it.

A fellow machinist, Bryan Traywick, got a single vagrant guest up and was able to deploy an app to it, which got me thinking that it was time to tackle this problem for real and create a Moonshine plugin to make creating local deployments with multiple guests easier. After a few days of effort, quite a bit of coffee and profanity, and playing god with dozens of vagrant guests, I’m happy to present Moonshine Vagrant!

It’s not a traditional Moonshine plugin, as it’s just a series of Capistrano tasks, but it works. How does it work? What does it do? I’ll tell you!

What does it do? It copies an existing deploy stage (usually staging or production) and creates a new stage called “vagrant” and all the local configuration you need to have vagrant start up those guests on your local machine, and the config you need to add to your local dnsmasq config so you can interact with your vagrant stage just like you would staging or production.

How does it work? There are several prerequisites, but if you have an existing deployment stage (we’ll use staging for this example), you can generate all of the configuration you need to get essentially the same deployment locally using vagrant by running a single cap task:

cap staging vagrant_setup:create_vagrant_stage

That cap task generates the following files:

  • Vagrantfile.generated - This contains the definition for all of the servers in your new “vagrant” stage.
  • config/environments/vagrant.generated.rb - This is cheating. It’s just a copy of the staging environment config.
  • config/deploy/vagrant.generated.rb - A new capistrano stage called “vagrant” with the new servers in it.
  • config/moonshine/vagrant.generated.yml - The Moonshine config file for the new vagrant stage.
  • local_dnsmasq.generated.txt - The settings you need to cut and paste into your local dnsmasq config file.

They all have “.generated” in them so you don’t accidentally break an existing vagrant stage, so you end up having to move some things around, but it’s all explained in the output from that cap task.

I’ve been using it for local development for one of our local projects since last Thursday and it’s amazing how it’s changed my development process. It’s now trivial to get back to a “clean” state by running vagrant destroy and starting all over with clean guests, and I’m much more likely to experiment than I was when I could impact the rest of the team by breaking staging.

I think we’ve just scratched the surface on the potential for this - and I know the setup is already too complex (check out the prerequisites list and you’ll agree). I think we can make every step of this process easier and more automated, but I’m pretty thrilled that with a single cap task and by moving a few files around, I can get a deployment that looks and feels a lot like production running on my local machine. Keep an eye out for updates, as I expect we’ll be updating the plugin frequently.

Like I said, I’ve only been running moonshine_vagrant since last Thursday, but here are some things I’ve “discovered”:

  • You need a bunch of disk space - 9 guests have eaten up about 35gb of storage.
    • But, vagrant destroy will clean up most of that pretty quickly
  • You need a bunch of RAM - the more the better. Really.
  • If you’re going to change your Vagrantfile, run vagrant halt (or destroy if the guest name is changing) first as the vagrant command uses the current Vagrantfile to figure out which guests it owns. I did that a few too many times last week and had to go kill a bunch of guests by hand.
  • Don’t reboot your machine with vagrant guests running. They come back up as a bit of a mess.
  • vagrant suspend is your friend, especially for replication and services that run health checks like MongoDB, MariaDB, etc. Just run vagrant resume to get everything back.

Also, if you’re a Rails Machine customer and would like us to help you get moonshine_vagrant setup, just let us know!