DigitalOcean Apps skill for Codex

App specs in git, databases behind trusted sources. Codex exports the live App Platform spec before editing, then manages services, workers, static sites and pre-deploy migration jobs in .do/app.yaml with bindable database variables and encrypted secrets. For Droplets it uses cloud-init, tag-based Cloud Firewalls and reserved IPs, locks managed databases to trusted sources and connection pools, and confirms before deleting anything.

  • Cloud Platforms
  • $digitalocean-apps
  • 193 lines
  • 2 files
  • ~1,850 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- digitalocean-apps

Installs to ~/.agents/skills/digitalocean-apps/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $digitalocean-apps, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Deploys and manages DigitalOcean workloads with doctl - App Platform app specs (.do/app.yaml) for services, workers, static sites, jobs and managed databases with bindable variables, plus Droplets with cloud-init, Cloud Firewalls, VPCs, reserved IPs, volumes, snapshots, backups, Spaces object storage and managed database trusted sources. Use when deploying to DigitalOcean, writing or fixing an app spec, an App Platform build or health check fails, choosing between App Platform and a Droplet, or locking down a managed database.

Use it when

  • Deploying an app to DigitalOcean App Platform or a Droplet
  • Writing, exporting or fixing a .do/app.yaml spec
  • Locking down a DigitalOcean managed database or Droplet network access
  • Choosing between App Platform, Droplets and DOKS

Use something else when

  • You are running Docker Compose on any VPS regardless of provider: use vps-deploys
  • The workload is on DigitalOcean Kubernetes and needs manifests: use kubernetes-manifests

How to check the result

doctl apps spec validate passes, the committed spec matches doctl apps spec get, health checks return 200, and database trusted sources list only the app or VPC.

The mistake it prevents

Applying an old spec from git after someone changed settings in the console, which silently reverts their changes.

~/.agents/skills/digitalocean-apps/SKILL.md

--- name: digitalocean-apps description: Deploys and manages DigitalOcean workloads with doctl - App Platform app specs (.do/app.yaml) for services, workers, static sites, jobs and managed… license: MIT ---

Good DigitalOcean setups keep the App Platform spec in git and apply it with doctl, attach managed databases through bindable variables instead of pasted URLs, restrict databases to trusted sources, and treat Droplets as cattle built from cloud-init with a Cloud Firewall attached before they ever serve traffic.

Inspect first

  1. Read AGENTS.md, .do/app.yaml (or .do/deploy.template.yaml), Dockerfile, Procfile, and any Terraform using the digitalocean provider.
  2. doctl auth list and doctl account get show which team the CLI targets. Every doctl call needs network and an API token; in an offline sandbox, write specs and hand commands to the user.
  3. If an app already exists, export the live spec before editing so you do not drop settings made in the UI:
doctl apps list
doctl apps spec get <app-id> > .do/app.yaml

App Platform or Droplet?

NeedChoose
Web app or API from a repo or image, no server managementApp Platform
Background workers, cron-like jobs, static frontends in one unitApp Platform (workers, jobs, static_sites)
Custom daemons, GPU, kernel tuning, unusual ports, SSH accessDroplet
Lowest fixed cost for a hobby project with several containersDroplet with Compose (see vps-deploys)
Kubernetes workloadsDOKS (managed Kubernetes)

App spec

# .do/app.yaml
name: acme
region: fra
services:
  - name: api
    github: { repo: acme/api, branch: main, deploy_on_push: true }
    source_dir: /
    build_command: npm ci && npm run build
    run_command: node dist/server.js
    http_port: 8080
    instance_count: 2
    instance_size_slug: <size from: doctl apps tier instance-size list>
    health_check:
      http_path: /healthz
      initial_delay_seconds: 10
    routes: [{ path: /api }]
    envs:
      - key: DATABASE_URL
        scope: RUN_TIME
        value: ${db.DATABASE_URL}
      - key: STRIPE_SECRET_KEY
        scope: RUN_TIME
        type: SECRET
        value: placeholder-set-in-console   # replaced by encrypted value; never commit the real key
      - key: PUBLIC_BASE_URL
        scope: RUN_AND_BUILD_TIME
        value: ${APP_URL}

workers:
  - name: jobs
    github: { repo: acme/api, branch: main, deploy_on_push: true }
    run_command: node dist/worker.js
    envs:
      - key: DATABASE_URL
        scope: RUN_TIME
        value: ${db.DATABASE_URL}

jobs:
  - name: migrate
    kind: PRE_DEPLOY
    github: { repo: acme/api, branch: main }
    run_command: npm run migrate
    envs:
      - key: DATABASE_URL
        scope: RUN_TIME
        value: ${db.DATABASE_URL}

static_sites:
  - name: web
    github: { repo: acme/web, branch: main, deploy_on_push: true }
    build_command: npm ci && npm run build
    output_dir: dist
    catchall_document: index.html
    routes: [{ path: / }]

