Programmatically creating DigitalOcean Products and Services

How you can use Pulumi to create DigitalOcean droplets and more!

August 30, 2021

DigitalOcean

Pulumi

Pulumi is a tool which is used to programmatically create and manage software infrastructure. Pulumi is written in languages such as Javascript and Python, and this is something we can take advantage of to programmatically create services.

With Pulumi - you can use it with Node to create products and services for cloud providers, as well as using things like NPM packages or other Node tools.

Pulumi allows you to create a large range of resources for DigitalOcean - you can view the full reference guide here: https://www.pulumi.com/docs/reference/pkg/digitalocean/

What Are we Making?

In this post we're going to do a few things:

  • Create a Droplet
  • Create an SSH Key so we can access the droplet
  • Add the Droplet to a new Project in DigitalOcean

Getting Everything set up

The first thing would be to install Pulumi itself - you can do this by running either choco on Windows, or brew on Macs

# Windows
choco install pulumi
# Mac
brew install pulumi

You can view the full install guide on Pulumi's website. https://www.pulumi.com/docs/get-started/install/

The next thing we need to do - is setup our project.

Project Setup

In a blank folder, create a Pulumi.yaml file - this will define the details of our project - as well as which runtime we're using. In our case, that would be node.

# Pulumi.yaml

name: 'Pulumi Test'
runtime:
  name: nodejs

Stack Setup

One advantage of programmatically generating infrastructure is that you're able to easily replicate it for different environments.

To create a new production stack - you can run:

pulumi stack init production

This would also switch the current stack in the terminal to production.

API Access

The last thing we need to do setup wise is to get an API token from DigitalOcean, this would allow Pulumi to create API requests to DigitalOcean.

From within the DigitalOcean account - select "API" in the bottom right, and then select "Generate new Token"

Screenshot of the DigitalOcean Applications & API page

After selecting the button - enter in a name for the token (I just chose "Pulumi"), and ensure that the "Write" option is checked. Select "Generate Token" and you should see your newly created token on the page.

Make sure you copy this token, as it would only be shown once!

To give the token to Pulumi - you can set it two ways:

The first is by an environment variable:

export DIGITALOCEAN_TOKEN=TOKEN_VALUE

Or the alternative would be to set it within Pulumi itself. You can do this by running:

pulumi config set digitalocean:token TOKEN_VALUE --secret

Make sure to use --secret so it's encrypted!

Creating A Droplet

Now that everything is setup, create an index.js file, and import Pulumi, and use the Droplet class to define a droplet.

// index.js
const pulumi = require('@pulumi/pulumi');
const digitalocean = require('@pulumi/digitalocean');

const droplet = new digitalocean.Droplet("Test Droplet", {
  size: "s-1vcpu-1gb",
  image: "ubuntu-18-04-x64",
  region: "lon1",
});

Next, in the terminal run pulumi up - This will go through everything in our index file, and figure out what would need creating or changing.

In our case - you should see our new droplet being created! Select "No" for now, because we need to do one other thing before we create it.

Adding an SSH key

So that we can access the Droplet easily once it's been created, we can add an SSH key to it.

First - create an SSH key, and save the public key on your machine. However, you need to be careful in the format you save it, DigitalOcean will only be expecting a single line, without the headers, an example of this would be ssh-rsa XXXXXXXXXXXXX.

You'll also need to save the private key on your machine so you can use it to access the droplet via SSH later.

Once that's done, we can use fs to read the public key, and use Pulumi to create it in DigitalOcean, and add it to our Droplet:

// index.js
const pulumi = require('@pulumi/pulumi');
const digitalocean = require('@pulumi/digitalocean');
const fs = require('fs');

const sshKey = new digitalocean.SshKey('default', {
  publicKey: fs.readFileSync('path/to/key').toString()
})

const droplet = new digitalocean.Droplet("Test Droplet", {
  size: "s-1vcpu-1gb",
  image: "ubuntu-18-04-x64",
  region: "lon1",
  sshKeys: [sshKey.fingerprint]
});

If you'd like to re-use an existing SSH key from the DigitalOcean environment, you can use getSshKey from Pulumi.

Now then, running pulumi up will again tell us what is being created, and as well as our droplet from before, you should also see the new SSH Key!

This time, we'll allow Pulumi to run everything, by selecting "Yes" - waiting a few minutes should see a new Droplet and SSH key created within DigitalOcean!

Adding The Droplet To A Project

The last thing we need to do is add the new Droplet to a project - this can be done by creating a Project and adding our droplet to the resources

const project = new digitalocean.Project('Pulumi', {
  description: 'Programmatic creation of a droplet with Pulumi',
  resources: [
    droplet.dropletUrn,
  ]
});

Running pulumi up again, and selecting "Yes" - you should see our new project that will be created, but will notice that our Droplet hasn't been listed, this is because no changes would be made to it.

Now you should be able to see our "Pulumi" project, and it should have our Droplet inside it!

Cleaning Everything Up

One advantage of writing architecture programmatically - is that it also tends to be easy to clean up everything once you're done.

With Pulumi - you can run pulumi destroy to destroy everything we've made.

Final Thoughts

Pulumi is a great resource to programmatically create infrastructure. It's great you can take benefits of Node and apply them to creating services.