> ## 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.

# Devin Connect

> Devin Connect gives Devin private access to internal systems: deploy a gateway as a policy proxy, reached by an outbound-only tunnel or AWS PrivateLink.

<Note>
  Devin Connect is currently in **early access**. Features and configuration may change. Reach out to your Cognition account team if you are interested in early access.
</Note>

Devin Connect gives Devin sessions access to internal systems (source control, artifact registries, internal APIs) without building a network path per resource. You deploy a lightweight gateway inside your own network, and Devin reaches it over a private connection.

**Current gateway release: v0.0.2**

## What Devin Connect does

Devin Connect has two parts, and they are configured independently.

**A policy proxy inside your network.** The Gateway is an HTTP CONNECT proxy with a default-deny allowlist. It accepts a connection request for `host:port`, checks it against your routes, resolves the name with your own DNS, dials the destination, and relays opaque bytes. Neither the Gateway nor Devin infrastructure terminates or inspects the TLS between the Devin VM and your service, and every connection is audit logged.

**A private path from Devin to that proxy.** Devin has to reach the proxy without either side exposing anything to the public internet. There are two ways to do that, and the proxy behaves identically under both:

* **Reverse tunnel**: the Gateway dials outbound to a Devin-side endpoint over TLS and Devin sends connection requests back down that tunnel. Nothing is opened inbound to your network, and no cloud-provider integration is needed.
* **AWS PrivateLink**: you front the Gateway with a Network Load Balancer and a VPC Endpoint Service, and Cognition consumes it with an Interface VPC Endpoint in your dedicated tenant VPC. Traffic stays on the AWS backbone and Devin dials the Gateway directly over private IPs.

