Digitalocean logo

Digitalocean

Community
ericrisco
digitalocean

Use when deploying or operating a workload on DigitalOcean — Droplet vs App Platform vs Functions, doctl, app spec YAML, Managed Postgres/MySQL/Valkey on the VPC, S3-compatible Spaces + CDN. NOT host-agnostic CI/CD or rollback strategy (that is `deployment`), NOT a bare Hetzner VPS (that is `hetzner`), NOT another managed PaaS (that is `railway`).

Overview

Publisherericrisco
Repositoryrsc-harness
Skill namedigitalocean
Stars
239
Forks
24
Bundled files
4
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 4 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by ericrisco on GitHub. Read the source before you install it.

Installation

Install the Digitalocean AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/ericrisco/rsc-harness/tree/main/skills/digitalocean
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/ericrisco/rsc-harness.git /tmp/rsc-harness
mkdir -p .claude/skills
cp -r /tmp/rsc-harness/skills/digitalocean .claude/skills/digitalocean
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Digitalocean in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Digitalocean on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Digitalocean is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

DigitalOcean — Droplet vs App Platform, doctl, Managed DBs, Spaces

You own one decision: where on DO does this run, and how do I ship it. Host-agnostic CI/CD, release gating and rollback strategy are ../deployment/SKILL.md; authoring the Dockerfile is docker; DNS records and the registrar are domains-dns; a bare Hetzner box and its economics are hetzner. Pick the compute model first, then wire data and storage, then the ops that bite in production.

text
workload → [Droplet | App Platform | Functions] → Managed DB (VPC private host) → Spaces (S3 + CDN)
              raw VPS    managed PaaS   event fn        Postgres/MySQL/Valkey         object store

The core decision: Droplet vs App Platform vs Functions

Settle this before writing a single command. Most web apps want App Platform; reach for a Droplet only when you need the box itself.

AxisDroplet (VPS)App Platform (PaaS)Functions
ControlFull root, any daemon, any portBuild+run only, no SSHPer-invocation, no host
Ops burdenYou patch/secure/restart itDO runs it, auto TLS, auto deployZero infra
Price floorPer-second billing since 2026-01-01, min 60s or $0.013 static sites free; dynamic from $5/mo per servicePay per call
ScalingResize/clone/load-balance yourselfSet instance count + size, autoscaleImplicit
Best forStateful daemons, cron hosts, custom networking, "give me a Linux box"Web service / API / worker / static site from a repoEvent glue, webhooks

Rules of thumb:

  • Stateless web service or API from a Git repo → App Platform. It builds, deploys, gives you TLS and a URL, and re-deploys on push. No box to patch. Static frontend → App Platform static site (free, up to 3); don't run a Droplet to serve HTML.
  • You need root, a long-lived stateful daemon, custom ports, or a cron host → Droplet.
  • A managed Postgres/MySQL/Valkey → always the Managed Database product, never a DB you hand-install on a Droplet, unless you have a hard reason.

doctl setup

doctl is the official DO CLI; it drives everything below.

bash
# macOS
brew install doctl
# Linux: download the release tarball from github.com/digitalocean/doctl/releases, then:
#   tar xf doctl-*.tar.gz && sudo mv doctl /usr/local/bin

# Authenticate with a token from cloud.digitalocean.com/account/api/tokens
doctl auth init                       # pastes a token, validates, stores a context
doctl auth init --context prod        # a named context per account/env
doctl auth switch --context prod      # switch the active context
doctl account get                     # verify the token works

Never commit the token. It is a full-account credential. Keep it in your shell keychain, a secret manager, or CI secret — never in the repo, never in an app spec. Why: a leaked dop_v1_… token lets anyone create/destroy your whole account.

App Platform via app spec

App Platform deploys from an app spec (YAML or JSON). Treat the spec as the source of truth, version it, and apply it with doctl.

