diff --git a/scripts/deploy.js b/scripts/deploy.js
index 45ff83610f0adac0f2cb2a6e075113747af55e0a..5ff7dfc9045c792f8f0c3e1c6c55a998605faf73 100755
--- a/scripts/deploy.js
+++ b/scripts/deploy.js
@@ -28,14 +28,36 @@ function printInstructions(name, deets) {
   console.log("enjoy!  Here's your server details", JSON.stringify(deets, null, 4));
 }
 
-verbs['deploy'] = function(args) {
+function validateName(name) {
+  if (!/^[a-z][0-9a-z_\-]*$/.test(name)) {
+    throw "invalid name!  must be a valid dns fragment ([z-a0-9\-_])";
+  }
+}
+
+verbs['destroy'] = function(args) {
   if (!args || args.length != 1) {
     throw 'missing required argument: name of instance';
   }
   var name = args[0];
-  if (!/^[a-z][0-9a-z_\-]*$/.test(name)) {
-    throw "invalid name!  must be a valid dns fragment ([z-a0-9\-_])";
+  validateName(name);
+
+  process.stdout.write("trying to destroy VM for " + name + ".hacksign.in: "); 
+  vm.destroy(name, function(cb, err) {
+    console.log(err ? "failed: " + err : "done");
+    process.stdout.write("trying to remove DNS for " + name + ".hacksign.in: "); 
+    dns.deleteRecord(name, function(cb, err) {
+      console.log(err ? "failed: " + err : "done");
+    });
+  });
+}
+
+verbs['deploy'] = function(args) {
+  if (!args || args.length != 1) {
+    throw 'missing required argument: name of instance';
   }
+  var name = args[0];
+  validateName(name);
+
   console.log("attempting to set up " + name + ".hacksign.in");
 
   dns.inUse(name, function(err, r) {
diff --git a/scripts/deploy/vm.js b/scripts/deploy/vm.js
index f6f33825c39b5c57b71332f2583d1644a67433c9..d07c0606b10a6dd8abdd1bc1a36e39dd2aee1bb7 100644
--- a/scripts/deploy/vm.js
+++ b/scripts/deploy/vm.js
@@ -4,7 +4,7 @@ jsel = require('JSONSelect'),
 key = require('./key.js'),
 sec = require('./sec.js');
 
-const BROWSERID_TEMPLATE_IMAGE_ID = 'ami-1f14c576';
+const BROWSERID_TEMPLATE_IMAGE_ID = 'ami-bb1ccdd2';
 
 function extractInstanceDeets(horribleBlob) {
   var instance = {};
@@ -13,22 +13,43 @@ function extractInstanceDeets(horribleBlob) {
      if (horribleBlob[key]) instance[key] = horribleBlob[key];
    });
   var name = jsel.match('.tagSet :has(.key:val("Name")) > .value', horribleBlob);
-  if (name.length) instance.name = name[0];
+  if (name.length) {
+    instance.fullName = name[0];
+    instance.name = name[0].replace('browserid deployment (', '')
+                           .replace(/\)$/, '');
+  }
   return instance;
 }
 
 exports.list = function(cb) {
   aws.call('DescribeInstances', {}, function(result) {
-    var instances = [];
+    var instances = {};
+    var i = 1;
     jsel.forEach(
       '.instancesSet > .item:has(.instanceState .name:val("running"))',
       result, function(item) {
-        instances.push(extractInstanceDeets(item));
+        var deets = extractInstanceDeets(item);
+        instances[deets.name || 'unknown ' + i++] = deets;
       });
     cb(null, instances);
   });
 };
 
+exports.destroy = function(name, cb) {
+  exports.list(function(err, r) {
+    if (err) return cb('failed to list vms: ' + err);
+    if (!r[name]) return cb('no such vm');
+
+    aws.call('TerminateInstances', {
+      InstanceId: r[name].instanceId
+    }, function(result) {
+      console.log(result);
+      try { return cb(result.Errors.Error.Message); } catch(e) {};
+      return null;
+    });
+  });
+};
+
 function returnSingleImageInfo(result, cb) {
   if (!result) return cb('no results from ec2 api');
   try { return cb(result.Errors.Error.Message); } catch(e) {};