GREEN PACKAGE SKILL · DIGITALOCEAN · RESTATE
Restate Package Skill
A reproducible Green workflow for one production-oriented Restate server and TypeScript reference application, protected behind Caddy and Cloudflare on a guarded DigitalOcean Droplet.
Quick start
npx skills add getcolors/restate
cp .agents/skills/package-restate-green/green ./green
chmod +x green
./green build
./green create --dry-run
Build renders reproducible output and dry-run walks the workflow without provider side effects. Real creation and deletion require explicit authorization.
Architecture and sizing
Infrastructure
OpenTofu discovers the configured region’s existing default VPC and creates one Ubuntu 24.04 Droplet and firewall. No VPC is created or hard-coded.
Runtime
Ansible converges a private Docker Compose stack containing Restate, the TypeScript reference application, and Caddy. Persistent Restate and activity state live under /var/lib.
Network
Cloudflare publishes the zone apex and Caddy serves origin TLS. Restate ports 8080, 9070, and 5122 never cross the Compose boundary.
Capacity
The desired eight-vCPU, 16 GiB class leaves headroom above Restate’s default memory pools for RocksDB, Node.js, Caddy, image builds, and reboot acceptance.
The package pins Restate Server 1.7.3 and TypeScript SDK 1.16.6. It favors reliable production-default operation over a tuned-down development footprint.
Workflow API and behavior
curl https://example.com/health
curl -X POST -H 'content-type: application/json' \
-d '{"value":7}' https://example.com/workflows/my-id
curl https://example.com/workflows/my-id
The example workflow durably sleeps, fails its activity twice, succeeds on attempt three, and returns the input squared with a deterministic SHA-256 verification value. Restate’s workflow-ID boundary makes a repeated start duplicate-safe: callers receive the same ID without creating a second execution.
Desired state and lifecycle
Non-secret configuration belongs only in colors.yml. It describes the profile, DigitalOcean compute and SSH boundary, DNS, backend, Restate host, backup storage, and retention. The complete schema is in the configuration reference.
./green build
./green create --dry-run
./green create
./green delete
- Supply credentials only as matching
COLORS_PAR_*environment variables. - Never export
COLORS_PAR_PROFILEor edit generated.colors/. - Keep
compute-prevent-destroy: true; deletion remains separately guarded. - Inspect generated output and the dry-run before converging live infrastructure.
Acceptance and operations
The live convergence checks health, starts the caller-selected workflow, repeats the start, reboots the Droplet during the durable sleep, waits for HTTPS to recover, and verifies final status, result, and retry count. That reboot is an external persistence test, not a simulation.
ssh root@SERVER 'cd /opt/restate && docker compose ps'
ssh root@SERVER 'cd /opt/restate && docker compose logs --tail=200 restate app caddy'
ssh root@SERVER 'systemctl status restate-backup.timer'
Use logs and service state to diagnose the stack; do not expose a private Restate port as a shortcut.
Backup, restoration, and upgrades
A systemd timer briefly stops stateful services, archives /var/lib/restate and /var/lib/restate-app, and uploads the consistent archive to the configured R2 prefix. Restore only onto an isolated compatible replacement: stop Compose, extract the selected archive with ownership preserved, retain the stable node name, start the stack, and verify old and new workflows before moving DNS.
Before upgrading, take and verify a backup, review Restate’s immutable deployment and workflow-versioning rules, change exact pins, inspect golden output, and run tests, build, and dry-run. Long-running workflows must remain compatible with the deployed code.
Development and source
bb test
bb golden
./scripts/launcher.sh
Source on GitHub. Review every golden diff before accepting it.