yaml
# .do/app.yaml — minimal web service + managed Postgres
name: my-api
region: nyc
services:
  - name: web
    github:
      repo: me/my-api
      branch: main
      deploy_on_push: true
    instance_size_slug: apps-s-1vcpu-1gb   # ~$5/mo basic; sizes go up to dedicated
    instance_count: 1
    http_port: 8080
    envs:
      - key: NODE_ENV
        value: production
        scope: RUN_TIME              # RUN_TIME | BUILD_TIME | RUN_AND_BUILD_TIME
      - key: DATABASE_URL
        value: ${db.DATABASE_URL}    # injected from the managed DB below
        scope: RUN_TIME
      - key: API_SIGNING_KEY
        value: ${API_SIGNING_KEY}
        type: SECRET                 # encrypted at rest; never plaintext
        scope: RUN_TIME
databases:
  - name: db
    engine: PG
    production: true

Lifecycle — validate, then create or update:

bash
doctl apps spec validate .do/app.yaml          # structural lint, no deploy
doctl apps create --spec .do/app.yaml          # first deploy; prints the app id
doctl apps update <app-id> --spec .do/app.yaml # apply changes (and to roll back: re-apply the prior spec)
doctl apps list                                # find the id

Env scoping that matters:

  • type: SECRET encrypts the value at rest and hides it in the dashboard. Use it for every key, token, password. Plain value: is readable.
  • scope: BUILD_TIME for things only the build needs; RUN_TIME for runtime; don't leak build-only secrets into the running container.
  • ${db.DATABASE_URL} (and ${db.HOSTNAME}, ${db.PORT}, etc.) are auto-injected when the service references a databases: entry — you never paste the connection string.

Operate:

bash
doctl apps logs <app-id> --type run --follow     # run | build | deploy
doctl apps logs <app-id> <component> --type run  # one component

Rollback = re-apply the previous spec (git-revert .do/app.yaml and doctl apps update), or redeploy a prior deployment from the dashboard. There is no magic rollback verb — your git history of the spec is the rollback mechanism.

For multi-component apps (web + worker + static_site + job + db, health checks, ingress routes, autoscaling, instance-size table, alerts) see references/app-spec.md.

Droplets

A Droplet is a Linux VPS. Bootstrap it declaratively, lock it down with a cloud firewall.

