> ## Documentation Index
> Fetch the complete documentation index at: https://openworklabs.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> For agents: install the OpenWork desktop app with `brew install --cask openwork` (macOS) or from https://openworklabs.com/download. Do not run `npx openwork`; the npm package named `openwork` is a different project.
> Connect an agent to OpenWork with the MCP Gateway: `claude mcp add --transport http openwork https://api.openworklabs.com/mcp/agent`. Teams sign up at https://app.openworklabs.com?mode=sign-up.
> Step-by-step agent guide: https://openworklabs.com/docs/start-here/use-openwork-from-an-ai-agent.md
> Connect Slack (any organization admin): https://openworklabs.com/docs/slack/connect-slack.md. OpenWork in Slack (@openwork bot) is private alpha for approved organizations. Setup guide: https://openworklabs.com/docs/slack/overview.md. Agent skill: https://openworklabs.com/.well-known/agent-skills/set-up-openwork-slack/SKILL.md.

# Deploy to your cloud

> Run OpenWork in your AWS, Azure, or Google Cloud account with managed MySQL and either Kubernetes or Cloud Run.

OpenWork's primary private-cloud shape uses the published Helm chart, a managed Kubernetes cluster, and a MySQL-compatible database in your own account. A Google Cloud Run starter is also available for Den Web and Den API. You control the network, DNS, certificates, database, backups, identity provider, and secrets.

