Per virtual machine, vagrant uses a directory with a
Vagrantfile in it. As
a convention, I place my vagrant directories as subdirectory inside
~/vm/. The name of the subdirectory (I’ll use “django” as an example in
this blog post) is the name I use for the virtual machine. So
~/vm/django/Vagrantfile is the vagrant file for my “django” virtual machine.
I have one other (“barebones”), but I already know I’m also going to make a
“php” one for three mysql/php sites that I sometimes do a bit of work
on. Those end up in
~/vm/php/ and so.
Everything that’s not in git (/svn/hg/bzr) doesn’t exist, so I’ve versioned my
~/vm/ directory. I ignore (
.gitignore) the django/php/barebones
Vagrantfiles in those directories are symlinks to
~/vm/vagrantfile_django and so on. There’s a
README.txt to help me
set it all up when I move to a new computer.
I also have a fabfile for setting up the (django) box automatically. Some of the things the fabfile does:
I edit my code locally on OSX and I prefer to continue doing that. I also sometimes want to copy downloaded files directly to my source code. Or edit images in an OSX image editor.
So: I want to have some part of my directory structure available both in OSX
and inside the virtual machine. I’ve handled that in my
file is mostly the vagrant-provided default one. The relevant filesystem line
# Share an additional folder to the guest VM. The first argument is # an identifier, the second is the path on the guest to mount the # folder, and the third is the path on the host to the actual folder. config.vm.share_folder "v-data", "/vagrant", ".", :nfs => true
This mounts the
~/vm/django/ folder on OSX to
/vagrant/ inside the
virtual machine (with NFS), making them available on both. I checkout my
source code in
/vagrant/some_category/some_project on the virtual machine,
which ends up as
~/vm/django/some_category/some_project on OSX.
Note that I use checkoutmanager to create and update my svn/git/hg checkouts, so it was simple for me to split its configuration. I have a separate checkoutmanager config for my django virtual machine and one for OSX.
Vagrant provides a
vagrant ssh command that gives you an ssh shell for the
virtual machine in whose directory you are. But I don’t want to
cd to a
directory first. So I set up a hostname and ssh config for my virtual
machines. I can do
ssh django now to get inside my virtual machine.
126.96.36.199 django 188.8.131.52 barebones 184.108.40.206 php
Host django HostName 220.127.116.11 User vagrant ForwardAgent yes Host barebones HostName 18.104.22.168 User vagrant ForwardAgent yes Host php HostName 22.214.171.124 User vagrant ForwardAgent yes
User line logs me in as user “vagrant” even though I’m “reinout”
in OSX. And “ForwardAgent” lets me re-use my ssh key if I connect to servers
from within the virtual machine.
I have emacs (emacs server) running all the time and open files in emacs from
the commandline. And I want to do
git add from the commandline. So
I want to be inside the actual OSX source directory when working, not
inside some ssh session inside the virtual machine: I cannot access my OSX
emacs from there.
All fine, as I’ve set up my directories the right way (see above).
But... what about running commands? Starting django? Running a buildout? I need to do that inside the virtual machine: that’s why I set it up in the first place.
That’s where a tiny utility I made comes in. I use fabric quite a lot. Fabric allows you to execute commands
remotely via ssh. Hey, that’s just what I need. I know my own conventions for
filesystem placement, so I can figure out whether my shell is inside a vagrant
~/vm/django/somewhere/) and how to map that to a directory
/vagrant/somewhere/) inside the right virtual machine (“django”).
~/vm/django/utils/checkoutmanager $ vc bin/test [django] Executing task 'run_cmd' [django] run: bin/test [django] out: Running tests at level 1 [django] out: Running zope.testing.testrunner.layer.UnitTests tests: [django] out: Set up zope.testing.testrunner.layer.UnitTests in 0.000 seconds. [django] out: Running: [django] out: ......................... [django] out: Ran 25 tests with 0 failures and 0 errors in 0.044 seconds. [django] out: Tearing down left over layers: [django] out: Tear down zope.testing.testrunner.layer.UnitTests in 0.000 seconds.
It runs the
bin/test command inside the correct directory inside the
correct virtual machine.
As an extra proof, here’s the
pwd (“print working directory”) command output:
~/vm/django/utils/checkoutmanager $ vc pwd [django] Executing task 'run_cmd' [django] run: pwd [django] out: /vagrant/utils/checkoutmanager
Works like a charm!
I’m pretty happy with my setup and with vagrant. It took a few days of finding
out the right way to use it, but I’m settled now. The
vc command coupled
with a good filesystem layout works fine in practice.
And I’m happy that I can now use ubuntu to manage all those pesky OS-level dependencies! And that I can still use all the OSX goodies.
My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):