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

# Air-Gapped Devin Network and Certificates

> Configure air-gapped Devin Desktop and CLI for your network: trust a private CA with DEVIN_CA_BUNDLE, use a proxy, and resolve NET and CFG004 codes.

> [!NOTE]
>
> This documentation is for the federal deployments of Devin. [Back to Devin Docs](/get-started/devin-intro)

The air-gapped CLI and Desktop connect to the model endpoints in your [models file](/federal/air-gapped/models-file), the identity provider issuer in your [auth file](/federal/air-gapped/sso), and any MCP servers you configure locally. This page covers what those connections require from your network: TLS trust, an optional proxy, and the codes you see when a connection fails.

***

## TLS requirements

* Every model `base_url` and the SSO `issuer` must be `https://`. Plain `http://` is accepted only for loopback hosts (`localhost`, `127.0.0.0/8`, `[::1]`).
* Certificates are verified with the operating system's trust store (Security.framework on macOS, the system CA store on Linux). If your endpoints are signed by a CA that is already installed on the workstation, no further configuration is needed.
* If your endpoints are signed by a private CA that is *not* in the OS trust store, add it with `DEVIN_CA_BUNDLE` as described below. The CLI never disables certificate verification.

## Trust a private CA with `DEVIN_CA_BUNDLE`

`DEVIN_CA_BUNDLE` names a PEM file whose certificates are trusted **in addition to** the OS trust store. It applies to inference requests, to `devin airgap doctor` probes, and to every request the CLI makes to your IdP during SSO login and revalidation.

**1. Assemble the bundle**

Put the root (and, if you use one, intermediate) certificates of your private CA into a single PEM file. The file may contain several `-----BEGIN CERTIFICATE-----` blocks.

```sh theme={null}
sudo install -m 0644 ./corp-root-ca.pem /etc/devin/ca-bundle.pem
```

Your endpoints do not need to share a certificate or a CA. There is one bundle for the whole agent process and it applies to every connection, so if different endpoints are signed by different private CAs, concatenate all of those CAs into the same file:

```sh theme={null}
cat ./corp-root-ca.pem ./ml-platform-ca.pem ./idp-root-ca.pem | sudo tee /etc/devin/ca-bundle.pem > /dev/null
sudo chmod 0644 /etc/devin/ca-bundle.pem
```

With that bundle, `https://vllm.corp.example` (signed by `corp-root-ca`), `https://models.ml.example` (signed by `ml-platform-ca`) and your IdP (signed by `idp-root-ca`) are all trusted. Endpoints signed by a CA that is already in the OS trust store need no entry. The models file has no per-model certificate or TLS fields, and a separate bundle per endpoint is not supported.

**2. Export the variable in the agent's environment**

```sh theme={null}
export DEVIN_CA_BUNDLE=/etc/devin/ca-bundle.pem
```