> [card] [AWS](https://openworklabs.com/docs/self-host/deploy-to-your-cloud/aws.md)
>
> Deploy on EKS or ECS Fargate with Amazon RDS for MySQL.

> [card] [Azure](https://openworklabs.com/docs/self-host/deploy-to-your-cloud/azure.md)
>
> Deploy on AKS or Container Apps with Azure Database for MySQL.

> [card] [Google Cloud](https://openworklabs.com/docs/self-host/deploy-to-your-cloud/google-cloud.md)
>
> Deploy on GKE or Cloud Run with Cloud SQL for MySQL.

## Terraform modules (beta)

> [!WARNING]
>
> OpenWork's Terraform modules are **beta**. If you hit an issue:
>
> * **Customers with a support agreement:** contact your OpenWork team through your usual support channel.
> * **Everyone else:** [open a GitHub issue](https://github.com/different-ai/openwork/issues/new/choose).
> * **Security issues:** report them privately ([SECURITY.md](https://github.com/different-ai/openwork/blob/dev/SECURITY.md)).
>
> Pin the module source to a reviewed commit and check its tested scenarios,
> upgrade notes, and known limitations before deploying. Do not include secrets
> or private state in reports.

These cloud-native options deploy the core Den web and Den API services without
Kubernetes. They do not imply support for every optional Helm component or the
hosted managed installer. All three modules are available on `dev` with the same
beta support level; their tested scenarios and cloud-specific limits differ:

| Cloud | What the module deploys | Support and availability | Guide and source |
| - | - | - | - |
| AWS | ECS Fargate services, HTTPS ALB, RDS for MySQL, Secrets Manager, and a dedicated migration task | **Beta**; on `dev` | [AWS guide](https://openworklabs.com/docs/self-host/deploy-to-your-cloud/aws.md), [module](https://github.com/different-ai/openwork/tree/dev/infra/terraform/modules/openwork-aws-ecs) |
| Google Cloud | Cloud Run services, Cloud SQL for MySQL, Secret Manager, and a dedicated migration job | **Beta**; on `dev` | [Google Cloud guide](https://openworklabs.com/docs/self-host/deploy-to-your-cloud/google-cloud.md), [module](https://github.com/different-ai/openwork/tree/dev/infra/terraform/modules/openwork-gcp-cloud-run) |
| Azure | Container Apps services, MySQL Flexible Server, secret references, and a dedicated migration job | **Beta**; on `dev` | [Azure guide](https://openworklabs.com/docs/self-host/deploy-to-your-cloud/azure.md), [module](https://github.com/different-ai/openwork/tree/dev/infra/terraform/modules/openwork-azure-container-apps) |

The [shared module contract](https://github.com/different-ai/openwork/blob/dev/infra/terraform/MODULE_CONTRACT.md)
describes migration ordering, secrets preservation, tool compatibility, and the
per-cloud limits. A successful core smoke run is not production load, backup
restoration, or legacy-upgrade certification. Follow the source revision's README
for exact inputs and test coverage. Availability on `dev` does not imply a tagged
module release or production qualification.

## Small / trial sizing

These **provisional defaults** cover the core Den services, based on light
setup/sign-in measurements (one administrator and a few sign-ins), not a tested
user count. Medium/Large tiers require load and soak tests and are not specified.
Optional Gateway, Workbot and runner services need separate sizing.

| Deployment | Den API per copy | Den web per copy | MySQL baseline | Database-update step |
| - | - | - | - | - |
| AWS ECS module | 1 vCPU / 2 GiB | 0.5 vCPU / 1 GiB | db.t4g.small, 2 GiB memory, 20 GiB disk | 1 vCPU / 2 GiB |
| Google Cloud Run module | 1 vCPU / 2 GiB | 1 vCPU / 1 GiB | db-g1-small, 1.7 GB memory, 20 GB disk | 1 vCPU / 2 GiB |
| Azure Container Apps module | 1 vCPU / 2 GiB | 0.5 vCPU / 1 GiB | B\_Standard\_B1ms, 2 GiB memory, 20 GB disk | 0.5 vCPU / 1 GiB |

The Helm chart sets no default resource requests or limits; set them for your cluster.

Cloud modules start with one API and one web copy; use two API copies when you
need service redundancy, with additional compute cost. This alone does not make
the database highly available. Keep automated database backups enabled.
Google Cloud's 1.7 GB shared-core database is a **trial-only exception** to the
2 GB recommendation: it has no Cloud SQL SLA; choose a dedicated tier for
production after measuring. Cloud Run's web default remains 1 CPU for its
request-driven service configuration. Migration-job peaks were not sampled;
the envelopes above are provisional headroom, not measured peaks.

### Default changes and estimated monthly cost

USD public on-demand list-price estimates checked 2026-10-19, 730 hours/month
for hourly charges. These are **component deltas, not total deployment quotes**;
exclude taxes, discounts/free tiers, network/backup charges and AWS CPU credits.

| Change | Region | Before → after | Monthly increase (estimate) |
| - | - | - | - |
| AWS Single-AZ MySQL instance | us-east-1 | micro $0.016/h → small $0.032/h; $11.68 → $23.36/month | **+\$11.68** |
| Cloud SQL zonal MySQL SSD | us-central1 | 10 → 20 GB at $0.17/GB-month; $1.70 → \$3.40/month | **+\$1.70** |
| AWS/GCP application sizes; Azure module | us-east-1 / us-central1 / eastus | Unchanged | **\$0** |

Sources: [AWS RDS pricing](https://aws.amazon.com/rds/mysql/pricing/),
[Cloud SQL pricing](https://cloud.google.com/sql/pricing/).
Existing direct AWS users see an in-place class change and a database restart
when performed; [pin micro before upgrading to opt out](https://openworklabs.com/docs/self-host/deploy-to-your-cloud/aws.md#upgrade-notes).
Existing direct GCP users see online storage growth, which cannot be shrunk;
[pin 10 GB before applying to opt out](https://openworklabs.com/docs/self-host/deploy-to-your-cloud/google-cloud.md#upgrade-notes).

Managed installers retain their own pinned **small** profiles, not a promise of
identical sizes across clouds. AWS currently pins micro, API 1 vCPU / 2 GiB,
web 0.5 vCPU / 1 GiB; GCP currently uses db-custom-1-3840 with 20 GB disk,
API 2 vCPU / 2 GiB and web 1 vCPU / 1 GiB. They are untouched here.
Aligning them needs a separately reviewed installer change that preserves
existing sizes and obtains explicit approval for resize, restart or cost changes;
updating direct-module defaults does not authorize a managed resize.

## Managed installation from hosted OpenWork

The default-off **Deployments** rollout lets workspace owners approve an AWS
installer in their own account and track health and approved updates. AWS, GCP
and deployment agent tools share the cloud-only, default-off `managedDeployments`
rollout. GCP uses customer-approved Google Cloud Shell and requires a dedicated
billing-enabled project, public Cloud DNS, and an operator-published immutable
installer release. Local tests are not a live deployment receipt; the GCP
rollout must stay off until a real release and approved installation are verified.
Azure is not supported by the managed installer yet.

A locked installer message is server-side publication/configuration—not a
request for your cloud keys. Signing in to AWS or Google Cloud on your Mac
cannot publish the installer. Operators follow
[the managed-deployment runbook](https://github.com/different-ai/openwork/blob/dev/docs/managed-deployments.md);
manual deployments below remain independent of the rollout.

## Common architecture

Every provider guide uses the same OpenWork boundaries:

* Den web listens on port `3005` and serves the browser experience.
* Den API listens on port `8788` and owns authentication, organizations, policy, and control-plane APIs.
* A MySQL 8-compatible database stores shared control-plane state.
* The default migration Job is a pre-install/pre-upgrade hook, not an automatic safe rolling schema cutover.
* OpenWork Gateway is optional and disabled by default; it retains the `openwork-inference` image and `*-inference` resource names. It is not the separate `den-gateway` Web proxy.
* HTTPS hostnames expose web and API traffic through the provider's load-balancing layer.

Use private database networking in production. Require TLS for public application traffic, encrypt storage and backups, and keep database and authentication secrets in the provider secret store or a Kubernetes Secret—not in a Helm values file.

## Reverse-proxy client addresses

Set `DEN_TRUSTED_PROXIES` on Den API to a comma-separated list of your reverse
proxies' IP addresses or CIDRs (for example, `192.0.2.10,192.0.2.11`). Better Auth
uses this list to resolve forwarded client addresses for authentication rate
limits. Without it, clients can share a fallback rate-limit bucket.

Only include the proxies you operate, not broad ranges containing clients. Your
origin must accept traffic only from those proxies, and the proxies must overwrite
or safely append forwarded headers. This setting interprets the forwarded chain;
it cannot verify the direct sender. Leave it unset when there is no trusted proxy.
Keep rate limiting enabled in production.

If Den Web runs on Vercel, its outgoing addresses change, so it cannot be listed
as a trusted proxy. Set the same `DEN_WEB_CLIENT_IP_SECRET` (32+ characters) on
Den Web and Den API instead. Den Web then signs the address Vercel saw for each
person, and Den API accepts only a valid signature less than five minutes old.

Sign-up, sign-in, and verification-code limits are counted per email address
first, with a much larger allowance per client address. People behind one office
network can sign up together, and a sign-up from a valid invitation link does not
count against the shared address.

## Deployment sequence

1. Create the Kubernetes cluster and private MySQL database in compatible networks.
2. Reserve the public address or load-balancer entry point.
3. Create the database, database user, and Kubernetes namespace.
4. Generate independent database, Better Auth, and Den encryption secrets.
5. Prepare provider-specific Helm values for the web and API hostnames.
6. For a fresh database, install the matching chart/images and verify initialization before opening traffic. For an existing database, follow the release-specific migration and rollout procedure; Gateway requires the [quiesced upgrade guide](https://openworklabs.com/docs/self-host/gateway-upgrade.md), not an unattended rolling upgrade.
7. Point DNS at the load balancer and verify trusted HTTPS.
8. [Create the first administrator](https://openworklabs.com/docs/self-host/deploy-to-your-cloud/first-administrator.md).
9. Configure SAML or OIDC SSO and invite or provision members.

## Before you start

You need:

* a cloud account with permission to create Kubernetes, networking, load-balancing, managed MySQL, DNS, certificates, and secrets;
* `kubectl` and Helm, plus the provider CLI and Kubernetes authentication plugin;
* two DNS names, normally one for Den web and one for Den API;
* a real email address for the initial owner;
* a backup, restore, upgrade, and rollback plan.

> [!NOTE]
>
> The provider pages give the supported architecture and point to the repository's detailed operator runbooks for exact commands. Pin a chart version in production and use the runbook from the matching release or branch.

## After deployment

To configure Gateway, follow [Enable OpenWork Gateway](https://openworklabs.com/docs/self-host/gateway.md). This requires the Gateway-capable chart implementation introduced in `0.2.0` or later, matching release images, and an authenticated capability-version-1 response. Gateway is GA for admins in every organization when configured; no platform-admin organization grant or organization API toggle is needed. `GATEWAY_ENABLED` and `deploymentCapabilities.aiGateway` remain installation configuration checks. Neither legacy service enablement nor existing OpenWork Models billing enables the deployment automatically.

## Scheduled maintenance jobs

Two maintenance tasks run on a schedule instead of on every request, so busy write paths never queue behind a shared totals row. Other background work (SCIM cleanup, Automations, worker reconciliation, provider token refresh) runs inside Den API or the Gateway and needs no setup.

| Job | What it does | Hosted schedule | Helm values | Endpoint and token |
| - | - | - | - | - |
| Gateway usage rollup | Folds Gateway request logs older than two days into hourly usage rollups and deletes the folded rows; folds hourly rollups older than 90 days into daily ones. | Hourly, `5 * * * *` | `gateway.retention.*` (off by default) | Gateway `POST /internal/rollups/run`, `GATEWAY_ADMIN_TOKEN` |
| Audit usage refresh | Recomputes each organization's audit usage totals (retained operations, events, bytes). | Daily | `denApi.auditUsage.*` (off by default, `30 3 * * *`) | Den API `POST /internal/audit/usage/refresh`, `DEN_MAINTENANCE_TOKEN` |

Both endpoints answer `404` when their token is not configured and `401` for a wrong token. Both are safe to rerun.

With Helm, enable each job and its token as described in [Enable OpenWork Gateway](https://openworklabs.com/docs/self-host/gateway.md#optional-admin-webhook-and-retention) and the chart README's *Audit usage refresh* section. On Cloud Run, ECS Fargate, or Docker Compose, schedule the calls yourself with Cloud Scheduler, EventBridge Scheduler, or host cron, from a network location that can reach the internal service:

```sh theme={null}
# Hourly, only when Gateway is enabled
curl -fsS -X POST -H "Authorization: Bearer $GATEWAY_ADMIN_TOKEN" \
  -H "content-type: application/json" \
  -d '{"maxBucketsPerRun":48,"maxSourceRowsPerBucket":5000}' \
  http://<gateway-internal-host>:8791/internal/rollups/run

# Daily
curl -fsS -X POST -H "Authorization: Bearer $DEN_MAINTENANCE_TOKEN" \
  http://<den-api-internal-host>:8788/internal/audit/usage/refresh
```

Without the rollup job, Gateway request logs are never compacted and grow without limit. Without the audit refresh, the audit usage screen keeps showing its last measured totals.

Use [Private network deployment](https://openworklabs.com/docs/start-here/private-network-deployment.md) when Den is reachable only through a VPN or private network. Review [Outbound network access](https://openworklabs.com/docs/start-here/outbound-network-access.md), [Certificate trust and proxies](https://openworklabs.com/docs/start-here/certificate-trust-and-proxies.md), and [Air-gapped deployment](https://openworklabs.com/docs/start-here/air-gapped-deployment.md) before restricting egress.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.