DigitalOcean
Run a Routecraft project on DigitalOcean: on App Platform from the scaffolded Dockerfile, or on a Droplet when deferred work and agent sessions have to survive a redeploy.
Both start from the image described in Deployment. This page covers only what DigitalOcean changes.
App Platform
App Platform has no Bun runtime of its own, so it builds the project from its Dockerfile, which a Bun project from create-routecraft already has.
- Push the project to GitHub or GitLab, with
craft.config.tsand theDockerfileat the root. - Create the app from the repository. App Platform detects the
Dockerfile; no build or run command is needed, because the image'sCMDrunscraft start. - Pick the component type. A project whose capabilities start on their own (schedules, a mailbox, timers) and serve nothing over HTTP is a worker. A project that serves MCP over HTTP,
http()routes or the ops endpoints is a web service. - Set the secrets your adapters read (API keys, mail passwords) as encrypted environment variables. The image already sets
NODE_ENV=production.
A web service listens on the port App Platform gives it
App Platform routes traffic to the port in the component's settings and passes it in PORT. Bind every interface and read the port from the environment:
// craft.config.ts
import { defineConfig } from '@routecraft/routecraft'
export const craftConfig = defineConfig({
servers: {
default: { host: '0.0.0.0', port: Number(process.env.PORT ?? 8080) },
},
ops: {},
})
With ops: {} on the same server, point the component's health check at /health/live. It answers without a credential and carries no dependency state, so an upstream outage never makes App Platform restart the app. Monitoring explains the three health paths.
State does not survive a redeploy
App Platform's filesystem is not persistent and it offers no volumes. Everything the runtime keeps under .routecraft/ (deferred exchanges, agent sessions, the telemetry database) starts empty after every deploy or restart. That is fine for a project that neither defers nor keeps sessions. When a capability waits for a person, or an agent must remember a conversation across a restart, run on a Droplet instead.
A Droplet with Docker
A Droplet is a plain VM, so the image runs exactly as Deployment describes, with a named volume for the state:
docker build -t my-app .
docker run -d --restart unless-stopped \
--env-file .env \
-p 8080:8080 \
-v my-app-state:/app/.routecraft \
my-app
Bind 0.0.0.0 on the servers you publish, as on any container host, and put a DigitalOcean firewall or load balancer in front of any port that is not meant for the public.
Node embedding on App Platform
A service that embeds @routecraft/routecraft in its own Node application, rather than running craft, can use the Node buildpack directly:
- Runtime: Node 22.6 or later.
- Build command:
npm ci --omit=dev, or your own build script. - Run command:
node --experimental-strip-types src/server.ts, without the flag on Node 23.6 or later.
The same rule about state applies. Programmatic invocation covers the embedding API.
Related
Servers and ports
Named servers, the host and port each binds, and the doors that mount on them.
Monitoring
Logging, the events to alarm on, health endpoints and telemetry.
Durable agents
The deferred work that needs persistent state to survive a restart.