Pick one in the [Connectivity modes](#connectivity-modes) tabs below; everything else on this page applies to both.

Properties that hold in both cases:

* **Dedicated single-tenant VPC.** Your Devin deployment runs in its own VPC (see the [Customer Dedicated Deployment model](/enterprise/deployment/overview#customer-dedicated-deployment-architecture)). Devin VMs send traffic for your routed destinations toward the Gateway via Cognition-configured egress control.
* **Default-deny, enforced twice.** Routes are enforced on the Gateway and on the Devin side, so a config-only change on one side cannot widen access. Routing a destination never widens a session's permissions: the session's [security profile](/product-guides/security-profiles) still has to allow it.
* **Your application TLS is end-to-end.** The Gateway forwards opaque byte streams.
* **DNS stays inside your network.** Route targets are resolved by your resolvers (the Gateway host's system resolver by default, or nameservers you configure).
* **One deployment covers every routed destination.** You add hostnames and IPv4 ranges in Devin settings rather than building per-service plumbing.

### Choosing a connectivity mode

| | Reverse tunnel | AWS PrivateLink |
| - | - | - |
| Inbound exposure | None; the Gateway dials out | None on the internet; the endpoint service is reachable only by Cognition's account |
| Cloud requirements | Any network with egress to `:443` | Gateway must run in AWS, with an NLB and a VPC Endpoint Service |
| Authentication of the connection | Enrollment token issued by Devin | AWS account principal on the endpoint service |
| Traffic path | Public internet (TLS), or your VPN/Transit Gateway attachment | AWS backbone |
| Cross-region | Not applicable | Supported if you enable it on the endpoint service |

## Configure Devin Connect

Configuration happens in the Devin web app in both modes, on the "Devin Connect" page in enterprise settings, available to users with the appropriate admin role. An account can have several gateways, each routing its own group of destinations: at most one reverse-tunnel gateway, plus any number of PrivateLink gateways.

1. Choose "Add gateway", give it a name, and pick a connection: "Tunnel" for the reverse tunnel, or "Direct" for AWS PrivateLink. For "Direct", also enter the interface endpoint's DNS name and port (see the [AWS PrivateLink](#connectivity-modes) tab).
2. On the gateway's card, choose "Add destination" for each destination Devin should reach through it: an exact hostname, or an IPv4 address or CIDR such as `10.20.0.0/16`. Wildcards are not supported. A destination can belong to only one gateway.
3. For a tunnel gateway, choose "Generate token" to enroll it. The enrollment token is shown once, is never stored by Devin, and can be rotated or revoked at any time with "Regenerate token". Direct gateways have no tunnel to authenticate, so this step does not apply.
4. For a tunnel gateway, copy the deployment snippet for your platform (Docker, Kubernetes, AWS ECS, Terraform on ECS or EC2, or a Linux host). The snippet contains a ready-to-run `config.yaml` built from the gateway's destinations, so re-copy it after changing them.

Each tunnel gateway's card also shows whether it is currently connected and when it was last seen.

### Hostname and IPv4 destinations

* **Hostnames** are matched on the name the session connects to, read from the TLS SNI or the HTTP `Host` header. They therefore route TLS and plain HTTP traffic only. The Gateway resolves the name with your DNS.
* **IPv4 addresses and CIDRs** are matched on the destination IP of the connection, so they route any TCP protocol, including SSH and database connections. Devin does not resolve your internal names for these routes: sessions connect by IP address, or you provide name resolution in the environment, for example `/etc/hosts` entries set up in your [blueprint](/onboard-devin/environment/blueprints).

In the Gateway's own `config.yaml`, allow IPv4 destinations with `ipv4` rules; the generated snippet includes them.

## Connectivity modes

<Tabs>
  <Tab title="Reverse tunnel">
    <Frame caption="Outbound-only connectivity from the gateway in your network to your dedicated Devin VPC">
      <img src="https://mintcdn.com/cognitionai/pakAWPD9ouZl-d-T/images/gateway-architecture.svg?fit=max&auto=format&n=pakAWPD9ouZl-d-T&q=85&s=73c8490d5db855c0230952ca725feb0e" alt="Devin Connect reverse tunnel architecture" width="900" height="480" data-path="images/gateway-architecture.svg" />
    </Frame>

    The Gateway dials out N TLS tunnels to your tenant endpoint, `<customer>.gateway.devinenterprise.com:443`. You never open an inbound port. A registered tunnel only carries streams that the Devin side opens toward your Gateway; it is not an inbound path into Devin.

    Enrollment works like this:

    1. Devin issues you an enrollment token for the tunnel gateway from the "Devin Connect" settings page.
    2. You install the token on the Gateway host at the path `tunnel.auth_token_file` points to.
    3. The Gateway dials `<customer>.gateway.devinenterprise.com:443`, verifies the Devin edge's server certificate, and presents the token.
    4. The edge validates the token (constant-time comparison against a stored digest; the raw token is never stored on the Devin side) and registers the tunnel. Devin-side dials for the gateway's destinations then flow through it.

    The tunnel is configured with a `tunnel` stanza and no `listen` address, so the Gateway host exposes no proxy port at all:

    ```yaml theme={null}
    tunnel:
      endpoint: acme.gateway.devinenterprise.com:443
      gateway_id: gw-1
      # Enrollment token, one line; re-read on every connection attempt so it
      # can be rotated without a restart.
      auth_token_file: /etc/devin-gateway/tunnel-token
      # carrier: websocket   # default; use `direct` to disable WebSocket framing.
      # ca_file: corp-ca.pem # only if a corporate TLS-inspection proxy re-signs
      #                      # the edge connection.
      # egress_proxy:        # customer egress HTTP CONNECT proxy, if required.
      #   addr: proxy.corp.example:3128
    ```

    | Field | Description |
    | - | - |
    | `endpoint` | Your tenant endpoint, `<customer>.gateway.devinenterprise.com:443`. |
    | `gateway_id` | Identifier for this Gateway instance, used in logs and metrics. |
    | `auth_token_file` | Path to the one-line enrollment token file. |
    | `carrier` | `websocket` (default) or `direct`. Both run the identical protocol inside the same TLS connection; `websocket` adds HTTP Upgrade framing for egress paths that do not pass raw TLS. |
    | `ca_file` | PEM CA bundle to verify the Devin edge certificate, only needed behind a corporate TLS-inspection proxy that re-signs certificates. |
    | `egress_proxy` | Your egress HTTP CONNECT proxy (`addr`, optional `auth`), if outbound traffic must go through one. |
    | `connection_pool` | `size` (1-16 tunnels, reloadable) and `max_streams_per_connection` (2-2048). |

    Additional checklist items for this mode:

    * Allow egress from the Gateway to `<customer>.gateway.devinenterprise.com:443` and to your allowlisted internal services. No inbound rules are needed.
    * Store the enrollment token in your secret manager and mount it as a file. Never bake it into images, config under version control, or logs; the Gateway never logs it.
    * Optionally provide Cognition your egress CIDR ranges to restrict the public endpoint at the IP level (defense in depth; the enrollment token remains the authentication gate).
  </Tab>

  <Tab title="AWS PrivateLink">
    <Frame caption="Devin reaching the gateway over AWS PrivateLink">
      <img src="https://mintcdn.com/cognitionai/v9tdcDMHoLlrePLV/images/gateway-privatelink-architecture.svg?fit=max&auto=format&n=v9tdcDMHoLlrePLV&q=85&s=8e026d75fd8336033d4a82ab1c4bf3a5" alt="Devin Connect PrivateLink architecture" width="900" height="480" data-path="images/gateway-privatelink-architecture.svg" />
    </Frame>

    The Gateway serves the allowlist proxy on a local HTTP CONNECT listener, and Devin reaches that listener over PrivateLink:

    1. You deploy the Gateway in a private subnet in your AWS VPC with a `listen` address.
    2. You put a Network Load Balancer in front of it targeting the listener port, and create a VPC Endpoint Service from that NLB.
    3. You add Cognition's AWS account as an allowed principal and send Cognition the endpoint service name.
    4. Cognition creates an Interface VPC Endpoint in your dedicated tenant VPC and sends you its DNS name. That sends a connection request to your endpoint service, which you approve (or have auto-accepted, if you enabled that on the service).
    5. On the "Devin Connect" settings page, you add a gateway with the "Direct" connection, enter the interface endpoint's DNS name and the listener port, and add the destinations it should serve. Put the same destinations in the Gateway's `routes`.

    Because the endpoint service is only consumable by Cognition's account and the NLB is internal to your VPC, there is no public listener. Access is authorized by the AWS principal on the endpoint service and by the Gateway's own default-deny allowlist.

    The Gateway configuration sets `listen` to the port the NLB targets:

    ```yaml theme={null}
    schema_version: 1
    admin_listen: 0.0.0.0:9090

    # The local HTTP CONNECT listener the NLB targets.
    listen: 0.0.0.0:8443

    routes:
      - name: devin
        rules:
          - hostname: "git.corp.example"
          - hostname: "api.corp.example"
        ports: [443]
    ```

    What to provide Cognition:

    * The VPC Endpoint Service name, for example `com.amazonaws.vpce.us-west-2.vpce-svc-0abc123`.
    * The listener port the NLB exposes.
    * Confirmation that Cognition's AWS account is an allowed principal.
    * Whether the endpoint service supports the region your Devin tenant runs in, if it differs from the Gateway's region.

    Additional checklist items for this mode:

    * Run the NLB targets in multiple Availability Zones.
    * If your services are in another region than your Devin tenant, enable cross-region support on the endpoint service. The steps are the same as in [Dedicated Deployment Private Networking](/enterprise/deployment/dedicated_saas_private_networking#cross-region-privatelink-if-your-services-are-in-a-different-region).
  </Tab>
</Tabs>

## Configuration reference

The Gateway is configured with a single YAML file, strictly validated and fail-closed: a config that fails validation is rejected as a whole and the previous config stays active. The file is polled every 5 seconds and hot-reloaded.

```yaml theme={null}
schema_version: 1

# Admin listener (/healthz, /readyz, /metrics).
admin_listen: 127.0.0.1:9090

# Data-plane listener. PrivateLink (direct) mode only: required without a
# `tunnel` stanza, rejected with one.
# listen: 0.0.0.0:8443

# Customer DNS for resolving route targets (system resolver if omitted).
dns:
  nameservers: ["10.0.0.2:53"]
  timeout: 5s

# Default-deny allowlist. Rules accept hostnames and ipv4/ipv6 CIDRs.
# Omitted ports means any port.
routes:
  - name: scm
    rules:
      - hostname: "git.corp.example"
      - hostname: "artifacts.corp.example"
    ports: [443]
  - name: internal-api
    rules:
      - hostname: "api.corp.example"
    ports: [443]
  - name: build-hosts
    rules:
      - ipv4: "10.20.0.0/16"
    ports: [22]

# Outbound tunnel to the Devin-side edge. Omit in PrivateLink mode.
tunnel:
  endpoint: acme.gateway.devinenterprise.com:443
  gateway_id: gw-1
  auth_token_file: /etc/devin-gateway/tunnel-token
```

### Routes (allowlist)

Anything not matched by a route is denied; an empty route list denies everything. Routes are evaluated in order and the first match wins.

| Field | Description |
| - | - |
| `name` | Unique route name; appears in connection audit logs. |
| `rules` | Destination match rules; the route matches if any rule matches. `hostname` matching is case-insensitive. `ipv4`/`ipv6` CIDR rules match literal-IP dials only. |
| `ports` | Allowed destination ports. Omitted means any port. |
| `upstream_proxy` | Optional upstream HTTP CONNECT proxy to chain through for this route (`addr`, optional `auth`). |

Hostnames are matched as requested, before DNS resolution, so policy applies to the name rather than whatever IP it happens to resolve to.

### Listeners

| Field | Description |
| - | - |
| `admin_listen` | Admin listener for `/healthz`, `/readyz`, and `/metrics`. |
| `listen` | Data-plane HTTP CONNECT listener. Set it in PrivateLink mode; omit it in tunnel mode, where connection requests arrive only over the authenticated tunnel. |
| `dial_timeout` | Timeout for dialing upstream targets (default 10s). |

### DNS

| Field | Description |
| - | - |
| `nameservers` | DNS servers (`ip:port`) used to resolve route targets. Omitted means the system resolver of the Gateway host, which is the common case since the Gateway runs inside your network. |
| `timeout` | Per-query timeout (default 5s). |

Hostname routes are refused if your DNS resolves them to loopback, link-local, or unspecified addresses, so an allowlisted name cannot be steered at the Gateway host itself or a metadata endpoint.

## Running the Gateway

The Gateway ships as a container image containing a single static binary (the image is built `FROM scratch` and runs as a non-root user). Mount the config at `/etc/devin-gateway/config.yaml`, and in tunnel mode the token file wherever `tunnel.auth_token_file` points.

```bash theme={null}
gateway serve --config /etc/devin-gateway/config.yaml
gateway validate-config --config config.yaml   # strict config validation
gateway doctor --config config.yaml            # JSON diagnostic summary
```

Operational endpoints on `admin_listen`:

* `/healthz` for process liveness.
* `/readyz` for readiness.
* `/metrics` for Prometheus metrics.

Deployment checklist for both modes:

* Run the Gateway in a private subnet.
* Wire `/healthz` and `/readyz` into your orchestrator's health checks.
* Keep each gateway's destinations in Devin settings and the routes in its Gateway config in sync; a destination allowed on only one side is not reachable.

## Logging and SIEM integration

The Gateway logs to stdout. When stdout is not a terminal (the normal case in a container) logs are emitted as JSON lines, ready for machine consumption. To get them into your SIEM, use your platform's standard log pipeline: the container log driver or agent (CloudWatch Logs, Fluent Bit, Vector, Datadog agent, and so on) collects stdout and forwards it like any other workload's logs. The Gateway needs no SIEM-specific configuration.

Connection audit events include:

* `conn_open` and `conn_close`, with destination host and port, matched route name, client address, bytes transferred in each direction, and duration.
* `deny`, with the destination and reason (for example, no matching allowlist route).

The enrollment token is never logged, and payload contents are never logged.

For per-service private connectivity without a Gateway, see [Dedicated Deployment Private Networking](/enterprise/deployment/dedicated_saas_private_networking). For an overview of deployment models, see the [Deployment overview](/enterprise/deployment/overview).


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