Category: Workflow

Virtualized Development, Part 2

This is a follow up to my post, Set up VirtualBox for Web Development, where I describe how to configure a VirtualBox VM with two NICs so that you can develop on a local VM wherever you happen to be. I’m going to describe how to enhance that with a shared folder between your guest and host operating systems so that changes can be immediately reflected with a need to “upload” them to the virtual server.

One of the advantages to working with virtual machines for development is having a sandbox to throw stuff in. Not having to install PHP or MySQL on your local machine is nice, and if something goes wrong, just wipe it and start over (or boot from a snapshot). But wouldn’t it be nice if you could save your files and have the changes instantly reflected on the VM without going through an app like Transmit? I’ve been working with CodeKit recently, and one of the nice features is that it will refresh the browser for you automatically when you save your changes, but if you have to “upload” the files to a VM every time you save, this feature isn’t quite as useful. So, let’s fix that.

A couple of things came together in an interesting way leading up to this post. I’ve been working with CodeKit for a few weeks and it had started to become obvious that my workflow was a little flawed. Uploading to the VM after every save was getting old, even with Dropsend from TextMate. I knew about shared folders between VirtualBox host and guest, but gave up after briefly looking into it because I didn’t know how to install Guest Additions via the command line.

Then, someone showed me Vagrant. It’s an awesome app for automatically provisioning “lightweight, reproducible, and portable development environments.” I had a problem with it though; my MacBook is old and slow. Part of the automatic process is using Chef to essentially set up all the apps you need to run your environment – PHP, Apache, MySQL, etc. Everything went smoothly until Chef started doing its thing, then the CPU would jump to 100% and everything would lock up. I could limit this to 75% of the the host’s CPU if I wanted, but that wasn’t the real issue. I never really gave it a chance to finish, but it took long enough that it would be completely impractical for me to wait that long every time I needed to provision a VM for a new project. So, back to plain VirtualBox.

Let’s do this already!

As I mentioned, there is a way to set up a shared folder between the guest and host – Vagrant does this automatically for you, which is the main feature I was interested in anyway. Once you have the guest OS configured the way you want it, it’s only a few steps to create the shared folder:

First, install Guest Tools.

sudo apt-get install dkms
sudo apt-get install build-essential
sudo apt-get install linux-headers-$(uname -r)
sudo reboot

After the machine reboots, go to the “Devices” menu and click “Install Guest Additions”. This will essentially add Guest Additions as a CD-Rom, just like if you were using a desktop OS, but you have to mount it manually. Then, run the Guest Additions setup.

cd /media
sudo mkdir cdrom
sudo mount /dev/cdrom /media/cdrom
cd /media/cdrom
sudo ./VBoxLinuxAdditions-x86.run

If you haven’t already, you’ll need to shut down the guest to add a shared folder in the VirtualBox settings. From VirtualBox, click on the VM you want to set up, go to “Settings”, “Shared Folders”, and add a new share. Then, mount it with the following, where “yourshare” is the name you gave the shared folder.

mkdir /path/to/mountdir
sudo mount -t vboxsf yourshare /path/to/mountdir

Now you can just save your files into that folder and they will be shared on the guest as well. Eventually, when I get a new machine, I’ll try Vagrant again. This works excellent for me right now though.

Resources

  1. The commands to install Guest Additions came straight from Michael Halls-Moore’s blog.

Update

Instead of mounting the shared folder directly to the path you need it at, you may want to use a symbolic link to take advantage of the auto-mount feature of VirtualBox. When auto-mount is turned on, the folder will be mount in /media as the name you set it up as in VirtualBox, but it will have a prefix of ‘sf_’ in front of it. To create the symbolic link, you would run the following command.

ln -s /media/sf_yourshare /path/to/mount

Set up VirtualBox for Web Development

I’ve used many different development styles through the years. For a while I was a big fan of using Coda to develop live on the server. Recently I’m using more of Textmate and Transmit1. And, while I still like the how fast I can move while writing changes straight to the server, I don’t necessarily want to be doing anything that could potentially break a client’s website — even for a short time. The solution to this is pretty simple; run a virtual machine that acts just like the remote server. You can make your changes and when you’re sure it’s right, you can make one push up to the live site. This probably seems pretty obvious, but I’m going to talk about how I have my VM configured so that it works even on a strange network.

Goal

We want a virtual machine that has a static address that will work even if we pick up and decide to work out of a coffee shop for a day or, say, a warehouse in Northern California. It needs to act just like a production server, which means it also needs to be connected to the web.

Solution

  1. In Preferences, set up a VirtualBox network. Since this particular network is going to be for servers, we won’t worry about turning on a DHCP server. Screenshot
  2. Create a new VM in VirtualBox. I like Ubuntu, but you can use any distro you want. Use whatever specs work for you. It would be a good idea to mirror the production machine you’ll be working with as closely as possible. Don’t worry about networking on the machine yet — that’s next.
  3. Make sure the VM is not running and open its settings. Go to the network tab and verify that adapter 1 is still set for NAT. This is how the VM will access the internet.
  4. Click over to adapter 2. Check the box to enable the adapter and set it to use the network that we set up in step 1.
  5. Start the VM and open the network configuration file. In the current version of Ubuntu this is at /etc/network/interfaces. Make sure you leave eth0 as a dynamic interface and set eth1 as a static interface for your VirtualBox network. Screenshot
  6. Restart the machine and verify that it can access the internet. Also verify that you can access the machine from your host OS on the IP address you gave it.

