// LEARN LINUX TV • ARTICLE

How to Automate DigitalOcean with Kestra 2.0 (Full Tutorial)

Kestra 2.0 is here, and in this tutorial I’ll show you how to automate DigitalOcean with it. We’ll walk through the brand new DigitalOcean plugin, build our Kestra flow, and add inputs so the flow can be reused with different values. If you’ve been looking for an open-source way to automate your cloud infrastructure, this one’s for you!

YouTube player

Video-Specific Links

New features in 2.0

And to catch up from last time, version 2.0 of Kestra is here. It’s actually the largest update in the history of the project. The execution engine was completely rewritten, the UI was redesigned, MCP for AI integration, which can help you deploy resources even faster. And to keep up with that, version 2.0 of Kestra also includes Agent governance, which helps you limit the types of things that can be created through MCP.

Any flow you’ve already written can be exposed as an MCP tool. So the thing you built to rebuild a VM – Claude or Cursor can now call it by name. You’re not giving an AI shell access to your infrastructure; you’re giving it a specific button you wrote, tested, and version-controlled.

The agent itself is just YAML. Model, tools, memory, system prompt – all of it in the same repo as everything else, reviewed in a pull request like any other change. If you already do GitOps, an agent is just another file in it.

The AI plugin is licensed with Apache 2.0, even in the open-source edition. So this isn’t an enterprise-specific feature, everything I’m about to show you runs on the same free version we’ll be using shortly.

Here’s something else that’s pretty cool. In 2.0 the workers are stateless – they’ve got no database connection of their own, they just talk back to the Kestra server over gRPC. As a result, your firewall rules get a lot simpler, because you’re allowing one outbound connection instead of exposing a database. And the workers never hold database credentials, so a compromised worker won’t lead to a database reach. And that’s what makes running them in an air-gapped or heavily restricted network actually practical.

All of that, on top of a platform that’s already solid. Kestra is 100% open-source, licensed through Apache 2.0. 

In addition to version 2.0, another new development around Kestra is that they’ve joined the DigitalOcean partner program. As part of this partnership, a new plugin was introduced that lets Kestra manage DigitalOcean resources, such as Droplets, DNS, Firewalls, Kubernetes, and more. This extends Kestra’s functionality even deeper into the cloud, adding DigitalOcean to its list of supported platforms.

In fact, what we’re going to do is actually use see this plugin in action today, as we automate deploying Droplets within Digital ocean during the next section.

Learning Lab Overview

And we’ll start with the most important part of any project – the planning phase. We’ll define our goal, and also the resources we’ll need on hand to be successful.

When it comes to our goal, as I mentioned earlier we’re going to build a Flow within Kestra that will automate the deployment of Droplets over on Digital Ocean. And for those of you that haven’t ever used Digital Ocean before, “Droplet” is just the platform’s fancy terminology for “Server”, but I digress.

Anyway, ultimately our goal is probably something more specific than just simply “creating a server”. Perhaps we want to automate the deployment of servers attached to a specific private network subnet complete with appropriate firewall rules. And yes, Kestra can do all of that, but let’s start small and focus on the foundation. For now, our goal is simply to create a Flow that can create Digital Ocean droplets. We can always expand and build on this in the future.

With that out of the way, what do we need for our project? The first thing we’ll need is a Kestra installation, which I showed you how to build in the first video, and you can always come back to this video once you have it set up.

Also, you’ll need an account over on Digital Ocean. You can use your existing account if you have one, or you can set up a new one. You can use the affiliate link in the description below if you want to help support the channel, but that’s not required and makes no difference for this tutorial. And as an aside, I should probably mention that Digital Ocean is not currently a sponsor of this channel, and they had no input on this video.

Next, you’ll need an API key as well. You can generate one by visiting the AP section of Digital Ocean’s dashboard, and you can generate a new one right there. Just give it access to manage Droplets, save the key in a safe place, and that’s all you’ll need from that side of things.

As for me, for this tutorial I created a brand-new Kestra instance to use as our demo.

Again, if you haven’t set up Kestra yet, check out my first video. I’ll show a URL on the screen right now that will take you right to it. 

For the new server I built, I deployed Kestra on Ubuntu 26.04 this time around, for no other reason than I probably feature Debian a little too often. It doesn’t impact our project anyway, since Kestra runs in a container so the underlying distro doesn’t really matter. Just about anything that can run Docker containers can run Kestra.

