This past week I have spent working on getting the workhammer project in a state where it could easily be run by other people on other environments (i.e. not requiring virtualenv and a Unix file system). The best solution for this is to use vagrant and one of the provisioners to automate the creation of a headless virtual machine with the correct services installed and set up, much like the production environment that will be used.
The great part of vagrant is that it utilizes various types of virtual environments,
I am currently focussing on VirtualBox as it is free and regularly used by most
developers I have worked with. But most of this can be switched to using VMWare,
AWS, or any other type of provider. Vagrant should also be able to be dropped and
you could just use the provisioning scripts to initialize a real machine for your
environment. All of this means that once I finished these scripts, anyone can have
a “bug free” (famous last words) environment up in running by just running the
vagrant up
command (as long as they have vagrant installed). That single command
will download a base box, initialize a copy in the project folder, then begin
running the provisioning scripts that will symlink (vagrant specific) the project
directory into /opt/
, install mongodb, install nginx, install
supervisord, then set up a conf file to host the application via nginx and auto
start it via supervisord. Then, after running all of that, you just need to hit
a specific port (:8080) and the site is hosted. The code no longer needs to worry
about someone trying to run it on Windows or remind the user to install mongo. You
don’t have to figure out weird bugs with having nginx start doing the static hosting
when you move into prod or teach everyone how to setup nginx and write a virtual
host config. All of the headache is gone.
For the provisioning, I am using puppet, which is a very powerful tool for
uniformly setting up machines for a specific environment. With puppet, I have it
installing and setting up nginx plus a class that handles creating virtualhost
files and setup nginx to begin serving these immediately. I wrote a module for
nginx that encapsulates this (and allows for me to cp
the folder to new projects
to quickly add nginx to the box). The same was done for mongo and supervisor, so
the only custom puppet script just sets up the basic environment specific to
the project. This includes the 3 modules I wrote, then installs the python stuff
for the environment. If the script is run via vagrant (the $vagrant
variable is
set in the Vagrantfile) it will symlink the project folder (which is mounted by
default in /vagrant/
to a folder in /opt/
. After this, the dependencies that
are defined in the requirements.txt
file are installed via pip. I use good
practices and created a user that is used for running the application. Finally the
application is added to the supervisord and nginx services so that they now handle
starting it up as a daemon and hosting it via a proper web server.
With all of this work, I can easily spin up a new development environment with the
vagrant up
command (I did yesterday when creating a box to demo the code) and if
I have messed it up, I can destroy the box and spin up a new one that will go back
to the vanilla setup. Other developers that want to work on this codebase can also
just pull the code and run the command and get a copy of the same environment I am
running the application out of. I feel like I will be using this pair of tools for
all of my future projects (and hopefully professionally as well). It removes all of
the headaches of dealing with different environments for every developer and trying
to keep the code from polluting the global environment on another machine.