Tag Archives: ruby

Getting inside Cloud Foundry for debug (and profit?)

I’ve recently started to play with some more of the internals of Cloud Foundry than I’ve been used to. This has been made much easier by the advent of bosh-lite, a system for deploying all of Cloud Foundry’s components using the bosh continuous deployment and configuration tool, into a single virtual machine. bosh-lite achieves this by using containers (Cloud Foundry’s own Warden container technology) to “emulate” the individual VMs where jobs would run in a full distributed topology.

bosh-lite has actually been around for a number of months now, but I’ve not had much of a chance to play with it until recently. This is partly due to other activities, and also that my earlier attempts to get an environment up-and-running were hampered by lack of memory. It should be possible to run bosh-lite with a Cloud Foundry deployment in 8Gb of RAM, but given my laptop’s configuration and the amount of other stuff I’m usually running, that was never comfortable – now I’m rocking 16Gb in a MacBook Pro, things are running more smoothly.

I don’t intend to spend this post documenting how to install bosh-lite and get a running single-node Cloud Foundry system. I followed the instructions in the README and things went well on this occasion. One suggestion that I’d make is if you can, to use VMware Fusion (assuming like me, you’re on OS X) and the Vagrant provider for Fusion, seems quite a lot better than Virtualbox. If you do, don’t forget to pass the --provider=vmware_fusion flag when you bring your Vagrant image up (that’s something I do usually forget). One other little thing to mention is that after I started the bosh deployment, the bosh CLI gem timed out and returned a REST error – but the deployment process itself continued without any issues, and I was able to use bosh tasks to check in on the progress. If you are interested, I used cf-release-157 this time around.

Once I had my minty-fresh Cloud Foundry running, I deployed Matt Stine’s handy, simple, Ruby scale demo app and pushed up the number of instances.

So what’s the point of this post? I want to mention two things…

Note: this is not about debugging applications on Cloud Foundry in general – a PaaS is an opinionated system and you generally shouldn’t need to poke around inside it like this. This is for debugging the Cloud Foundry runtime itself, or aspects that might run inside a container. Oh, and I’m sorry about the formatting of some of the shell output examples below!

Peeking at NATS traffic

NATS is the internal, lightweight message bus that Cloud Foundry components use to talk to one another. I’d read blog posts from Cornelia and from Dr Nic about digging into this before.

First of all, I used bosh ssh to access the NATS host:

$ bosh ssh
1. ha_proxy_z1/0
2. nats_z1/0
3. postgres_z1/0
4. uaa_z1/0
5. login_z1/0
6. api_z1/0
7. clock_global/0
8. api_worker_z1/0
9. etcd_leader_z1/0
10. hm9000_z1/0
11. runner_z1/0
12. loggregator_z1/0
13. loggregator_trafficcontroller_z1/0
14. router_z1/0
Choose an instance: 2
Enter password (use it to sudo on remote host): ***
Target deployment is `cf-warden'

Setting up ssh artifacts

Director task 9

Task 9 done
Starting interactive shell on job nats_z1/0

So now I’m on the NATS host – now what? well, strictly speaking I didn’t need to login to that host / container, since of course, as a messaging system, the other hosts can connect to it anyway. The reason I wanted to login to it was to find out how NATS was configured.

$ ps -ef | grep nats
root 1470 1 0 12:09 ? 00:00:12 /var/vcap/packages/gnatsd/bin/gnatsd -V -D -c /var/vcap/jobs/nats/config/nats.conf

$ more /var/vcap/jobs/nats/config/nats.conf

net: ""
port: 4222

pid_file: "/var/vcap/sys/run/nats/nats.pid"
log_file: "/var/vcap/sys/log/nats/nats.log"

authorization {
user: "nats"
password: "nats"
timeout: 15

cluster {
host: ""
port: 4223

authorization {
user: "nats"
password: "nats"
timeout: 15

routes = [


From this, I can see that NATS is listening on IP, port 4222 (the NATS default), and that it is configured for username/password authentication. Handy to know!

I borrowed a little script from Dr Nic, but needed to modify it slightly to talk to authenticated NATS (his original script assumed there was no auth in place):

[update – Dr Nic has provided a more convenient method to do this, in the comments below – check out nats-sub – but this works, as well]

$ ./nats-all.sh
Msg received on [router.register] : '{"host":"","port":8080,"uris":["login."],"tags":{"component":"login"},"index":0,"private_instance_id":"e6194fe8-4910-4cb1-9f7c-d5ee7ff3f36b"}'
Msg received on [router.register] : '{"host":"","port":8080,"uris":["uaa."],"tags":{"component":"uaa"},"index":0,"private_instance_id":"7713dd5b-3613-41a6-9c67-c48f22a769b4"}'
Msg received on [router.register] : '{"dea":"0-1ba3459ea4cd406db833c1d188a78c02","app":"b8550851-37a0-4bd5-bdce-1d787b087887","uris":["andyp."],"host":"","port":61021,"tags":{"component":"dea-0"},"private_instance_id":"b52dfd91d68144cabb14b6c7bae77daae8b493acf1354c99941d49772a1f61fb"}'
Msg received on [router.register] : '{"dea":"0-1ba3459ea4cd406db833c1d188a78c02","app":"b8550851-37a0-4bd5-bdce-1d787b087887","uris":["andyp."],"host":"","port":61025,"tags":{"component":"dea-0"},"private_instance_id":"090f5c5aeee94fdfb4a4e0f0afde2553480dcd97c018431db37b4dffdc80fde4"}'
Msg received on [router.register] : '{"dea":"0-1ba3459ea4cd406db833c1d188a78c02","app":"b8550851-37a0-4bd5-bdce-1d787b087887","uris":["andyp."],"host":"","port":61028,"tags":{"component":"dea-0"},"private_instance_id":"92e10af77b274836a3f54373c9b7feee025c5b72f41a4c4982bde97d241ebd5b"}'
Msg received on [router.register] : '{"dea":"0-1ba3459ea4cd406db833c1d188a78c02","app":"b8550851-37a0-4bd5-bdce-1d787b087887","uris":["andyp."],"host":"","port":61039,"tags":{"component":"dea-0"},"private_instance_id":"86edf0c0a7f84f04b52693b489ad93b7f857f77271b84d568d8f5600b34f7054"}'
Msg received on [router.register] : '{"host":"","port":34567,"uris":["8b24c0a7d28f4e03aa028a3dc89fb8c3."],"tags":{"component":"directory-server-0"}}'
Msg received on [dea.advertise] : '{"id":"0-1ba3459ea4cd406db833c1d188a78c02","stacks":["lucid64"],"available_memory":23296,"available_disk":22528,"app_id_to_count":{"b8550851-37a0-4bd5-bdce-1d787b087887":10},"placement_properties":{"zone":"default"}}'
Msg received on [staging.advertise] : '{"id":"0-1ba3459ea4cd406db833c1d188a78c02","stacks":["lucid64"],"available_memory":23296}'
Msg received on [dea.heartbeat] : '{"droplets":[{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"d92d3c0c43ce4b6981e443e5c2064580","index":0,"state":"RUNNING","state_timestamp":1392639135.9526377},{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"898e632697e246de9cf6b7330444227c","index":1,"state":"RUNNING","state_timestamp":1392639136.3117783},{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"56d023e374aa49d88720daabac58e862","index":2,"state":"RUNNING","state_timestamp":1392639135.2225387},{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"f11d86a7f4ad47f1ad554ae1b087d5f6","index":3,"state":"RUNNING","state_timestamp":1392639136.1042},{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"c9e6de77f0484e6cae47f73ad6ca778a","index":4,"state":"RUNNING","state_timestamp":1392639135.9426212},{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"924c387fc33444289b2db2762eefac42","index":5,"state":"RUNNING","state_timestamp":1392639135.940636},{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"69866b260b1a49a09c03e178c4add2c5","index":6,"state":"RUNNING","state_timestamp":1392639135.944143},{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"94bc605505d94dc1832e55bf2f671a99","index":7,"state":"RUNNING","state_timestamp":1392639135.4456258},{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"8420df9bbe64456385dfa91285641ba4","index":8,"state":"RUNNING","state_timestamp":1392639135.9456131},{"cc_partition":"default","droplet":"b8550851-37a0-4bd5-bdce-1d787b087887","version":"a420d371-0816-4baf-9649-4e21255a66a4","instance":"ed9ad14f6599494c96f90296c59e6041","index":9,"state":"RUNNING","state_timestamp":1392639135.938359}],"dea":"0-1ba3459ea4cd406db833c1d188a78c02"}'
Msg received on [router.register] : '{"host":"","port":8080,"uris":["loggregator."]}'
Msg received on [router.register] : '{"host":"","port":9022,"uris":["api."],"tags":{"component":"CloudController"},"index":0,"private_instance_id":null}'
Msg received on [router.register] : '{"host":"","port":8080,"uris":["login."],"tags":{"component":"login"},"index":0,"private_instance_id":"e6194fe8-4910-4cb1-9f7c-d5ee7ff3f36b"}'

Warden containers and shells

Cloud Foundry’s native container technology is called Warden. When an application is deployed, Cloud Foundry starts up a Warden container based on the limits assigned in terms of memory etc, and the applications run inside that. How can you get “inside” the container to see what is going on?

Well, there are a couple of techniques. Cloud Foundry Loggregator provides streaming access to the standard application logs (stdout/stderr) via the cf logs command. Another option is James Bayer’s cool websocket-based method for getting access to the container. Yet another option is Warden’s own shell, wsh. This does assume you can access the DEA machine with ssh, however.

wsh doesn’t seem to be very well documented, although I knew Cornelia had played around with it – see her excellent blog post on troubleshooting CF and applications, including a great flowchart / graphic suggesting different techniques.

Here’s the secret sauce:

1. Login to the DEA VM (called “runner_z1/0” in the list provided by bosh ssh).

2. Identify your Warden container… there are a lot showing below, but I happen to know that these are several instances of the same app. The important part is the instance-17ij46hadt2 – the second part or that value maps to the location of the container’s private space on disk.

$ ps -ef | grep warden
root        49    42  1 11:41 ?        00:00:41 /var/vcap/bosh/bin/ruby /var/vcap/bosh/bin/bosh_agent -c -I warden -P ubuntu
root      5390 32634  0 12:12 ?        00:00:00 /var/vcap/data/packages/warden/38.1/warden/src/oom/oom /tmp/warden/cgroup/memory/instance-17ij46hadss
root      5503 32634  0 12:12 ?        00:00:00 /var/vcap/data/packages/warden/38.1/warden/src/oom/oom /tmp/warden/cgroup/memory/instance-17ij46hadsu
root      5697 32634  0 12:12 ?        00:00:00 /var/vcap/data/packages/warden/38.1/warden/src/oom/oom /tmp/warden/cgroup/memory/instance-17ij46hadt3
root      6779 32634  0 12:12 ?        00:00:00 /var/vcap/data/warden/depot/17ij46hadsu/bin/iomux-spawn /var/vcap/data/warden/depot/17ij46hadsu/jobs/58 /var/vcap/data/warden/depot/17ij46hadsu/bin/wsh --socket /var/vcap/data/warden/depot/17ij46hadsu/run/wshd.sock --user vcap /bin/bash
root      6780  6779  0 12:12 ?        00:00:00 /var/vcap/data/warden/depot/17ij46hadsu/bin/wsh --socket /var/vcap/data/warden/depot/17ij46hadsu/run/wshd.sock --user vcap /bin/bash
root      6784 32634  0 12:12 ?        00:00:00 /var/vcap/data/warden/depot/17ij46hadsu/bin/iomux-link -w /var/vcap/data/warden/depot/17ij46hadsu/jobs/58/cursors /var/vcap/data/warden/depot/17ij46hadsu/jobs/58
root      6930 32634  0 12:12 ?        00:00:00 /var/vcap/data/warden/depot/17ij46hadss/bin/iomux-spawn /var/vcap/data/warden/depot/17ij46hadss/jobs/59 /var/vcap/data/warden/depot/17ij46hadss/bin/wsh --socket /var/vcap/data/warden/depot/17ij46hadss/run/wshd.sock --user vcap /bin/bash
root      6931  6930  0 12:12 ?        00:00:00 /var/vcap/data/warden/depot/17ij46hadss/bin/wsh --socket /var/vcap/data/warden/depot/17ij46hadss/run/wshd.sock --user vcap /bin/bash
root      6934 32634  0 12:12 ?        00:00:00 /var/vcap/data/warden/depot/17ij46hadss/bin/iomux-link -w /var/vcap/data/warden/depot/17ij46hadss/jobs/59/cursors /var/vcap/data/warden/depot/17ij46hadss/jobs/59
root      6950 32634  0 12:12 ?        00:00:00 /var/vcap/data/warden/depot/17ij46hadt3/bin/iomux-spawn /var/vcap/data/warden/depot/17ij46hadt3/jobs/60 /var/vcap/data/warden/depot/17ij46hadt3/bin/wsh --socket /var/vcap/data/warden/depot/17ij46hadt3/run/wshd.sock --user vcap /bin/bash
root      6955  6950  0 12:12 ?        00:00:00 /var/vcap/data/warden/depot/17ij46hadt3/bin/wsh --socket /var/vcap/data/warden/depot/17ij46hadt3/run/wshd.sock --user vcap /bin/bash
root      6960 32634  0 12:12 ?        00:00:00 /var/vcap/data/warden/depot/17ij46hadt3/bin/iomux-link -w /var/vcap/data/warden/depot/17ij46hadt3/jobs/60/cursors /var/vcap/data/warden/depot/17ij46hadt3/jobs/60
vcap     23713 16807  0 12:26 pts/0    00:00:00 grep --color=auto warden
root     32634     1  0 11:52 ?        00:00:09 ruby /var/vcap/data/packages/warden/38.1/warden/vendor/bundle/ruby/1.9.1/bin/rake warden:start[/var/vcap/jobs/dea_next/config/warden.yml]

3. Head over to the directory for your chosen Warden instance:

$ cd /var/vcap/data/warden/depot/17ij46hadt2

4. Notice that the Warden containers are running as root. If you run wsh now as an unprivileged user, you’ll get a connect: Permission denied error. Time to switch to root, and then run wsh specifying the command to run inside the shell, as a parameter:

$ sudo su -
# cd /var/vcap/data/warden/depot/17ij46hadt2
# bin/wsh /bin/bash

5. At this point, we’re inside the Warden container with a bash shell, and all commands are scoped inside it. So, let’s take a look at what is running:

root@17ij46hadt2:~# ps -ef
root         1     0  0 12:12 ?        00:00:00 wshd: 17ij46hadt2
vcap        29     1  0 12:12 ?        00:00:00 /bin/bash
vcap        31    29  0 12:12 ?        00:00:00 ruby /home/vcap/app/vendor/bundle/ruby/1.9.1/bin/rackup config.ru -p 61031
vcap        32    31  0 12:12 ?        00:00:00 /bin/bash
vcap        33    31  0 12:12 ?        00:00:00 /bin/bash
vcap        34    32  0 12:12 ?        00:00:00 tee /home/vcap/logs/stdout.log
vcap        35    33  0 12:12 ?        00:00:00 tee /home/vcap/logs/stderr.log
root        39     1  0 12:27 pts/0    00:00:00 /bin/bash
root        52    39  0 12:27 pts/0    00:00:00 ps -ef

This is our Ruby app, running on port 61031, and we can see the logs being written as well.

Hopefully this is useful information for folks wanting to dig around inside bosh-lite and a running Cloud Foundry system!


A simple website on Cloud Foundry

I’ve been remiss in blogging since switching job roles, so it’s about time to change that!

One of the goals of a Platform as a Service (PaaS) – like Cloud Foundry – is to enable developers to be more productive, more quickly. It’s about getting out of the way, removing the barriers and setup steps, and enabling developers to write and deploy great code as quickly as possible.

Something I’ve needed to do fairly often since starting work with Cloud Foundry is to quickly put up a “static” web site. The platform supports a number of runtimes and frameworks (Java, Ruby, node.js etc) but it doesn’t currently[1] have an runtime type of “website”. So, I can’t simply put together a bunch of HTML, CSS, images and client-side Javascript files, run vmc push, and have my site online on cloudfoundry.com – I need an “application” to serve the web content.

That’s exactly what my sinatra-static-web project does for me. I’ve found that it’s a very handy and quick template application which enables me to get simple static sites up on Cloud Foundry, and a good starting point to build out from if I want to stretch my Ruby skills 🙂

To use it, simply fork or clone the project using Git; replace the entire contents of the public directory with your HTML, CSS and JS files (with an index.html file as the main page); potentially adjust a couple of settings in the web.rb file; and vmc push the app. You can take a look at the sample site I’ve added to the app, of course… it’s just a load of junk content based on Twitter Bootstrap and with some random Lorem Ipsum-style text to fill it out.

There’s no real need to go near the code, and it is trivial at any rate – but let’s take a quick look.

# a super-trivial Sinatra-based webserver
# for static content
require 'sinatra'

# set all the settings!

configure do
  # this is arguably not necessary... 'public'
  # folder is the static content location by default
  set :public_folder, 'public'

  # optionally configure Cache-Control headers on responses
  # set :static_cache_control, [:public, :max_age => 300]

  # if using mime types not known to Sinatra, uncomment and
  # configure here (by file extension)
  # mime_type :foo, 'text/foo'

# serve the files!

# route to starting page (index.html)
get "/" do
  redirect '/index.html'

# route to custom error page (404.html)
not_found do
  redirect '/404.html'

The code uses the super-handy Sinatra framework for Ruby, which allows an application with multiple URLs to be defined very quickly. In this case, we simply declare a dependency on Sinatra; set the public folder as the one where the static content resides; and then create a default route, so that when a user hits our root URL / they are redirected to the index.html file. We also create an error route so that if the user hits a URL that doesn’t exist, they receive a customised but simple 404 error page (assuming that such a file exists in the public folder!).

As you can see, there’s really only a few lines of code here, and the rest is handled by the framework. I’ve commented out a couple of optional parameters that can be used if desired, but without any changes this will serve the contents of the public folder perfectly happily.

I’ve used this a few times now, for sites of varying levels of complexity – in particular the resources site I created for Cloud Foundry’s sponsorship of Young Rewired State was based on this (the source code is on Github if you want to take a look at that, too – it’s understandably extremely similar!). I was also able to use it to help a number of students who I worked with at YRS 2012 to get their sites online. More on YRS, shortly…

Just a simple little resource that you might find handy for prototyping your next web UI – you don’t even need to know Ruby, Java, or node.js to get going!

[1] … note that I’m not saying that Cloud Foundry should have or will have such a type of container in the future – but the code base is Open Source, so there’s every chance that someone will come along and add this kind of thing one day!

Update 05 March 2013: I just pushed a few changes to the app to reflect a slight change in the way Sinatra apps work on Cloud Foundry now. Use the source!

Unshaved yaks with MonoDevelop (and some pre-shaved ones, too)

This yak is ready to go!There’s a cool Cloud Foundry fan site called preshavedyak.com – and last week at SourceDevCon London, we challenged a bunch of developers to earn themselves a nice new preshavedyak hoodie by registering for a Cloud Foundry beta account and seeing how quickly they could get a “hello world” app up-and-running in the cloud. The event saw a bunch of new signups and some great discussions.

The “pre-shaved yak”, of course, is one aspect of what a polyglot open source PaaS is all about – delivering a ready-made, ready-to-host, application runtime environment. We shaved the yak, so you can just go ahead and get productive with your development tool of choice, be that vi or emacs, Notepad or TextMate, or Eclipse / a.n.other IDE. Grab a micro Cloud Foundry VM image and take your pre-shaved yak with you when you’re not connected! 🙂

I actually started to write this post in order to comment on something that’s a bit more hairy that, though! I’ve been playing around a little bit with MonoDevelop and ASP.NET (for reasons that will become apparent during this week, I suspect). I’m using the current stable Mono (2.10) and MonoDevelop (2.8) packages on Lion, and they seem to work well. I’ve also recently been learning about Sinatra, the lightweight web framework for Ruby, and one of the node.js equivalents called Express. It turns out that the .NET world has a bunch of Sinatra-wannabes, the most popular of which appears to be Nancy (see what they did there…? dive into the world of Sinatra-themed name-related web frameworks…!).

Nancy’s site recommends installation via NuGet, which is evidently really well integrated into Visual Studio (NuGet is the equivalent of gem in Ruby, or npm in node.js). Unfortunately there’s no MonoDevelop equivalent. Here’s where the yak shaving started! The NuGet FAQ claims that the command line NuGet.exe will run and can be compiled under Mono, but in my experience, that’s not quite true – I could not get the source to compile in MonoDevelop on OS X. I grabbed the pre-compiled version and followed the instruction to get it to update itself (basically you just run it, and it bootstraps and downloads the latest available)… that went fine, but after that, it would no longer work and produced a huge stack trace.

So here, after getting most of a yak’s fleece all over me, is the secret. The prebuilt NuGet.exe will work under Mono on OS X, but it does require a Windows .NET 4.0 DLL (Microsoft.Build.dll) to be in the same directory / locatable in the path – I grabbed mine from my Windows VM install. It also requires that you tell Mono to present a v4.0 runtime. So I whipped up a tiny script to avoid having to type a bunch of paths and switches each time.

Further results of this recent dalliance in .NET land will be coming soon…

Ubuntu 12.04 and Cloud Foundry

Well, it’s that fun Ubuntu release day again, and around the world, I’m sure there are parties aplenty…

I grabbed an ISO this morning (64-bit desktop version, natch), and quickly setup a new virtual machine to run on my Mac. A nice feature of VMware Fusion 4.0 is the “easy install” option which lets you rapidly pop in the basic information needed to setup the system, and the rest is taken care of for you.

In my case, I specified a user ID, selected that I wanted my home folder read/write shared into the VM, and then customised the machine to up the memory and add a CPU core. In a few minutes (my machine has an SSD…!) I had a new virtual machine, running full screen in a separate space on Mission Control. Fusion even took care of installing VMware Tools so it was able to do the file sharing, use the full screen resolution etc etc straight away.

So… first impressions? Much more slick than 11.10 which I was using on a daily basis until recently. In particular, the configuration options have been streamlined really nicely. I’m still struggling with discovery of applications in Unity but in general, it’s not bad at all.

Browsing through the available packages, I was interested to find that the Cloud Foundry tools are available in the default repositories:

Cloudfoundry client

That’s awesome! you can just run sudo apt-get install cloudfoundry-client and get the main tool for deploying apps and administering Cloud Foundry right from the repository using the regular apt method (actually this is simply a convenience package – under the covers it installs a package called ruby-vmc, which installs the vmc command-line Ruby gem… it’s nice that the Ubuntu guys have made it easier to discover, though).

So what’s the problem? Well – no big deal, but actually, if you want to keep up with Cloud Foundry as a developing platform, you might want to grab something slightly newer than what is available on tap in the repository. As I write this, the version of vmc available via the cloudfoundry-client package is 0.3.10 and the one we’re currently working with is at least 0.3.16.

My suggestion, therefore, is to do the following:

  1. Install rvm (Ruby Version Manager). That way, you can have different versions of Ruby itself installed, manage gems for the different versions independently, and also – importantly – not require root privileges to do your development work and install additional gems. A handy guide to installing rvm on Ubuntu is here, and it still works fine on 12.04. Just follow the commands shown in the Installing RVM and Installing Ruby sections and you should be all set and rocking ruby-1.9.2 on your new 12.04 setup.
    (I’m using rvm and JewelryBox to manage Ruby versions on OS X, incidentally. Great tools)
  2. Run either gem install vmc or gem install vmc --pre (the latter option will get you the very latest pre-release of vmc, if you like the bleeding edge). Note that, if you installed rvm and Ruby successfully, you should not need root permissions to install gems.
  3. There is no step 3 — vmc target http://api.cloudfoundry.com and then vmc login and you should be good to go. Looking for a sample app to deploy? You could take a look at the Sinatra example I added to the cloudfoundry-samples repository on Github last week…

It’s fantastic that Ubuntu is moving towards strong desktop / development environment support for Cloud Foundry.

Oh, there’s another story with Precise Pangolin,  too – you can rapidly install the server side pieces to build your own cloud using the Juju Charms which provide Cloud Foundry support. But… that’s a story for another post, in another time and place…. 🙂

Update 15/05: I raised bug #998111 against Ubuntu to ask for the ruby-vmc package to be updated, in case you feel like tracking progress via Launchpad.