bash
doctl compute droplet create web-1 \
  --region nyc3 --size s-1vcpu-1gb --image ubuntu-24-04-x64 \
  --ssh-keys <fingerprint> \
  --vpc-uuid <vpc-uuid> \
  --user-data-file cloud-init.yaml \
  --wait
  • Cloud firewall, not just ufw. A cloud firewall filters at DO's edge before traffic reaches the box, and applies to a tag/group of Droplets. Use it as the real perimeter; host ufw is defense-in-depth, not the only line. Why: a misconfigured ufw after a reboot still leaves the edge firewall protecting you.
  • Reserved IP is free while assigned to a Droplet (you pay only when it's unassigned). Assign one so you can re-point it to a replacement Droplet without DNS changes — that's your failover handle.
  • Snapshots/backups are your restore path; enable automated backups or snapshot before risky changes.
  • Per-second billing since 2026-01-01 (min 60s or $0.01): short-lived Droplets are cheap to spin up and destroy, but a powered-off Droplet still bills for storage — destroy, don't just power off, to stop charges.

Cloud-init recipes, firewall inbound/outbound rule sets, snapshot cadence + restore, reserved-IP failover, and the VPC + private-DB layout live in references/droplet-ops.md.

Managed Databases

Use the Managed Database product for Postgres/MySQL/Valkey — DO handles patching, failover, and backups.

  • Provision sizing: managed Postgres starts ~$15/mo single node; HA (primary+standby) from ~$30/mo; read replicas available for read scaling.
  • Connect over the VPC private host, not the public one. Same-region Droplets and Managed DBs talk over the VPC with no bandwidth charge and sub-ms latency, and the private host keeps the DB off the public internet. Add the app's Droplet/App as a trusted source so only it can connect.
  • Connection pooling (PgBouncer) is built in. Use a pool when many short-lived clients (serverless, lots of App Platform instances) would otherwise exhaust connections — a cluster supports up to ~21 pools / up to ~1,000 connections depending on size, and the pool listens on a separate pool port from the raw DB port. Point your app at the pool connection string, not the raw one.
  • For schema design, indexing, query tuning, migrations → that's ../postgresdb/SKILL.md, not here. This skill only provisions and wires the cluster.

Spaces (S3-compatible object storage + CDN)

Spaces is S3-API-compatible object storage with a built-in CDN.

  • $5/mo includes 250 GiB storage + 1 TiB outbound transfer; inbound is free; the CDN is included at no extra cost across 200+ edge locations.
  • Spaces keys are NOT your API token. Generate a separate Spaces access key + secret; the doctl/API token does not work for S3 operations.
  • Use any S3 SDK or aws-cli/s3cmd against the regional endpoint:
python
# boto3 against DO Spaces (nyc3 region/endpoint)
import boto3
s3 = boto3.client(
    "s3",
    endpoint_url="https://nyc3.digitaloceanspaces.com",
    region_name="nyc3",
    aws_access_key_id="<SPACES_KEY>",       # Spaces key, not the DO API token
    aws_secret_access_key="<SPACES_SECRET>",
)
s3.upload_file("photo.jpg", "my-bucket", "photo.jpg", ExtraArgs={"ACL": "public-read"})

Serve public assets through the bucket's CDN edge URL; set CORS on the bucket if a browser fetches it cross-origin, and a lifecycle rule to expire/transition old objects.

Basic ops + cost gotchas

  • Set alerts on the app/DB (deploy failures, CPU, restart count) so you hear about trouble before users do. App-level dashboards/alerting strategy is ../monitoring.
  • Scale by editing instance_count/instance_size_slug in the spec and re-applying; capacity strategy that's host-agnostic is ../scaling.
  • App Platform data transfer overage is $0.02/GiB, billed separately from Droplet transfer — a chatty media app can run up a bill; front heavy static assets with Spaces+CDN.
  • An unassigned reserved IP is billed. Release reserved IPs you're not using.

Anti-patterns

Anti-patternWhy it bitesDo instead
Hardcoding a dop_v1_… token or DB password as a plain value: in the app specSpec is in git, value is readable, full-account compromisetype: SECRET env, or ${db.*} injection; token only in doctl auth
Connecting app→DB over the public hostPublic exposure + egress cost + latencyVPC private host + trusted source
Running a stateful long-lived daemon as an App Platform serviceComponents are restartable/stateless; state is lostDroplet (or a job/worker designed to be stateless)
Sizing a dedicated apps-d-2vcpu-4gb (~$78/mo) for a hobby appPaying enterprise rates for toy trafficStart apps-s-1vcpu-1gb (~$5) and scale up on real metrics
ufw on the Droplet as the only firewallA bad reboot/config leaves the host openCloud firewall at the edge + host ufw as defense-in-depth
Hand-installing Postgres on a Droplet "to save money"You now own patching, backups, failoverManaged Database unless you have a hard reason
Powering off a Droplet to stop billingPowered-off Droplets still bill for storageSnapshot then destroy
Leaving a reserved IP unassignedIt's billed when not attachedRelease it

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Digitalocean AI skill do?

Use when deploying or operating a workload on DigitalOcean — Droplet vs App Platform vs Functions, doctl, app spec YAML, Managed Postgres/MySQL/Valkey on the VPC, S3-compatible Spaces + CDN. NOT host-agnostic CI/CD or rollback strategy (that is `deployment`), NOT a bare Hetzner VPS (that is `hetzner`), NOT another managed PaaS (that is `railway`).

Why use Digitalocean on TypingMind?

Because you install it once and use it with any model. Digitalocean is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Digitalocean in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/ericrisco/rsc-harness/tree/main/skills/digitalocean. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Digitalocean?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Digitalocean?

As many as you like. As long as a model supports skills, you can use Digitalocean with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Digitalocean AI skill free?

Yes. It is published on GitHub by ericrisco under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