# Deployment Strategies for OpenWork: Private Network, Air-Gapped, and Local Development

> Explore OpenWork deployment strategies: Private Network Helm, Air-Gapped, and Local Docker Compose. Configure your OpenWork setup using the official repository.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: deployment-strategies
- Published: 2026-08-02

---

**OpenWork supports three distinct deployment strategies—Private-Network Helm deployments for corporate LANs, Fully Air-Gapped installations with complete artifact mirroring, and Local Docker Compose stacks for development—all configurable through the official `different-ai/openwork` repository.**

The `different-ai/openwork` repository provides enterprise-grade deployment strategies that accommodate everything from rapid local prototyping to hardened, isolated production environments. Each strategy shares the same core architecture comprising the **Den API** (control-plane), **Den Web** (UI layer), optional **Inference** services, a MySQL-compatible database, and **Better Auth** for authentication, ensuring consistency across development and production.

## Core Architecture Across All Strategies

Every deployment strategy relies on the same service boundaries defined in the source tree:

| Component | Role | Source Reference |
|-----------|------|------------------|
| **Den API** | Control-plane service storing organizations, policies, and MCP connections | `packages/den-api` |
| **Den Web** | Web UI and reverse proxy that desktop clients authenticate against | `packages/den-web` |
| **Inference** | Optional internal model provider runtime | `packages/inference` |
| **MySQL-compatible DB** | Persistent state storage | External dependency |
| **Better Auth** | Authentication layer for desktop client sessions | Configured via Helm/Compose |

## Private-Network Deployment Strategy

