Skip to content

Terraform and OpenStack: Boot an instance from CD-ROM

In the spirit of "this took me way too long", here's how to boot an instance with a CD-ROM on OpenStack, using Terraform.

Why would I need this?

In a perfect world, I have templates to bootstrap instances. Means, the instances are ready to go when booted. I customise them with cloud-init and let them do all kinds of cool (or necessary) stuff like configuring the network, setting hostnames, adding user accounts and then maybe joining them to a cluster.

But I don't live in a perfect world, still: I try to automate as much as I can. So I don't have to remember any of it.


The use-case is the installation (or setup) of a SoPhos firewall. The vendor provides me with an image which can be booted and then an installer and setup wizard have to be completed to finish the installation process.

Using Terraform

Let's look at the code first - the following is used to create the instance:

resource "openstack_compute_instance_v2" "vpn_host" {
  depends_on = [

  name        = "vpn"
  flavor_name = "dynamic-M1"

  security_groups = [

  # boot device
  block_device {
    source_type           = "blank"
    volume_size           = "100"
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = false

  # cd-rom
  block_device {
    uuid             =
    source_type      = "image"
    destination_type = "volume"
    boot_index       = 1
    volume_size      = 1
    device_type      = "cdrom"

  network {
    port =

  network {
    uuid =

I am omitting some code, but let's walk through this.

How to CD-ROM (block_device)

I am approaching this in reverse order — let me talk about the second block_device block first.

This is the bit that took me the longest because I didn't know how disk_bus or device_type play well together. Or which of the two is needed.

The moral of the story is, if the Terraform provider documentation is too vague, read OpenStack's documentation on device mapping instead. Or in your case, you are reading my blog post! :-)

To continue, the image of the SoPhos firewall is referenced by Therefor, I have a data provider which pulls the image from OpenStack (or Glance):

data "openstack_images_image_v2" "vpn_image" {
  name = "fancy readable name of the ISO here"

During terraform apply Terraform will try to resolve it. If successful its result will be used to create a (Cinder) volume from it. The "1 (GB)" size of the volume is what OpenStack suggested when I did this via the fancy web UI. Therefor, I used it in my Terraform setup.

The important part of the block_device block is device_type = "cdrom". Without it OpenStack will refuse to boot from the volume even though we provide a boot_index.

Small caveat: I had to add a depends_on as Terraform's dependency graph would not wait for the data provider to resolve during apply.

Boot device

Last but not least: I also need a bootable root partition to install to, and that's the first block_device block in my code snippet.

If all goes well, the provisioning is as follows:

  1. OpenStack starts the instance
  2. It discovers that the first disk is not bootable (yet)
  3. It proceeds with the CD-ROM (attached to /dev/hda in my case).

After the installation is finished, subsequent reboots of the instance always use the first disk. This is similar to dropping a CD into a (real) server, installing it (from the CD) and leaving the CD (in the drive) at the data center (just in case). :-)

The rest

The rest is hopefully straight forward.

I defined two other networks (with another Terraform run) which are used via data providers.

One is used as a port (for fixed IP allocation/configuration, and the other provides the VPN instance with another accessible IP for dial-in and remote management from the public network (via


Thanks for reading.

Foursquare: How private is private?

Location is one of my hobbies. Even though I don't map items for openstreetmap and the like, I still try out at least every location-related startup there is.

Foursquare, as you probably know is a location-based game — get points and badges to check into locations. The points are aggregated into weekly leaderboard (of penis envy) and everyone gets a fresh start every Monday morning.


Foursquare has different check-in modes. One is the regular, where your location gets published to your friends (and also Twitter/Facebook if those are linked up) and the other is called "off the grid" — supposedly not even your friends know where you're at.

Think of a possible scenario — cheating on your diet? You can still check into McDonald's and get the points but your boyfriend wouldn't know you did it.


Is off the grid really off the grid? Far from it.

If you play Foursquare on a more national or global scale (e.g. between cities) even though you check in off the grid, your general location is updated on your profile.

So let's say I went from Berlin to Munich and didn't want anyone else to know. I still check in off the grid at the airport in Munich (to get a stupid badge or whatever) and my Foursquare profile would not show where I exactly I checked in (e.g. airport), but it would say "Till (Munich)".

From what I noticed the other week, if you checked into a venue and did off the grid, it would still show your icon on the venue's page on Foursquare, which doesn't really sound like advertised either.

So how is that check-in actually private? Well, not at all.

Location without a check-in

But wait, it gets even better!

I noticed that Foursquare's Android and Blackberry applications update your location without checking-in. From what I gathered, it's plenty to look at your friend list and sure as hell enough to scan for places around you (to get caught ;-)).

Friend list

The friend list always shows people from the city you're in. So as soon as you open the application, it displays those. Whenever you leave the city, it'll say something like, "Friends in other cities" — and "Viola!", your profile got updated.

All of this is powered by the GPS tracking in your nifty phone. Pretty cool, eh?

Scanning places

Last weekend I went to Chemnitz to attend a family thing — even though didn't check in anywhere, I briefly scanned to see who and what was around me. Still, my profile got updated.

Foursquare: my history

The above shows two check-ins, Jet is in Berlin (gas station) and Aral is near Dresden (another gas station — but don't worry, I just bought a magazine and took my dog for a walk — didn't need to fuel up).

And here's a shot of my profile, which clearly states I'm in Chemnitz:

Foursquare: my profile

I guess I should have expected it, but I'm still not sure if I like it. The upside is, it's pretty accurate too (note, sarcasm)!

And in case anyone got doubts — I'm sure someone with elite jedi powers from Foursquare can verify that I didn't cheat.


I think the biggest mis-conception here is that I expected Foursquare to share my location only when I do something using the application or the website. I'd really like it to be a more active thing when my profile is populated with data. On the other hand, that's probably inconvenient as hell for … Foursquare?

Further more

I haven't really checked into this any further, but does anyone know if the Foursquare applications use background data?

I would like to how much of my location is shared on a regular basis and also how granular the data gathered is, e.g. Foursquare only updates the city/country on your profile, but do they really keep latitude and longitude?


Not the usual programming bs. :-) And that's all for today.

If in doubt about your data, you should disable location based services.

The very least you can do is to learn enough about them in order to understand (and comprehend) what's happening with your data.

EC2 security group owner ID

I recently had the pleasure to setup an RDS instance and it took me a while to figure out what the --ec2-security-group-owner-id parameter needs to be populated with when you want to allow access to your RDS instance from instances with a certain security group.

To cut to the chase, you need to log into AWS and then click the following link — done.