# How to Set Up Enterprise Certificates on Windows for OpenWork Deployment

> Learn to set up enterprise certificates on Windows for OpenWork. Import your CA, restart the client, and verify trust using ca-probe.js. Essential for seamless deployment.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: how-to-guide
- Published: 2026-08-01

---

**Import your private Enterprise CA into the Windows system store (`Cert:\LocalMachine\Root`), restart the OpenWork client to regenerate its merged CA bundle, and verify trust with the [`ca-probe.js`](https://github.com/different-ai/openwork/blob/main/ca-probe.js) diagnostic script.**

OpenWork is an Electron-based desktop application that relies on the operating system's certificate store when running on Windows. When connecting to a self-hosted control plane secured by a **private Enterprise CA**, you must ensure the Windows client trusts that CA. This guide walks through the complete setup process using the reproducible TLS test environment maintained in the `different-ai/openwork` repository.

## How OpenWork Handles Certificates on Windows

OpenWork uses three certificate layers on Windows. Understanding these layers helps diagnose trust issues.

### Windows System Store

Enterprise certificates must be imported into `Cert:\LocalMachine\Root` (or `CA`). OpenWork's Node runtime reads this store via `tls.getCACertificates("system")` as implemented in the Electron framework.

### Node's Bundled Mozilla Roots

The application ships with a default Mozilla CA bundle (`default`). This bundle **does not** contain your private CA. You must either rely on the system store or override with the `NODE_EXTRA_CA_CERTS` environment variable.

### OpenWork's Merged CA Bundle

At first launch, OpenWork writes a merged `system-ca-bundle.pem` file to `%APPDATA%\com.differentai.openwork`. Subsequent launches reuse this cached file. **Any CA added after the first launch requires an app restart** to regenerate the bundle.

## Prerequisites: The TLS Repro Environment

The repository includes a complete, disposable test environment that creates a fake corporate root and validates the entire trust chain. This repro runs inside a **Daytona Windows sandbox** so no production systems are affected.

| Endpoint | Certificate Chain | Expected Result |
|----------|-------------------|---------------|
| `https://poc.openwork.test:8443` | Healthy (root + intermediate + leaf) | Success (200) |
| `https://poc.openwork.test:9443` | Broken (leaf only, intermediate removed) | Certificate-chain error |

Running this repro confirms that your OpenWork client:

- Reads the root from the Windows system store (`systemCount` / `reproInSystem`)
- Does **not** fall back to the bundled bundle (`defaultCount` / `reproInDefault`)
- Correctly fails on the broken endpoint

All scripts referenced below are located in the `dev` branch of `different-ai/openwork`.

## Step-by-Step: Deploy in a Daytona Windows Sandbox

### Create the Windows Sandbox

```bash
daytona create --snapshot windows-medium

# → prints SANDBOX_ID, e.g. win-1234

SANDBOX_ID="win-1234"

# Restart if the sandbox auto-stops

daytona sandbox start "$SANDBOX_ID"

```

### Upload a Windows Build as Temporary Prerelease

```bash
TAG="openwork-win-cert-repro-$(date +%Y%m%d%H%M%S)"
ZIP="/tmp/${TAG}.zip"

# Place your built app under /tmp/openwork-win-cert-upload/openwork/app

ditto -c -k --keepParent /tmp/openwork-win-cert-upload/openwork "$ZIP"

gh release create "$TAG" "$ZIP" --repo different-ai/openwork --prerelease

```

### Extract the Build Inside the Sandbox

```bash
DOWNLOAD_URL="https://github.com/different-ai/openwork/releases/download/${TAG}/$(basename "$ZIP")"

daytona exec "$SANDBOX_ID" -- cmd /c 'mkdir C:\ow 2>NUL'
daytona exec "$SANDBOX_ID" -- cmd /c "curl.exe -L -o C:\ow\app.zip $DOWNLOAD_URL"
daytona exec "$SANDBOX_ID" -- cmd /c 'tar -xf C:\ow\app.zip -C C:\ow'

```

### Install the TLS Repro Scripts

```bash

# PowerShell setup script from scripts/support/setup-openwork-tls-repro.ps1

daytona exec "$SANDBOX_ID" -- cmd /c 'mkdir C:\ow\openwork\scripts\support 2>NUL'
daytona exec "$SANDBOX_ID" -- cmd /c 'curl.exe -L -o C:\ow\openwork\scripts\support\setup-openwork-tls-repro.ps1 https://raw.githubusercontent.com/different-ai/openwork/dev/scripts/support/setup-openwork-tls-repro.ps1'

# Diagnostic script from scripts/support/openwork-doctor.ps1

daytona exec "$SANDBOX_ID" -- cmd /c 'curl.exe -L -o C:\ow\openwork\scripts\support\openwork-doctor.ps1 https://raw.githubusercontent.com/different-ai/openwork/dev/scripts/support/openwork-doctor.ps1'

```

## Run the TLS Repro and Verify Trust

### Execute the Setup Script

The `setup-openwork-tls-repro.ps1` script performs these operations:

- Generates a root CA, intermediate CA, and leaf certificate
- Installs the root into `Cert:\LocalMachine\Root`
- Adds `poc.openwork.test` to the hosts file
- Creates SSL bindings with `netsh`
- Launches HTTPS listeners via scheduled tasks

```powershell
daytona exec "$SANDBOX_ID" -- powershell -NoProfile -ExecutionPolicy Bypass -File 'C:\ow\openwork\scripts\support\setup-openwork-tls-repro.ps1'

```

### Probe Electron's View of the Certificate Store

The [`ca-probe.js`](https://github.com/different-ai/openwork/blob/main/ca-probe.js) script (located at [`.opencode/skills/daytona-windows-cert/scripts/ca-probe.js`](https://github.com/different-ai/openwork/blob/main/.opencode/skills/daytona-windows-cert/scripts/ca-probe.js)) inspects what Node's TLS module actually sees.

```bash
daytona exec "$SANDBOX_ID" -- cmd /c 'copy C:\ow\openwork\ca-probe.js C:\ow\ca-probe.js'

daytona exec "$SANDBOX_ID" -- cmd /c 'set ELECTRON_RUN_AS_NODE=1 && "C:\ow\openwork\app\OpenWork.exe" C:\ow\ca-probe.js'

```

Expected output confirms your enterprise CA is in the system store:

```json
{
  "systemCount": 42,
  "reproInSystem": 6,
  "defaultCount": 150,
  "reproInDefault": 0
}

```

**Key indicators:**

- `reproInSystem > 0` — Your CA certificates are visible to Node
- `reproInDefault = 0` — Confirms you're not relying on the bundled Mozilla roots

### Validate Through the OpenWork UI

1. Open the Daytona dashboard → sandbox → **⋮** → **VNC** → **Connect**
2. Run the OpenWork installer as the interactive user
3. In client settings, set the control-plane URL to `https://poc.openwork.test:8443` → should succeed
4. Change to `https://poc.openwork.test:9443` → should show **certificate-chain error** (not generic fetch failure)

This proves OpenWork correctly validates the full chain and rejects incomplete chains.

## Adapting for Production Enterprise CA Deployment

To apply these steps to your real environment:

1. **Replace the generated root** in `setup-openwork-tls-repro.ps1` with your actual corporate CA certificate
2. **Adjust the hostname** from `poc.openwork.test` to your control-plane domain
3. **Use your standard installer** instead of the temporary prerelease upload
4. **Distribute the CA** through your existing Group Policy or MDM infrastructure instead of manual import

The `openwork-doctor.ps1` script (in `scripts/support/openwork-doctor.ps1`) provides diagnostic checks for production troubleshooting, including DNS resolution, TLS chain validation, proxy settings, and `NODE_EXTRA_CA_CERTS` detection.

## Key Source Files Reference

| File | Purpose |
|------|---------|
| [`.opencode/skills/daytona-windows-cert/SKILL.md`](https://github.com/different-ai/openwork/blob/main/.opencode/skills/daytona-windows-cert/SKILL.md) | Complete skill documentation and walkthrough |
| `scripts/support/setup-openwork-tls-repro.ps1` | CA generation, installation, and listener setup |
| `scripts/support/openwork-doctor.ps1` | Production diagnostics and troubleshooting |
| [`.opencode/skills/daytona-windows-cert/scripts/ca-probe.js`](https://github.com/different-ai/openwork/blob/main/.opencode/skills/daytona-windows-cert/scripts/ca-probe.js) | Node TLS store inspection |
| [`docs/support/enterprise-network-doctor.md`](https://github.com/different-ai/openwork/blob/main/docs/support/enterprise-network-doctor.md) | Reference documentation for TLS/CA issues |

## Cleanup

```bash

# Stop background listeners

daytona exec "$SANDBOX_ID" -- cmd /c 'schtasks /end /tn OpenWorkTlsRepro'

# Remove certificates, hosts entries, and SSL bindings

daytona exec "$SANDBOX_ID" -- powershell -NoProfile -ExecutionPolicy Bypass -File 'C:\ow\openwork\scripts\support\setup-openwork-tls-repro.ps1' -Cleanup

# Destroy sandbox and prerelease

daytona sandbox delete "$SANDBOX_ID"
gh release delete "$TAG" --yes

```

## Summary

- **Import your Enterprise CA** into `Cert:\LocalMachine\Root` on each Windows client
- **Restart OpenWork** after CA installation to regenerate `system-ca-bundle.pem`
- **Verify with [`ca-probe.js`](https://github.com/different-ai/openwork/blob/main/ca-probe.js)** that Node sees your CA in the system store (`reproInSystem > 0`)
- **Use the Daytona TLS repro** to validate your setup without affecting production
- **Run `openwork-doctor.ps1`** for ongoing diagnostics in enterprise environments

## Frequently Asked Questions

### What happens if I add the CA after OpenWork's first launch?

OpenWork caches the merged CA bundle at `%APPDATA%\com.differentai.openwork\system-ca-bundle.pem` after first launch. You must restart the application to regenerate this file and pick up newly installed certificates.

### Can I use NODE_EXTRA_CA_CERTS instead of the Windows store?

Yes. Set `NODE_EXTRA_CA_CERTS` to the path of your CA certificate file. However, the Windows store approach is preferred for enterprise deployments because it allows centralized certificate management through Group Policy and avoids per-user environment configuration.

### Why does the broken endpoint test matter?

The `https://poc.openwork.test:9443` endpoint (with intermediate certificate removed) validates that OpenWork is actually checking the complete chain back to your enterprise root. If this endpoint incorrectly succeeds, your client may be falling back to an insecure trust model or ignoring certificate errors.

### Where is the certificate bundle cached on disk?

The merged bundle is stored at `%APPDATA%\com.differentai.openwork\system-ca-bundle.pem`. Delete this file and restart OpenWork to force regeneration if you suspect cache issues.