When I installed it, I set it up pretty much the same way as last time. I downloaded Kestra’s Docker compose file, and mad e a few small tweaks. The first of which was to set up basic authentication in the highlighted section. I didn’t mind my credentials being in plain text, because this is just a demo and not a production instance.

The other change I made was to add a Base64 encoded version of my Digital Ocean API key, which is in the highlighted section you see here. If you haven’t encoded a string that way before, all you have to do is run a command similar to the following:

echo -n "xxxx" | base64 -w0

In this case, you’ll simply replace the X’s with your actual Digital Ocean API key, and it’ll return the base64 version of the key. Then, you can add a config line like mine to your Docker compose file, and when you build Kestra it’ll be aware of that key. If you’ve already deployed Kestra, you can simply run the docker compose command again:

docker compose up -d

Note that this is not a destructive command, it won’t wipe out your existing configuration. To be on the safe side though, you should always have a backup of your important configuration anyway.

Building our Flow

Now that we have the foundation all set, let’s start building! What we’ll do is go to the Flows section, and create a new one. I’ll paste mine in right here:

id: digitalocean_create_droplet_flow
namespace: dev.digitalocean
tasks:
  - id: create_droplet
    type: io.kestra.plugin.digitalocean.droplet.Create
    apiToken: "{{ secret('DIGITALOCEAN_TOKEN') }}"
    name: "srv-new"
    region: "nyc3"
    size: "s-1vcpu-1gb"
    image: "ubuntu-26-04-x64"

Breaking it down, we first give our Flow an ID. This must be unique, so you can come up with a name of your own. Be sure to settle on a naming convention before you save your file though, as this can’t be changed once you set it.

For the namespace, you can think of that as essentially a folder. This is how you can group related flows into one container, so for example if you manage multiple companies you could set up Flows for each in their own respective namespace, to keep them separate. Like the ID field, the namespace is also immutable and can’t be changed.

Continuing, we’re going to create a droplet, and we’re going to use Kestra’s official Digital Ocean plugin to do it. We’ll use the Create task within that plugin, and the API token will be set from the base64 encoded key we integrated into our build earlier.

After that, we can set values for the name of the instance, the region it’ll be created in, its instance size, image and so on. Feel free to adjust these values accordingly based on what you’re creating or where. For the name, that’s the actual name of the resulting VM itself. I went with new-server which makes it very obvious it’s a fresh deployment that’ll likely need additional tweaking.

But you know what? Let’s make this Flow a bit better. In a way, we’re creating a bit of work for ourselves. We’re hard-coding the image and region, which are fields that can change depending on your goal. So I’ve adjusted this flow to provide drop-downs for some of the values, so you can get even more usage out of one single flow.

I’ll paste in the code, and I’ll go over a bit about what’s changed:

id: digitalocean_create_droplet_flow
namespace: dev.digitalocean
inputs:
  - id: dropletName
    type: STRING
    description: "Enter the name for the droplet."
    displayName: "Droplet Name"
  - id: dropletImage
    type: SELECT
    description: "Select the image for the droplet."
    values:
      - "ubuntu-26-04-x64"
      - "debian-13-x64"
      - "fedora-44-x64"
    defaults: "ubuntu-22-04-x64"
  - id: dropletRegion
    type: SELECT
    description: "Select the region for the droplet."
    values:
      - "nyc1"
      - "nyc3"
      - "sfo3"
      - "ams3"
      - "sgp1"
    defaults: "nyc3"
  - id: dropletSize
    type: SELECT
    description: "Select the size for the droplet."
    values:
      - "s-1vcpu-1gb"
      - "s-1vcpu-2gb"
      - "s-2vcpu-2gb"
      - "s-2vcpu-4gb"
      - "c-2"
    defaults: "s-1vcpu-1gb"
tasks:
  - id: create_droplet
    type: io.kestra.plugin.digitalocean.droplet.Create
    apiToken: "{{ secret('DIGITALOCEAN_TOKEN') }}"
    name: "{{ inputs.dropletName }}"
    region: "{{ inputs.dropletRegion }}"
    size: "{{ inputs.dropletSize }}"
    image: "{{ inputs.dropletImage }}"

And now we’re seeing a much more useful flow! As you probably already know, as System Administrators where we deploy our cloud instances and the images we use to do so will vary from one deployment to the next. Also, the instance size will always be different depending on the type of services you’ll be running. The name field is also converted to an input box, so that way we can name our servers whatever we want to at the time of creation.