Create icon
LoopUntil icon
Get icon
Create icon
Log icon
If icon
Delete icon
Delete icon
SlackIncomingWebhook icon

Ephemeral DigitalOcean Droplet Runner with Guaranteed Teardown

Orchestrate ephemeral DigitalOcean droplets with Kestra. Create a VM per run, poll until active, run your job, and guarantee teardown with finally.

Categories
CloudInfrastructure

Run batch workloads on DigitalOcean droplets that exist only for the duration of a single execution. This blueprint provisions a fresh droplet with your job injected through cloud-init, polls the API until the machine is actually active, restricts SSH access to your admin network with a dedicated firewall, and then destroys both the firewall and the droplet in a finally block. Because teardown lives in finally rather than at the end of the happy path, a crashed workload or a failed boot never leaves an orphaned VM billing by the hour.

How it works

  1. create_droplet (io.kestra.plugin.digitalocean.droplet.Create) provisions a droplet named after the execution ID, tagged kestra and ephemeral, in the region and size passed as inputs. The batch job itself ships as a cloud-init userData script that runs on first boot.
  2. wait_until_active (io.kestra.plugin.core.flow.LoopUntil) polls droplet.Get every 10 seconds until the droplet status flips from new to active, failing the run if that takes longer than 10 minutes.
  3. lock_down (io.kestra.plugin.digitalocean.firewall.Create) attaches a single-purpose firewall that only allows inbound SSH from the admin_cidr input while keeping all outbound traffic open.
  4. run_workload is a placeholder log task reporting the droplet's public IP. In production you replace it with io.kestra.plugin.fs.ssh.Command pointed at {{ outputs.poll_droplet.ip }} to drive the machine directly.
  5. The finally block deletes the firewall and the droplet through If guards, so cleanup only targets resources that were actually created and runs whether the execution succeeded or failed.
  6. The errors block posts a Slack alert whenever anything fails, reminding the team that teardown already ran.

Every DigitalOcean task carries the API token from the DIGITALOCEAN_TOKEN secret, so any task can be copied out of this flow and still run standalone.

What you get

  • A per-execution droplet with a unique, traceable hostname derived from the Kestra execution ID.
  • A hard guarantee that compute is destroyed at the end of every run, including failed ones, thanks to finally.
  • A per-run firewall so the ephemeral machine is never exposed to the internet beyond SSH from your admin range.
  • Region, size, image, and admin CIDR as flow inputs, so the same flow serves smoke tests on 1 vCPU and heavy batch jobs on dedicated CPU sizes.

Who it's for

  • Data and platform engineers running nightly ETL, model training, or build jobs that need a clean machine per run without paying for idle time.
  • Teams replacing hand-rolled doctl scripts and cron with versioned, observable orchestration.
  • Anyone who has ever found a months-old forgotten droplet on the invoice.

Why orchestrate this with Kestra

The DigitalOcean console and doctl can create droplets, but neither can chain create, poll, firewall, execute, and destroy into one atomic unit with failure handling. A shell script dies halfway and leaks the VM; Kestra's finally block runs teardown no matter where the execution stopped, LoopUntil turns the asynchronous droplet boot into a synchronous step, and every run leaves a full audit trail of what was created, when, and what it cost in wall-clock time.

Prerequisites

  • A DigitalOcean account and a personal access token with read and write scopes for droplets and firewalls.
  • A Slack incoming webhook for failure alerts.

Secrets

  • DIGITALOCEAN_TOKEN: DigitalOcean personal access token.
  • SLACK_WEBHOOK_URL: Slack incoming webhook URL.

Quick start

  1. Add the two secrets above to your Kestra namespace.
  2. Set admin_cidr to the network you actually SSH from.
  3. Replace the cloud-init runcmd in create_droplet with your real job.
  4. Execute the flow and watch the droplet appear, work, and disappear in the DigitalOcean console.

How to extend

  • Replace the run_workload log with io.kestra.plugin.fs.ssh.Command to run commands over SSH on {{ outputs.poll_droplet.ip }} and stream their output into Kestra.
  • Add io.kestra.plugin.digitalocean.droplet.Action with action: SNAPSHOT before teardown to keep an image of the machine for debugging.
  • Attach a io.kestra.plugin.digitalocean.volume.Create and volume.Attach pair when the job needs scratch space larger than the droplet disk.
  • Trigger the flow from io.kestra.plugin.core.trigger.Schedule or a webhook to run the ephemeral machine on your release cadence.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.