Skip to content

Commit 35226a1

Browse files
deploy: 0efe40d
1 parent 5877084 commit 35226a1

187 files changed

Lines changed: 1261 additions & 907 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2.0/llms-full.txt

Lines changed: 220 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -6210,6 +6210,207 @@ from the detail view. Each action maps to a `POST` on the same run id and
62106210
returns either `200` with the resulting state or `409` when the action is
62116211
not valid for the run's current state.
62126212

6213+
# Self-Hosting Deployments
6214+
6215+
Durable Workflow v2 supports several self-hosted shapes. Pick the smallest path
6216+
that matches the environment you operate, then keep the image, database, cache,
6217+
auth, readiness, and upgrade contract explicit.
6218+
6219+
This guide covers the standalone server distribution. If you run the Laravel
6220+
package embedded in your own app, use the package installation and configuration
6221+
pages instead.
6222+
6223+
## Deployment support matrix
6224+
6225+
| Path | Start from | Supported for | Not promised by this path | Commercial support starts when |
6226+
| --- | --- | --- | --- | --- |
6227+
| Local development and internal non-production | [`docker-compose.published.yml`](https://github.com/durable-workflow/server/blob/main/docker-compose.published.yml) with `DW_SERVER_TAG=0.2` or `DW_SERVER_IMAGE=durableworkflow/server:0.2` | One developer machine, LAN demos, shared staging, SDK and worker integration tests | Internet-facing production, durable backup guarantees, strict secret rotation, multi-node failover | You want help turning a working dev stack into a production runbook |
6228+
| Single-node production | [`docker-compose.published.yml`](https://github.com/durable-workflow/server/blob/main/docker-compose.published.yml) with a production env file, MySQL and Redis volumes, role-scoped tokens, backups, TLS through a reverse proxy, and pinned image tags or digests | One VM, VPS, or internal Docker host with persistent workflow state and a simple operational model | Host-level HA, automatic database failover, multi-region recovery, zero-downtime major topology changes | The deployment carries production traffic and you want review of backup, restore, auth, TLS, upgrade, or rollback procedures |
6229+
| Small clustered deployment | Published `durableworkflow/server` or `ghcr.io/durable-workflow/server` images using the [Compose recipe](https://github.com/durable-workflow/server/blob/main/docker-compose.published.yml) as the container/process template, with shared external MySQL/PostgreSQL and Redis | Horizontal API and worker capacity when one node is no longer enough | Database/cache HA design, cross-region operation, bespoke load-balancer behavior, generic "works everywhere" orchestration guarantees | You need sizing, failure-domain, rollout, or recovery planning across more than one host |
6230+
| Raw Kubernetes manifests | The server repository [`k8s/`](https://github.com/durable-workflow/server/tree/main/k8s) manifests, using published server images and your existing database, Redis, ingress, and secret management | Teams that already operate Kubernetes and want inspectable manifests for API, worker, scheduler, bootstrap, service, probes, config, and secrets | Helm charts, managed-Kubernetes provider validation, advanced HA, multi-region, custom operators, environment-specific storage/networking/security decisions | You need Helm, overlays, managed-cluster validation, high availability, or provider-specific production planning |
6231+
| Support-led topologies | A reviewed design based on your environment | Advanced HA, multi-region, bespoke security/networking, private SLOs, custom overlays, migration planning | Self-serve copy/paste operation | The topology itself is part of the product risk |
6232+
6233+
The public distribution is intentionally optimized for local development,
6234+
single-node production, and small clustered deployments. Kubernetes manifests
6235+
are provided for teams that already operate Kubernetes. Helm charts, advanced
6236+
HA, multi-region, and provider-specific managed-Kubernetes validation are
6237+
support-led because they depend on your database, cache, networking, security,
6238+
runner, and upgrade choices. See the [support boundary](/docs/2.0/support) for
6239+
the commercial support model.
6240+
6241+
## Published images
6242+
6243+
Use published images for self-hosted server deployments:
6244+
6245+
- Docker Hub: `durableworkflow/server:0.2`
6246+
- GitHub Container Registry: `ghcr.io/durable-workflow/server:0.2`
6247+
- Digest pinning: `durableworkflow/server@sha256:...` or
6248+
`ghcr.io/durable-workflow/server@sha256:...`
6249+
6250+
Use mutable tags only for local experiments. Production env files should pin a
6251+
specific version tag or digest so upgrade and rollback steps are auditable.
6252+
6253+
## Local development and internal non-production
6254+
6255+
Use the published-image Compose recipe when you want a source-free stack backed
6256+
by MySQL and Redis:
6257+
6258+
```bash
6259+
curl -fsSLO https://raw.githubusercontent.com/durable-workflow/server/main/docker-compose.published.yml
6260+
6261+
export DW_SERVER_TAG=0.2
6262+
export DW_AUTH_TOKEN=dev-token
6263+
6264+
docker compose -f docker-compose.published.yml up -d --wait
6265+
```
6266+
6267+
Verify the API, readiness, cluster discovery, and worker registration:
6268+
6269+
```bash
6270+
curl http://localhost:8080/api/health
6271+
curl http://localhost:8080/api/ready
6272+
curl -H "Authorization: Bearer $DW_AUTH_TOKEN" \
6273+
http://localhost:8080/api/cluster/info
6274+
6275+
curl -X POST http://localhost:8080/api/worker/register \
6276+
-H "Authorization: Bearer $DW_AUTH_TOKEN" \
6277+
-H "Content-Type: application/json" \
6278+
-H "X-Namespace: default" \
6279+
-H "X-Durable-Workflow-Protocol-Version: 1.0" \
6280+
-d '{"worker_id":"compose-worker","task_queue":"compose","runtime":"python"}'
6281+
```
6282+
6283+
This path is safe for development and internal staging. It is not a production
6284+
security boundary: the example uses one compatibility token, default service
6285+
passwords, local named volumes, and no TLS.
6286+
6287+
## Single-node production
6288+
6289+
Use the same Compose artifact with production configuration outside source
6290+
control:
6291+
6292+
```env
6293+
DW_SERVER_IMAGE=durableworkflow/server:0.2
6294+
SERVER_PORT=8080
6295+
APP_ENV=production
6296+
APP_DEBUG=false
6297+
6298+
DB_DATABASE=durable_workflow
6299+
DB_USERNAME=workflow
6300+
DB_PASSWORD=replace-with-random-password
6301+
DB_ROOT_PASSWORD=replace-with-random-root-password
6302+
6303+
DW_AUTH_DRIVER=token
6304+
DW_AUTH_BACKWARD_COMPATIBLE=false
6305+
DW_WORKER_TOKEN=replace-with-worker-token
6306+
DW_OPERATOR_TOKEN=replace-with-operator-token
6307+
DW_ADMIN_TOKEN=replace-with-admin-token
6308+
```
6309+
6310+
Start with that env file:
6311+
6312+
```bash
6313+
docker compose --env-file durable-workflow.prod.env \
6314+
-f docker-compose.published.yml up -d --wait
6315+
```
6316+
6317+
Operate the host as a production service:
6318+
6319+
- Put TLS, public routing, request logging, and IP allow lists in a reverse
6320+
proxy in front of the API container.
6321+
- Do not expose MySQL or Redis publicly.
6322+
- Use `DW_WORKER_TOKEN` for workers, `DW_OPERATOR_TOKEN` for application and
6323+
operator traffic, and `DW_ADMIN_TOKEN` for namespace and administrative work.
6324+
- Back up the MySQL volume before every image upgrade and on a regular
6325+
schedule. Redis should be preserved for graceful restarts, but MySQL remains
6326+
the durable workflow-history source of truth.
6327+
- Keep the exact env file, image tag or digest, and database backup together for
6328+
restores.
6329+
6330+
Upgrade order:
6331+
6332+
1. Back up MySQL and record the current image reference.
6333+
2. Change only `DW_SERVER_IMAGE` or `DW_SERVER_TAG`.
6334+
3. Pull the new image.
6335+
4. Run `docker compose --env-file durable-workflow.prod.env -f docker-compose.published.yml up -d --wait`.
6336+
5. Confirm `/api/ready`, `/api/cluster/info`, and worker registration before
6337+
shifting external traffic.
6338+
6339+
The server README keeps the latest command-level Compose examples in the
6340+
[Official Image + Compose](https://github.com/durable-workflow/server#official-image--compose)
6341+
section.
6342+
6343+
## Small clustered deployments
6344+
6345+
A small cluster is a modest extension of the single-node model:
6346+
6347+
- Run two or more API containers behind a load balancer.
6348+
- Run one or more worker containers for each task queue.
6349+
- Use shared external MySQL or PostgreSQL for durable history.
6350+
- Use shared Redis or another lock-capable network cache so long polls, queue
6351+
wakeups, and cache locks work across hosts.
6352+
- Run bootstrap/migrations once per rollout before new API and worker containers
6353+
accept traffic.
6354+
- Treat the database and cache as the primary failure domains. The server
6355+
containers are replaceable; the persistence layer is not.
6356+
6357+
This path is self-serve when your team already has a clear VM, network,
6358+
database, cache, backup, and load-balancer model. It becomes support-led when
6359+
you need help deciding those boundaries, capacity, rollout order, or recovery
6360+
procedures.
6361+
6362+
## Kubernetes manifests
6363+
6364+
The server repository includes raw manifests under
6365+
[`k8s/`](https://github.com/durable-workflow/server/tree/main/k8s) for teams
6366+
that already operate Kubernetes:
6367+
6368+
- Namespace and shared labels
6369+
- ConfigMap and Secret split
6370+
- Bootstrap/migration Job
6371+
- API Deployment and Service
6372+
- Worker Deployment
6373+
- Scheduler CronJob
6374+
- PodDisruptionBudget
6375+
- `/api/health` liveness and `/api/ready` readiness probes
6376+
- Conservative resource requests and limits
6377+
6378+
Before applying the manifests, replace the image tag with a specific published
6379+
version or digest, provide real database and Redis credentials, and wire the
6380+
ConfigMap values to the services your cluster already operates. The manifests
6381+
are intentionally raw and inspectable; they are not a Helm chart and do not
6382+
promise generic managed-Kubernetes behavior.
6383+
6384+
For a Kubernetes production rollout, prove at minimum:
6385+
6386+
```bash
6387+
kubectl -n durable-workflow wait --for=condition=complete job/durable-workflow-migrate --timeout=180s
6388+
kubectl -n durable-workflow rollout status deploy/durable-workflow-server
6389+
kubectl -n durable-workflow rollout status deploy/durable-workflow-worker
6390+
kubectl -n durable-workflow port-forward svc/durable-workflow-server 8080:8080
6391+
curl http://localhost:8080/api/ready
6392+
curl -H "Authorization: Bearer $DW_ADMIN_TOKEN" http://localhost:8080/api/cluster/info
6393+
```
6394+
6395+
Provider-specific load balancers, storage classes, network policies, managed
6396+
database failover, Helm charts, multi-region, and advanced HA are support-led or
6397+
tracked separately from the raw-manifest contract.
6398+
6399+
## Readiness contract
6400+
6401+
Use both health and readiness checks:
6402+
6403+
- `GET /api/health` proves the process is serving HTTP.
6404+
- `GET /api/ready` proves the server can use its configured runtime
6405+
dependencies, including migrations and default namespace readiness.
6406+
- `GET /api/cluster/info` proves an authenticated client can discover build
6407+
identity, control-plane protocol, worker protocol, payload codecs, and server
6408+
capabilities.
6409+
- `POST /api/worker/register` proves workers can authenticate into the expected
6410+
namespace and task queue.
6411+
6412+
Do not shift traffic based on `/api/health` alone.
6413+
62136414
# Migrating to 2.0
62146415

62156416
This guide covers the key changes when upgrading an existing Laravel v1 application to v2.
@@ -7425,89 +7626,25 @@ See the [CLI install page](/docs/2.0/polyglot/cli#install) for a platform-detect
74257626

74267627
## Deployment
74277628

7428-
### Docker
7429-
7430-
Build and run a production image:
7431-
7432-
```bash
7433-
docker build -t my-workflow-server .
7434-
docker run -d \
7435-
-p 8080:8080 \
7436-
-e DB_CONNECTION=mysql \
7437-
-e DB_HOST=your-db-host \
7438-
-e DW_AUTH_TOKEN=your-secret \
7439-
my-workflow-server
7440-
```
7441-
7442-
Run migrations before starting the API:
7443-
7444-
```bash
7445-
docker run --rm \
7446-
-e DB_CONNECTION=mysql \
7447-
-e DB_HOST=your-db-host \
7448-
my-workflow-server \
7449-
php artisan migrate --force
7450-
```
7451-
7452-
### Kubernetes
7453-
7454-
The server is stateless and horizontally scalable. Key considerations:
7455-
7456-
- **Shared cache** — Use Redis or another networked cache for multi-node deployments. Long-poll wake-ups use cache-backed signals, so a shared cache ensures prompt task delivery.
7457-
- **Shared queue** — Use Redis, SQS, or another networked queue backend. Do not use the `sync` driver.
7458-
- **Database** — MySQL 8.0+, PostgreSQL 13+, or compatible. Run migrations as a Kubernetes Job before starting the API.
7459-
- **Liveness probe** — `GET /api/health`
7460-
- **Readiness probe** — `GET /api/health`
7461-
7462-
Example deployment manifest:
7463-
7464-
```yaml
7465-
apiVersion: apps/v1
7466-
kind: Deployment
7467-
metadata:
7468-
name: workflow-server
7469-
spec:
7470-
replicas: 3
7471-
selector:
7472-
matchLabels:
7473-
app: workflow-server
7474-
template:
7475-
metadata:
7476-
labels:
7477-
app: workflow-server
7478-
spec:
7479-
containers:
7480-
- name: server
7481-
image: my-workflow-server:latest
7482-
ports:
7483-
- containerPort: 8080
7484-
env:
7485-
- name: DB_CONNECTION
7486-
value: mysql
7487-
- name: DB_HOST
7488-
value: mysql-service
7489-
- name: CACHE_STORE
7490-
value: redis
7491-
- name: REDIS_HOST
7492-
value: redis-service
7493-
- name: DW_AUTH_TOKEN
7494-
valueFrom:
7495-
secretKeyRef:
7496-
name: workflow-secrets
7497-
key: auth-token
7498-
livenessProbe:
7499-
httpGet:
7500-
path: /api/health
7501-
port: 8080
7502-
initialDelaySeconds: 10
7503-
periodSeconds: 10
7504-
readinessProbe:
7505-
httpGet:
7506-
path: /api/health
7507-
port: 8080
7508-
initialDelaySeconds: 5
7509-
periodSeconds: 5
7510-
```
7629+
Use the [self-hosting deployment guide](/docs/2.0/deployment) to choose a
7630+
supported topology before deploying production traffic. It separates local
7631+
development, single-node production, small clustered deployments, raw
7632+
Kubernetes manifests, and support-led topologies.
7633+
7634+
For self-hosted server deployments, start from published images rather than
7635+
source-tree builds:
7636+
7637+
- Docker Hub: `durableworkflow/server:0.2`
7638+
- GitHub Container Registry: `ghcr.io/durable-workflow/server:0.2`
7639+
- Published-image Compose:
7640+
[`docker-compose.published.yml`](https://github.com/durable-workflow/server/blob/main/docker-compose.published.yml)
7641+
- Raw Kubernetes manifests:
7642+
[`k8s/`](https://github.com/durable-workflow/server/tree/main/k8s)
7643+
7644+
Production deployments should pin a version tag or image digest, use
7645+
role-scoped credentials, run bootstrap/migrations before serving traffic, and
7646+
prove readiness with `/api/ready`, `/api/cluster/info`, and worker
7647+
registration. Do not shift production traffic based on `/api/health` alone.
75117648

75127649
## API Reference
75137650

0 commit comments

Comments
 (0)