databases:
  - name: db
    engine: PG
    production: true
    cluster_name: acme-pg       # existing managed cluster; omit for a dev database

Spec rules:

  • scope matters: BUILD_TIME values are not available at runtime and vice versa. Front end public URLs usually need RUN_AND_BUILD_TIME.
  • Bindable variables (${db.DATABASE_URL}, ${db.CA_CERT}, ${APP_URL}, ${_self.PRIVATE_URL}) keep secrets out of the spec and update when resources change.
  • Secrets: after the first apply, doctl apps spec get returns encrypted values (EV[...]). Commit those, not plaintext.
  • PRE_DEPLOY jobs run before the new version receives traffic; a failure stops the deploy. Keep migrations backward compatible with the running version.
  • Dev databases (no production: true) are for testing only; use a managed cluster for anything real.

Apply and observe

doctl apps spec validate .do/app.yaml
doctl apps create --spec .do/app.yaml                  # first time
doctl apps update <app-id> --spec .do/app.yaml         # later changes; confirm for production
doctl apps create-deployment <app-id>                  # redeploy without spec change
doctl apps list-deployments <app-id>
doctl apps logs <app-id> api --type build
doctl apps logs <app-id> api --type run --follow

Rollback: redeploy a previous deployment from the console’s deployment history, or point the spec at a known-good image tag or commit. Database changes do not roll back.

Droplets

doctl compute droplet create web-1 \
  --image ubuntu-24-04-x64 --size s-2vcpu-4gb --region fra1 \
  --vpc-uuid <vpc-id> --ssh-keys <key-fingerprint> \
  --enable-monitoring --enable-backups \
  --user-data-file cloud-init.yaml --tag-names web,prod --wait

doctl compute firewall create --name web-fw --tag-names web \
  --inbound-rules "protocol:tcp,ports:22,address:203.0.113.10/32 protocol:tcp,ports:80,address:0.0.0.0/0,address:::/0 protocol:tcp,ports:443,address:0.0.0.0/0,address:::/0" \
  --outbound-rules "protocol:tcp,ports:all,address:0.0.0.0/0,address:::/0 protocol:udp,ports:all,address:0.0.0.0/0,address:::/0"
  • Attach firewalls by tag so new Droplets are covered automatically.
  • Use a reserved IP for anything DNS points at; reassign it to a replacement Droplet instead of changing DNS.
  • Volumes (block storage) hold data that must outlive the Droplet; snapshots before risky changes; weekly or daily backups as a safety net, plus your own off-provider backups.
  • Destroying a Droplet or volume is permanent: confirm with the user and check for a recent snapshot first.

Managed databases

doctl databases list
doctl databases firewalls append <db-id> --rule app:<app-id>
doctl databases firewalls append <db-id> --rule tag:web
doctl databases pool create <db-id> api-pool --db app --user doadmin --size 20 --mode transaction
  • Restrict trusted sources to the app, the Droplet tag or the VPC. An empty trusted sources list means any IP with credentials can connect.
  • Use the connection pool (PgBouncer) URL from apps with many instances; transaction mode breaks session features such as prepared statements in some drivers.
  • Connect with sslmode=require and pin the CA (${db.CA_CERT}) when the driver supports it.

Spaces

Spaces is S3-compatible: use any S3 SDK with endpoint https://<region>.digitaloceanspaces.com and Spaces access keys. Enable the CDN per Space for public assets; keep private objects private and serve them with presigned URLs.

Verification

  • doctl apps spec validate passes; the spec in git matches doctl apps spec get.
  • Build and run logs are clean; the health check path returns 200.
  • Database trusted sources list only the app, tags or VPC.
  • Droplets have a firewall attached (doctl compute firewall list) and SSH limited.
  • Production spec updates, Droplet or database deletions happen only after explicit user confirmation.

Gotchas

  • Editing settings in the console and then applying an old spec from git silently reverts them. Always export first.
  • App Platform sends traffic to http_port; an app listening on a different port fails health checks with no obvious error in the build log.
  • Static sites without catchall_document return 404 on client-side routes.
  • Droplet backups are taken on DigitalOcean’s schedule and stored with DigitalOcean; they do not replace application-level database dumps.

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "DigitalOcean Apps"
  short_description: "App specs in git, databases behind trusted sources"
  default_prompt: "$digitalocean-apps Write a DigitalOcean App Platform spec for our API, worker and React frontend with Postgres"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
Just launched

Codex Skills Pro is live

79 premium skills for Codex, each with scripts, references and an evidence report that proves the result.

Bought one by one$882.21
All 79 skills$49
94% off

That's $0.62 a skill, paid once.

Get all 79 for $49Or pick single skills from $4.99 →

Secure checkout by Creem