Something I like to do, just to make this a little easier to work with is to set that address to a local domain in my hosts file. Something like local.dev seems to be popular, but you can name it whatever you want. Obviously if you name it google.com you’ll need to start using Bing or something. ūüėČ

I realize this was a pretty quick overview of the process, so if there’s anything that was unclear, let me know in the comments or shoot me an email.


  1. Textmate with the Transmit bundle really makes Dropsend amazing. If you don’t know what I’m talking about, look for the Transmit bundle for Textmate and check out the secrets of transmit blog post that Panic wrote a while back. 

Setting Up Demos

I like making things as easy as possible, so every time I try to set up a decent “CMS” for doing demos on this site, I end up trashing everything a couple days later. I think I have something that’s useable this time though. It’s roughly based on Chris Coyier’s CSS-Tricks¬†examples section. I think I’ve seen him talk about his method of posting demos before, but I can’t seem to find where that might have been.

Normally, I would turn to WordPress for my online publishing. With all the new features in the past year, WordPress can be form-fit to really anything you could need to publish on the web. I’m going a little simpler than that this time though.

(more…)

Todo.txt to Omnifocus

For a long time now, I’ve been trying to figure out the best way to get stuff into my todo list on my Mac from my Android phone. I should say that I belong to the crazy group that uses OmniFocus, which is obviously a Mac app. They have wonderful iPhone and iPad apps, but I don’t have an iPhone. Sure I could carry an iPod touch around with me everywhere I go and for the most part I do, but my HTC Hero is with me 24/7.

This may not be obvious to everyone, but the best todo list app for Android is Todo.txt Touch by Gina Trapani. This thing almost made me drop OmniFocus, but I really like what I’ve got going in OmniFocus so instead I’m using Todo.txt Touch as input.

I’ve written an AppleScript that will look at my todo.txt file stored in my Dropbox and send everything over to OminFocus:

tell application "Finder"
    -- readFile
    set TodoTXT to "<Path to todo.txt>"
    set foo to (open for access TodoTXT with write permission)
    set txt to (read foo for (get eof foo))
    set eof foo to 0
    close access foo

    set Names to paragraphs of txt
    repeat with nextLine in Names
        if length of nextLine is greater than 0 then

            tell application "OmniFocus"
                set theDoc to first document

                tell theDoc
                    make new inbox task with properties {name:nextLine}
                end tell
            end tell

        end if
    end repeat
end tell

Beware, this is my first iteration of this script. That doesn’t mean I’m promising future versions. I’m only using the Android app as input at this point. It will import all of your todos to the inbox and then blank the file.

Running it

First, Hazel is setup to watch the folder in my Dropbox with a rule that watches for the Created Date to be the same as the Modified Date. This basically means that the file is brand new. It might not be obvious at first why this works. Basically, when the todo.txt file syncs from Dropbox it is replaced with a new version, thus creating a new file in place of the one that was there. When the script then goes and updates the file, either by blanking it or, maybe in the future, updating it with todos from Omnifocus, it is modified locally and not recreated so the two different dates would be different.

The other way I can run the script is from within OmniFocus itself. The script lives in ~/Library/Scripts/Applications/OmniFocus/, which let’s you add it while customizing the menu.

Feedback

If you find this useful, let me know. If you go on to modify it and make it even more useful than it already is, I’d love to hear about that too.

Update

After David Sparks linked here on his MacSparky blog, one user suggested a shorter version of the script:

set p to "<Path to todo.txt>"
set l to paragraphs of (do shell script "grep . " & p)
do shell script ">" & p

tell app "OmniFocus" to tell document 1
repeat with v in l
make new inbox task with properties {name:v}
end repeat
end tell

Thanks for that and thanks to David for linking here.

Reeder Review

It’s been about a week now that I’ve been using Reeder for OSX. Now, the software is still in Beta, but I’m extremely impressed so far.

The first thing I noticed, even before I downloaded it, was that it uses your existing Google Reader account to populate the app. This is huge for me. I’ve tried other desktop RSS readers, but that just doesn’t work for me. In a world where we’re jumping from computer to computer, things like this really need to sync to the cloud. The fact that I can add feeds from this application and see them on the web, and add feeds from the web and see them in this app is one of the things that really makes this so great.

The Interface

I’m a fan of mac apps that look great. I think it’s one of the great advantages of owning a mac — there’s tons of great looking software that is also very functional. Reeder definitely lives up to that. Some people may not appreciate the style forced upon us without the ability to customize the main content, but I think they’ve done a great job with the design. As a designer and web publisher, I feel comfortable both using this as a reader and know this is what my content looks like in a desktop app.

The built in web browser is a nice addition, but I wish there was an option to have all links open in a real web browser. I think the main problem I’m having is the small window you get, so no web site actually fits in the frame. I find that even when I do click a link, I end up at the top of the frame to load the page in chrome.

Do Download

I’d definitely¬†recommend¬†downloading this app now. Don’t let the Beta logo scare you away. Just know that it is in Beta and all the features aren’t 100% flushed out yet. I’ve noticed, for example, that the Add/Manage subscription links don’t work yet — big deal though. You’ve been going to google.com/reader to add new RSS feeds up till now, I think you can wait until that feature works. The first thing you need to do when it’s installed is to turn on automatic updates. I’ve gotten at least three updates since I first downloaded it less than a week ago.