The variable must be visible to the process that runs the agent. For the terminal CLI, set it in the shell profile of every user. For Desktop, set it the same way you set model API-key variables (see [API key environment variables](/federal/air-gapped/models-file#api-key-environment-variables)): add it to the `devin.acp.agentEnv` setting, or on macOS use `launchctl setenv DEVIN_CA_BUNDLE /etc/devin/ca-bundle.pem` (`open` does not pass your shell's environment to the app).

**3. Confirm with doctor**

```sh theme={null}
devin airgap doctor
```

```text theme={null}
…
pass  CA bundle                                 /etc/devin/ca-bundle.pem (3 certificate(s))
pass  model 'llama-3.3-70b': endpoint reachability  GET https://vllm.corp.example/v1/models -> 200 OK (trusted only via DEVIN_CA_BUNDLE — the OS trust store alone rejects this endpoint's certificate)
pass  model 'qwen3-vl-32b': endpoint reachability  GET https://models.ml.example/v1/models -> 200 OK (trusted only via DEVIN_CA_BUNDLE — the OS trust store alone rejects this endpoint's certificate)
…
```

The suffix `trusted only via DEVIN_CA_BUNDLE` confirms the bundle is what makes the endpoint trusted: doctor retries each reachable endpoint with the OS trust store alone and reports whether that attempt fails on TLS. Without the variable set, the CA bundle row reads `not configured (OS trust store only; set DEVIN_CA_BUNDLE to add a private CA)`.

If the file cannot be read, contains an invalid PEM section, or contains no certificates, doctor fails the **CA bundle** check with `CFG004` and the message from the parser (for example `failed to read CA bundle '/etc/devin/ca-bundle.pem': No such file or directory`). At runtime the same condition is not fatal: the CLI prints a `warning: ignoring DEVIN_CA_BUNDLE: …` line and falls back to the OS trust store, so a typo in the path shows up as `NET003` TLS failures against your endpoints rather than as a startup error. Fix the bundle and re-run doctor.

## Proxy

The air-gapped CLI uses the same outbound proxy handling as the standard Devin CLI. By default (`"mode": "system"`) it honors the `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `NO_PROXY` environment variables and the operating system's PAC/auto-proxy settings. To force a specific proxy or to bypass proxies entirely, add a `proxy` block to the user config file (`config.json` in the shared Devin config directory; see [On-disk formats](/federal/air-gapped/on-disk-formats)):

```json theme={null}
{
  "proxy": {
    "mode": "manual",
    "url": "http://proxy.corp.example:8080",
    "no_proxy": "localhost,127.0.0.1,.corp.example"
  }
}
```

| `mode` | Behavior |
| - | - |
| `"system"` (default) | Use proxy environment variables and platform PAC settings. |
| `"manual"` | Send all traffic through `url` (`http://`, `https://`, or `socks5://`). Environment-variable proxies are ignored. |
| `"off"` | Connect directly; ignore all proxy settings. |

`no_proxy` applies in every mode and uses the same syntax as the `NO_PROXY` environment variable. To set the proxy for all users on a host, place the same `proxy` block in the machine-wide policy file `system.json` (`/etc/devin/system.json` on Linux, `/Library/Application Support/Devin/system.json` on macOS, `C:\ProgramData\Devin\system.json` on Windows); if both files define `proxy`, the CLI refuses to start until you remove the user copy. The full option reference is in the [CLI config file reference](/cli/reference/configuration/config-file#proxy).

A proxy that terminates TLS and re-signs traffic with its own CA counts as a private CA: add its certificate to `DEVIN_CA_BUNDLE`. Connections still go only to the destinations listed at the top of this page; the proxy changes the path, not the set of destinations.

## Timeouts

| Connection | Timeout |
| - | - |
| `devin airgap doctor` probes (connect and total) | 10 seconds per request |
| SSO requests to the IdP (discovery, token, JWKS) | 30 seconds per request |
| Inference requests | 30 seconds to connect; 300 seconds without data before the read is abandoned |

A probe that exceeds its timeout is reported as `NET005`.

## NET codes

`devin airgap doctor` attaches one of these codes to every failed endpoint probe. They are also the codes you will see in support requests. The full catalog is on the [Error codes](/federal/air-gapped/error-codes) page.

| Code | Meaning | What to do |
| - | - | - |
| `NET001` | DNS resolution of the endpoint host failed. | Check the hostname in the models or auth file and that the workstation's resolver can resolve it (`getent hosts <host>` or `dig <host>`). |
| `NET002` | TCP connection could not be established (refused, reset, unroutable). | Check that the port is open from the workstation and that any firewall or proxy allows it. |
| `NET003` | TLS handshake failed (untrusted, expired, or mismatched certificate). Doctor appends the certificate the server presented (`subject`, `issuer`, `expires`) when it can obtain it, and whether `DEVIN_CA_BUNDLE` was in effect. | If the issuer is your private CA, set or fix `DEVIN_CA_BUNDLE`. If the certificate is expired or its name does not match the URL, fix the server certificate. |
| `NET004` | Endpoint returned a non-success HTTP status other than 401/403. A `404` on `GET {base_url}/models` is only a warning, because some OpenAI-compatible servers do not implement `/models`. | Check that `base_url` includes the correct prefix (usually `/v1`) and that the server is healthy. |
| `NET005` | Request timed out. | Check network latency and that the endpoint is not overloaded; the `/models` probe should answer within 10 seconds. |
| `NET006` | Endpoint rejected the configured credentials (HTTP 401/403). | Check the value of the environment variable named by the model's `api_key.env`. |

## Related CFG codes

| Code | Meaning | What to do |
| - | - | - |
| `CFG002` | The environment variable named by a model's `api_key.env` is not set in the agent's environment. Doctor skips that model's network probes. | Export the variable in the environment the agent starts from; see [Models file](/federal/air-gapped/models-file#api-key-environment-variables). |
| `CFG004` | The `DEVIN_CA_BUNDLE` file is missing, unreadable, or contains no valid PEM certificates. | Fix the path or the file contents; the message names the parse error. |


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