---
title: "Self-host"
description: "Run OpenWork on your own server or infrastructure."
---

Most users just use the [desktop app](https://openworklabs.com/download). Self-hosting is for teams that want OpenWork to run on their own server, VPC, or private cloud and then connect the desktop app to it remotely.

Want hosted workspaces, team marketplaces, or shared providers without running infra? Use [OpenWork Cloud](/cloud/get-started) instead. Rolling this out across a company? [Book a call](https://calendar.app.google/86QpCENvhfEzDFLu5) about [Enterprise](/cloud/enterprise).

## What you deploy

OpenWork is split into normal services:

- **OpenWork app**: the desktop or web client people use.
- **Den web**: the web app for sign-in, worker launch, and connect links if you want a cloud-style setup.
- **Den controller**: the control plane for auth, workers, and provisioning.
- **Inference service**: optional OpenWork Models proxy and metering service.

If you only need one private remote workspace, deploy the worker runtime. If you want OpenWork Cloud-style accounts, teams, and organization management, deploy Den web, Den controller, and optionally the inference service.

For Kubernetes installs, use the published Helm chart:

```bash
helm upgrade --install openwork-ee oci://ghcr.io/different-ai/charts/openwork-ee \
  --version <chart-version> \
  -f values.prod.yaml
```

The chart pulls the matching GHCR images for `openwork-den-api`, `openwork-den-web`, and optional `openwork-inference` unless you mirror them into an internal registry.

## Plan the network

Use the dedicated Self-host planning pages instead of copying hostname, certificate, proxy, and diagnostics details into this overview:

- [Private network deployment](/start-here/private-network-deployment): the common topology where laptops have internet plus VPN access and Den stays private.
- [Air-gapped deployment](/start-here/air-gapped-deployment): definitions and the checklist for full isolation.
- [Outbound network access](/start-here/outbound-network-access): the canonical customer IT destination inventory and "what breaks when blocked" guidance.
- [Certificate trust and proxies](/start-here/certificate-trust-and-proxies): desktop, sidecar, Den, and MySQL trust surfaces.
- [Installer delivery](/start-here/installer-delivery): GitHub redirect, mounted artifacts, and MDM bootstrap choices.
- [Network diagnostics](/start-here/network-diagnostics): Windows doctor, Cloud catalog diagnostic trust, and Den outbound checks.

If you want self-hosted repository imports and sync from GitHub, configure the [GitHub connector for Helm](/start-here/github-connector-helm) after the core Den web and Den controller hosts are reachable.

To keep organization names, wordmarks, and desktop icons inside your deployment, follow [Brand an on-prem deployment](/start-here/on-prem-branding).

## How we deploy hosted workers

Our hosted deployment uses Render for long-running services and worker provisioning. Render gives us service deploys, env vars, health checks, logs, and worker builds without asking us to operate raw AWS services directly. If you want to run closer to AWS yourself, use the same service boundaries on ECS/Fargate, EC2, Kubernetes, or another container platform.

In production, hosted OpenWork runs the Cloud app and Den controller as scaled Render services with at least two instances. Render load balances traffic across healthy instances, removes failing instances from routing, and restarts failed instances. Den controller application instances are stateless replicas; shared control-plane state is stored in PlanetScale.

The production shape is straightforward:

- Put HTTPS in front of every public service.
- Expose the OpenWork server/worker URL, not raw opencode.
- Keep workspace and data paths on durable storage.
- Configure public URLs, auth origins, CORS origins, tokens, and provider credentials with env vars.
- Run Den database migrations before the Den controller receives traffic.

For containerized services, start from the [Docker packaging](https://github.com/different-ai/openwork/tree/dev/packaging/docker) in the repo.

## Databases and storage

- Worker runtimes use filesystem state and opencode SQLite data inside the mounted workspace/data paths.
- The Den control plane uses a MySQL-compatible database. Local Docker uses MySQL 8.4; production can use standard MySQL or PlanetScale-compatible credentials.
- Hosted OpenWork uses PlanetScale for Den control-plane state. PlanetScale production clusters provide one primary and at least two replicas across three availability zones, managed failover, and automated backups.
- Postgres is not required by the current Den deployment path.

For production, configure encryption explicitly:

- Enable encryption at rest for the MySQL-compatible database, database backups, object storage, worker volumes, and logs that may contain operational metadata.
- Require TLS for application-to-database traffic. `sslmode=require` encrypts the connection but is not certificate identity verification. For standard MySQL with certificate verification, use `sslmode=verify-ca`, `sslmode=verify-full`, or a strict equivalent such as `sslaccept=strict`, and provide the CA bundle through the database platform or Helm `customCa`.
- Keep the local Docker MySQL URL (`mysql://root:password@127.0.0.1:3306/openwork_den`) for development only; it is not a production security posture.
- Set a unique `DEN_DB_ENCRYPTION_KEY` of at least 32 characters. OpenWork uses it to encrypt selected sensitive database columns, but it does not replace infrastructure-level encryption at rest.

For a self-hosted production deployment, use a managed MySQL-compatible database with automated failover and backups, or provide equivalent redundancy yourself. Document the restore process, backup retention, recovery time objective, recovery point objective, and the person or team responsible for failover and restore.

## Auth and SSO

Den uses Better Auth. It runs in your deployment, uses your database, and is configured with your `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`, trusted origins, and optional GitHub/Google OAuth credentials.

SSO (SAML/OIDC) is in the current rollout and is designed to run against your own identity provider. When enabled, callback URLs and trusted origins should point at your self-hosted Den web/controller hosts.

For isolated Kubernetes deployments without approved outbound access to the Have I Been Pwned Pwned Passwords range API, the Helm chart disables external breached-password lookup by default. Email/password sign-in lockout remains local. If your deployment approves that external lookup, enable it in Helm. See [Air-gapped deployment](/start-here/air-gapped-deployment) for the broader isolation checklist.

If you do not deploy Den, worker access is token-based with `OPENWORK_TOKEN` and `OPENWORK_HOST_TOKEN`.

## Minimal working stack

### OpenWork Cloud and the desktop app

OpenWork cloud-style self-hosting is composed of three main pieces:

- Next.js frontend
- Node.js backend (Hono) with MySQL DB
- Electron/React desktop app

The desktop app should be pointed at the Den web URL when you use the single-origin topology. It derives API and MCP traffic through the Den web proxy:

- API: `<baseUrl>/api/den/v1/...`
- MCP: `<baseUrl>/api/den/mcp/...`

For self-hosted deployments, configure `baseUrl` to the public Den web origin and make sure that web app's `/api/den` route can reach your Den API backend. After sign-in, normal desktop API and MCP traffic does not use a separate API origin in that topology.

These three pieces cover most features, but do not include:

- Remote code execution through sandboxes
- Analytics
- Telemetry through OpenTelemetry
- Transactional email for invitations and lifecycle messages

## Optional vendors

OpenWork does not require many third-party services for the core runtime. These are optional or deployment-specific:

- Render: our current hosted service and worker deployment path.
- Daytona: optional sandbox provider for cloud workers.
- Vercel: optional Den web hosting and worker DNS automation.
- PostHog: optional analytics for public web surfaces. You can point it at self-hosted PostHog with `NEXT_PUBLIC_POSTHOG_HOST`, or remove/clear the key in your self-hosted web build if you do not want analytics.
- Polar: optional billing/paywall for hosted cloud workers.
- Loops: optional user sync and lifecycle messaging.
- GitHub/Google OAuth: optional social sign-in providers for Better Auth.
- GitHub connector app: optional repository connector for importing and syncing plugins or marketplaces from GitHub. For Helm installs, use the [GitHub connector setup guide](/start-here/github-connector-helm).

## Don't want to run infra?

Skip the server. [**OpenWork Cloud**](/cloud/get-started) runs hosted workers for your team.

Cloud also gives you org-wide primitives you'd otherwise have to build: [team templates](/cloud/share-with-your-team/team-templates), [shared LLM providers](/cloud/share-with-your-team/managed-llm-provider), [RBAC](/cloud/members-and-rbac), and [shared workspaces](/cloud/run-in-the-cloud/shared-workspace).

## Looking for support for a larger rollout?

If you're rolling OpenWork out across a company of 150\+ employees, a single self-hosted server VM might be harder to manage.

At that scale our customers typically want:

- **SSO (SAML/OIDC)** so people sign in with the identity your company already uses
- **Audit logs** across sessions, tool calls, and model usage
- **Model and tool allowlists** enforced centrally, not per-workspace
- **VPC / on-prem deployment** with your own networking and compliance constraints
- **Support and rollout help** from our team and custom deployment, not just in GitHub.

You can check the [**Enterprise**](/cloud/enterprise) page or [book a 30-minute call](https://calendar.app.google/86QpCENvhfEzDFLu5).
