GREEN PACKAGE SKILL · DIGITALOCEAN · DBOS
DBOS Package Skill
A reproducible, production-oriented DBOS durable-workflow service on one DigitalOcean Droplet, with a TypeScript reference API, colocated PostgreSQL, Cloudflare HTTPS, R2 backups, and restart acceptance.
Quick start
npx skills add getcolors/dbos
cp .agents/skills/package-dbos-green/green ./green
chmod +x green
./green build
./green create --dry-run
build renders the deployment without credentials. The dry-run walks the complete workflow while skipping side effects. A real create, acceptance run, or deletion touches live infrastructure and requires separate authorization.
Architecture
Compute
OpenTofu discovers the configured region’s default VPC, then creates one Ubuntu Droplet, firewall, and operator SSH key. It does not create a VPC or require a VPC UUID in desired state.
Runtime
ONCE installs Docker and Caddy and runs the pinned DBOS TypeScript application. PostgreSQL 17 and DBOS share the application container, but PostgreSQL binds only to loopback.
Public boundary
Cloudflare publishes one apex A record. HTTP, HTTPS, and restricted key-only SSH are the only admitted ports; PostgreSQL and internal DBOS interfaces are never public.
Sizing
The benchmark uses four shared vCPUs and 8 GiB RAM, leaving room for Node, PostgreSQL, Docker/Caddy, image replacement, and concurrent acceptance checks.
DBOS SDK 4.25.14 is pinned exactly. This is intentionally a single-node design: process and host restarts recover, but a Droplet, disk, or regional failure causes downtime and there is no automatic failover.
Reference workflow
GET /health
POST /workflows {"workflowID":"caller-id","input":"value","delaySeconds":60}
GET /workflows/:workflowID
The workflow durably sleeps and invokes a retryable activity. The activity records and fails its first attempt, succeeds on its second, and returns a deterministic SHA-256 result over the workflow ID and input. Reusing an ID returns the existing DBOS execution instead of starting duplicate work.
Desired state and credentials
colors.yml is the only desired-state file. It selects the profile, DigitalOcean region and size, restricted SSH sources, DNS, backend, application host, backup destination, and retention. See the configuration reference for every key.
- Supply secrets only through matching
COLORS_PAR_*environment variables in an ignored.envrc.private. - Never export
COLORS_PAR_PROFILE; the profile separates remote state. - Never edit or commit generated
.colors/output. - Keep
compute-prevent-destroy: true.
Acceptance and operations
./green create
./scripts/acceptance.sh
ssh dbos-digitalocean 'docker ps'
ssh dbos-digitalocean 'journalctl -u docker -u caddy --since=-1h'
Acceptance checks HTTPS, exactly two activity attempts, deterministic output, and duplicate-ID behavior. It then starts a delayed workflow, reboots the benchmark Droplet, waits for HTTPS recovery, and verifies the original workflow’s result. Because that script performs a real reboot, run it only against an authorized deployment.
Backups, restoration, and upgrades
A daily custom-format pg_dump is uploaded over HTTPS to the configured R2 bucket and prefix, with retention enforced by the container. Test recovery on an isolated replacement: restore into an empty compatible PostgreSQL database, verify DBOS workflow state and activity attempts, then exercise health and workflow retrieval before changing DNS. Never test restoration over the live database.
For upgrades, move the exact DBOS version and source together, review workflow compatibility guidance, inspect generated and golden diffs, take a verified backup, and confirm old pending workflows before retiring old code. PostgreSQL major upgrades require a separately tested dump/restore or pg_upgrade plan.
Development and source
bb test
bb golden
./scripts/launcher.sh
npm --prefix application run typecheck
npm --prefix application run build
npm --prefix application test
Source on GitHub. Inspect every golden change; never accept generated output merely to make the suite pass.