**Private-Network deployment** is designed for organizations where developer laptops retain internet access (for npm packages, model catalogs, and installers), but the Den services must remain inside a corporate LAN or VPN. This semi-air-gapped approach uses the **OpenWork EE Helm Chart** documented in [`packaging/helm/openwork-ee/README.md`](https://github.com/different-ai/openwork/blob/main/packaging/helm/openwork-ee/README.md).

### Configuration

Create a [`values.private-network.yaml`](https://github.com/different-ai/openwork/blob/main/values.private-network.yaml) file that exposes Den Web as the single origin endpoint:

```yaml

# values.private-network.yaml

config:
  tenancy:
    mode: "single_org"
    singleOrgName: "Acme"
    singleOrgSlug: "acme"
    ownerEmails: "admin@acme.com"
  public:
    webOrigin: "https://openwork.acme.internal"
    apiOrigin: "https://api.openwork.acme.internal"
    mcpResourceUrl: "https://api.openwork.acme.internal/mcp"
    desktopDenBaseUrl: "https://openwork.acme.internal"
    corsOrigins: "https://openwork.acme.internal,https://api.openwork.acme.internal"
    betterAuthTrustedOrigins: "https://openwork.acme.internal"
secret:
  values:
    databaseUrl: "mysql://openwork:REPLACE_ME@mysql.internal:3306/openwork_den"
    betterAuthSecret: "REPLACE_WITH_32+_CHARS"
    denDbEncryptionKey: "REPLACE_WITH_32+_CHARS"

```

### Installation

Deploy using the OCI-hosted Helm chart:

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

```

In this configuration, Den Web acts as a reverse proxy for Den API (`/api/den`), allowing the desktop client to communicate through a single origin while all database and inference traffic remains internal. For detailed network diagrams and troubleshooting, refer to `packages/docs/start-here/private-network-deployment.mdx`.

## Fully Air-Gapped Deployment Strategy

**Fully Air-Gapped deployment** prohibits all outbound internet access, requiring every dependency—including Helm charts, container images, installer artifacts, model catalogs, and provider APIs—to be mirrored internally. This strategy uses the same Helm chart as the private-network approach but requires extensive pre-configuration.

### Prerequisites

According to `packages/docs/start-here/air-gapped-deployment.mdx`, you must mirror:

- **Deployment artifacts**: All images (`openwork-den-api`, `openwork-den-web`, `openwork-inference`) into an internal OCI registry
- **Installer artifacts**: Mount release files inside Den via `installerArtifacts.mountPath` and set `OPENWORK_INSTALLER_ARTIFACTS_DIR`
- **Desktop runtime**: Internal mirror for `OPENCODE_MODELS_URL` and npm registry for `npx openwork-ui-mcp`
- **Security**: Load private CAs using `customCa` in Helm values

### Configuration

Create a [`values.air-gapped.yaml`](https://github.com/different-ai/openwork/blob/main/values.air-gapped.yaml) that disables external dependencies:

```yaml

# values.air-gapped.yaml

config:
  tenancy:
    mode: "single_org"
    singleOrgName: "Acme"
    singleOrgSlug: "acme"
    ownerEmails: "admin@acme.com"
  public:
    webOrigin: "https://openwork.acme.internal"
    apiOrigin: "https://api.openwork.acme.internal"
    mcpResourceUrl: "https://api.openwork.acme.internal/mcp"
    desktopDenBaseUrl: "https://openwork.acme.internal"
    corsOrigins: "https://openwork.acme.internal"
    betterAuthTrustedOrigins: "https://openwork.acme.internal"
    installerReleaseTag: "v0.18.0"
    installerReleaseRepo: "different-ai/openwork"
    installerArtifacts:
      enabled: true
      existingClaim: openwork-desktop-artifacts
      mountPath: /var/lib/openwork/installer-artifacts
secret:
  create: false
customCa:
  enabled: true
  existingSecret: openwork-ca
  key: ca.crt

```

### Installation from Internal Registry

```bash
helm upgrade --install openwork-ee \
  oci://registry.internal/different-ai/openwork-ee \
  --version <release-tag> \
  -f values.air-gapped.yaml

```

All external URLs—including model catalogs and provider endpoints—must resolve to internal equivalents, or the desktop client will fail during authentication or model loading.

## Local Development Deployment Strategy

**Local Development deployment** uses Docker Compose to spin up Den API, Den Web, and MySQL on a single workstation. This strategy, defined in [`packaging/docker/docker-compose.den-dev.yml`](https://github.com/different-ai/openwork/blob/main/packaging/docker/docker-compose.den-dev.yml), is ideal for UI development, feature prototyping, and integration testing.

### Quick Start

Run the development stack:

```bash
docker compose -f packaging/docker/docker-compose.den-dev.yml up -d

```

The compose file exposes the following ports by default:

- `3005` → Den Web
- `8788` → Den API
- `3306` → MySQL

### Verification

Confirm service health before connecting a client:

```bash
curl http://localhost:3005/api/health   # Den Web health

curl http://localhost:8788/health       # Den API health

```

Once healthy, point the desktop client to `http://localhost:3005`. The default configuration automatically creates a single organization named **OpenWork** for immediate testing.

## Selecting the Right Deployment Strategy

| Requirement | Recommended Strategy | Configuration File |
|-------------|---------------------|-------------------|
| Fast iteration, no production SLA | **Docker Compose** | [`packaging/docker/docker-compose.den-dev.yml`](https://github.com/different-ai/openwork/blob/main/packaging/docker/docker-compose.den-dev.yml) |
| Enterprise on-prem with internet access | **Private-Network Helm** | [`values.private-network.yaml`](https://github.com/different-ai/openwork/blob/main/values.private-network.yaml) |
| Strict security, no outbound traffic | **Air-Gapped Helm** | [`values.air-gapped.yaml`](https://github.com/different-ai/openwork/blob/main/values.air-gapped.yaml) |
| Managed Kubernetes (EKS, AKS, GKE) | **Private-Network Helm** | Chart examples in `packaging/helm/openwork-ee/` |

All strategies share the same codebase, allowing seamless promotion from local Docker Compose development to production Kubernetes deployments without modification.

## Summary

- **Private-Network deployments** use the `openwork-ee` Helm chart to keep Den services inside corporate networks while allowing desktop clients internet access for dependencies.
- **Air-Gapped deployments** require complete mirroring of Helm charts, container images, installer artifacts, and model catalogs into internal infrastructure, configured via [`values.air-gapped.yaml`](https://github.com/different-ai/openwork/blob/main/values.air-gapped.yaml).
- **Local development** relies on [`docker-compose.den-dev.yml`](https://github.com/different-ai/openwork/blob/main/docker-compose.den-dev.yml) for disposable, workstation-based environments with automatic single-organization creation.
- All strategies depend on the same five core components: Den API, Den Web, Inference (optional), MySQL, and Better Auth.

## Frequently Asked Questions

### What are the core components required for every OpenWork deployment?

Every deployment strategy requires the **Den API** (control-plane), **Den Web** (UI and reverse proxy), a **MySQL-compatible database**, and **Better Auth** for authentication. The **Inference** service is optional and only required if running model providers internally rather than using external APIs.

### How do I deploy OpenWork without any internet access?

Use the **Fully Air-Gapped** strategy. You must mirror the `openwork-ee` Helm chart and all container images (`openwork-den-api`, `openwork-den-web`, `openwork-inference`) into an internal OCI registry, mount installer artifacts via the `installerArtifacts` configuration, and point all external URLs (model catalogs, npm registries) to internal mirrors as documented in `packages/docs/start-here/air-gapped-deployment.mdx`.

### Can I run OpenWork locally without Kubernetes?

Yes. Clone the `different-ai/openwork` repository and run `docker compose -f packaging/docker/docker-compose.den-dev.yml up -d`. This starts Den API on port `8788`, Den Web on port `3005`, and MySQL on port `3306`, suitable for development and testing without Kubernetes overhead.

### What is the difference between single-organization and multi-tenant modes?

In `single_org` mode (configured via `config.tenancy.mode`), the deployment automatically provisions one organization at startup using the `singleOrgName`, `singleOrgSlug`, and `ownerEmails` values. Multi-tenant mode allows dynamic organization creation through the API. Single-organization mode is recommended for enterprise deployments where a single entity manages the instance.