---
title: Cloudflare Workers VPC
description: Securely connect your private cloud to Cloudflare to build cross-cloud apps.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/index.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Cloudflare Workers VPC

Securely connect your private cloud to Cloudflare to build cross-cloud apps.

 Available on Free and Paid plans 

Workers VPC allows you to connect your Workers to your private APIs and services in external clouds (AWS, Azure, GCP, on-premise, etc.) that are not accessible from the public Internet.

With Workers VPC, you can configure a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) to establish secure, private connections from your private networks to Cloudflare. Then, you can configure a [VPC Service](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/) for each service in the external private network you need to connect to, and use [VPC Service bindings](https://developers.cloudflare.com/workers-vpc/api/) to connect from Workers.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

* [ index.ts ](#tab-panel-6961)
* [ wrangler.jsonc ](#tab-panel-6962)

TypeScript

```

export default {

  async fetch(request, env, ctx) {

    // Access your private API through the service binding

    const response = await env.PRIVATE_API.fetch(

      "http://internal-api.company.local/data",

    );


      // Process the response from your private network

      const data = await response.json();


      return new Response(JSON.stringify(data), {

        headers: { "content-type": "application/json" },

      });

    },


};


```

```

  {

    "$schema": "node_modules/wrangler/config-schema.json",

    "name": "WORKER-NAME",

    "main": "src/index.ts",

    "compatibility_date": "2025-02-04",

    "vpc_services": [

      {

        "binding": "PRIVATE_API",

        "service_id": "ENTER_SERVICE_ID",

        "remote": true

      }

    ]

  }


```

## Use cases

### Access private APIs from Workers applications

Deploy APIs or full-stack applications to Workers that connect to private authentication services, CMS systems, internals APIs, and more. Your Workers applications run globally with optimized access to the backend services of your private network.

### API gateway

Route requests to internal microservices in your private network based on URL paths. Centralize access control and load balancing for multiple private services on Workers.

### Internal tooling, agents, dashboards

Build employee-facing applications and MCP servers that aggregate data from multiple private services. Create unified dashboards, admin panels, and internal tools without exposing backend systems.

## Related products

**[Workers](https://developers.cloudflare.com/workers/)** 

Build serverless applications and deploy instantly across the globe for exceptional performance, reliability, and scale.

**[Hyperdrive](https://developers.cloudflare.com/hyperdrive/)** 

Connect to PostgreSQL and MySQL databases from Workers with connection pooling and caching built-in, available to all Workers plans.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}}]}
```

---

---
title: Get started
description: This guide will walk you through creating your first Workers VPC Service, allowing your Worker to access resources in your private network.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/get-started.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Get started

This guide will walk you through creating your first Workers VPC Service, allowing your Worker to access resources in your private network.

You will create a Workers application, create a Tunnel in your private network to connect it to Cloudflare, and then configure VPC Services for the services on your private network you want to access from Workers.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

## Prerequisites

Before you begin, ensure you have completed the following:

1. Sign up for a [Cloudflare account ↗](https://dash.cloudflare.com/sign-up/workers-and-pages).
2. Install [Node.js ↗](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).

Node.js version manager

Use a Node version manager like [Volta ↗](https://volta.sh/) or [nvm ↗](https://github.com/nvm-sh/nvm) to avoid permission issues and change Node.js versions. [Wrangler](https://developers.cloudflare.com/workers/wrangler/install-and-update/), discussed later in this guide, requires a Node version of `16.17.0` or later.

Additionally, you will need:

* Access to a private network (your local network, AWS VPC, Azure VNet, GCP VPC, or on-premise networks)
* The **Connectivity Directory Bind** role to bind to existing VPC Services from Workers.
* Or, the **Connectivity Directory Admin** role to create VPC Services, and bind to them from Workers.

## 1\. Create a new Worker project

Create a new Worker project using Wrangler:

 npm  yarn  pnpm 

```
npm create cloudflare@latest -- workers-vpc-app
```

```
yarn create cloudflare workers-vpc-app
```

```
pnpm create cloudflare@latest workers-vpc-app
```

For setup, select the following options:

* For _What would you like to start with?_, choose `Hello World example`.
* For _Which template would you like to use?_, choose `Worker only`.
* For _Which language do you want to use?_, choose `TypeScript`.
* For _Do you want to use git for version control?_, choose `Yes`.
* For _Do you want to deploy your application?_, choose `No` (we will be making some changes before deploying).

Navigate to your project directory:

Terminal window

```

cd workers-vpc-app


```

## 2\. Set up Cloudflare Tunnel

A Cloudflare Tunnel creates a secure connection from your private network to Cloudflare. This tunnel will allow Workers to securely access your private resources. You can create the tunnel on a virtual machine or container in your external cloud, or even on your local desktop for the sake of this tutorial.

1. Navigate to the [Workers VPC dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc/tunnels) and select the **Tunnels** tab.
2. Select **Create** to create a new tunnel.
3. Enter a name for your tunnel (for example, `workers-vpc-tunnel`) and select **Save tunnel**.
4. Choose your operating system and architecture. The dashboard will provide specific installation instructions for your environment.
5. Follow the provided commands to download and install `cloudflared`, and execute the service installation command with your unique token.

The dashboard will confirm when your tunnel is successfully connected.

### Configuring your private network for Cloudflare Tunnel

Once your tunnel is connected, you will need to ensure it can access the services that you want your Workers to have access to. The tunnel should be installed on a machine that can reach the internal resources you want to expose to Workers VPC. In external clouds, this may mean configuring Access-Control-Lists, Security Groups, or VPC Firewall Rules to ensure that the tunnel can access the desired services.

Note

This guide provides a quick setup for Workers VPC.

For comprehensive tunnel configuration, monitoring, and management, refer to the [full Cloudflare Tunnel documentation](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/).

## 3\. Create a VPC Service

Now that your tunnel is running, create a VPC Service that Workers can use to access your internal resources:

* [ Dashboard ](#tab-panel-6973)
* [ Wrangler CLI ](#tab-panel-6974)

1. Navigate to the [Workers VPC dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc) and select the **VPC Services** tab.
2. Select **Create** to create a new VPC Service.
3. Enter a **Service name** for your VPC Service (for example, `my-private-api`).
4. Select your tunnel from the **Tunnel** dropdown, or select **Create Tunnel** if you need to create a new one.
5. Enter the **Host or IP address** of your internal service (for example, `localhost`, `internal-api.company.local`, or `10.0.1.50`).
6. Configure **Ports**. Select either:  
   * **Use default ports** for standard HTTP (80) and HTTPS (443)  
   * **Provide port values** to specify custom HTTP and HTTPS ports
7. Configure **DNS Resolver**. Select either:  
   * **Use tunnel as resolver** to use the tunnel's built-in DNS resolution  
   * **Custom resolver** and enter your DNS resolver IP (for example, `8.8.8.8`)
8. Select **Create service** to create your VPC Service.

The dashboard will display your new VPC Service with a unique Service ID. Save this Service ID for the next step.

Terminal window

```

npx wrangler vpc service create my-private-api \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname <YOUR_HOSTNAME>


```

Replace:

* `<YOUR_TUNNEL_ID>` with your tunnel ID from step 2
* `<YOUR_HOSTNAME>` with your internal service hostname (for example, `internal-api.company.local`)

You can also:

* Create services using IP addresses by replacing `--hostname <YOUR_HOSTNAME>` with `--ipv4 <YOUR_IPV4_ADDRESS>` (for example, `--ipv4 10.0.1.50`), `--ipv6 <YOUR_IPV6_ADDRESS>` (for example, `--ipv6 fe80::1`), or both for dual-stack configuration (`--ipv4 10.0.1.50 --ipv6 fe80::1`)
* Specify custom ports by adding `--http-port <PORT>` and/or `--https-port <PORT>` (for example, `--http-port 8080 --https-port 8443`)

The command will return a service ID. Save this for the next step.

If you encounter permission errors, refer to [Required roles](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#required-roles).

## 4\. Configure your Worker

Add the VPC Service binding to your Wrangler configuration file:

* [  wrangler.jsonc ](#tab-panel-6975)
* [  wrangler.toml ](#tab-panel-6976)

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "workers-vpc-app",

  "main": "src/index.ts",

  // Set this to today's date

  "compatibility_date": "2026-04-03",

  "vpc_services": [

    {

      "binding": "VPC_SERVICE",

      "service_id": "<YOUR_SERVICE_ID>"

    }

  ]

}


```

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "workers-vpc-app"

main = "src/index.ts"

# Set this to today's date

compatibility_date = "2026-04-03"


[[vpc_services]]

binding = "VPC_SERVICE"

service_id = "<YOUR_SERVICE_ID>"


```

Replace `<YOUR_SERVICE_ID>` with the service ID from step 3.

## 5\. Write your Worker code

Update your Worker to use the VPC Service binding. The following example:

TypeScript

```

export default {

  async fetch(request, env, ctx): Promise<Response> {

    const url = new URL(request.url);


    // This is a simple proxy scenario.

    // In this case, you will need to replace the URL with the proper protocol (http vs. https), hostname and port of the service.

    // For example, this could be "http://localhost:1111", "http://192.0.0.1:3000", "https://my-internal-api.example.com"

    const targetUrl = new URL(`http://<ENTER_SERVICE_HOST>:<ENTER_SERVICE_PORT>${url.pathname}${url.search}`);


    // Create new request with the target URL but preserve all other properties

    const proxyRequest = new Request(targetUrl, {

      method: request.method,

      headers: request.headers,

      body: request.body,

    });


    const response = await env.VPC_SERVICE.fetch(proxyRequest);


    return response;

  },

} satisfies ExportedHandler<Env>;


```

## 6\. Test locally

Test your Worker locally. You must use remote VPC Services, using either [Workers remote bindings](https://developers.cloudflare.com/workers/development-testing/#remote-bindings) as was configured in your `wrangler.jsonc` configuration file, or using `npx wrangler dev --remote`:

Terminal window

```

npx wrangler dev


```

Visit `http://localhost:8787` to test your Worker's connection to your private network.

## 7\. Deploy your Worker

Once testing is complete, deploy your Worker:

Terminal window

```

npx wrangler deploy


```

Your Worker is now deployed and can access your private network resources securely through the Cloudflare Tunnel. If you encounter permission errors, refer to [Required roles](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#required-roles).

## Next steps

* Explore [configuration options](https://developers.cloudflare.com/workers-vpc/configuration/) for advanced setups
* Set up [high availability tunnels](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/hardware-requirements/) for production
* View [platform-specific guides](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/) for AWS, Azure, GCP, and Kubernetes
* Check out [examples](https://developers.cloudflare.com/workers-vpc/examples/) for common use cases

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/get-started/","name":"Get started"}}]}
```

---

---
title: Workers Binding API
description: VPC Service bindings provide a convenient API for accessing VPC Services from your Worker. Each binding represents a connection to a service in your private network through a Cloudflare Tunnel.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/api/index.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Workers Binding API

VPC Service bindings provide a convenient API for accessing VPC Services from your Worker. Each binding represents a connection to a service in your private network through a Cloudflare Tunnel.

Each request made on the binding will route to the specific service that was configured for the VPC Service, while restricting access to the rest of your private network.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

## VPC Service binding

A VPC Service binding is accessed via the `env` parameter in your Worker's fetch handler. It provides a `fetch()` method for making HTTP requests to your private service.

Required roles

To bind a VPC Service in a Worker, your user needs `Connectivity Directory Bind` (or `Connectivity Directory Admin`). For role definitions, refer to [Roles](https://developers.cloudflare.com/fundamentals/manage-members/roles/#account-scoped-roles).

## fetch()

Makes an HTTP request to the private service through the configured tunnel.

JavaScript

```

const response = await env.VPC_SERVICE_BINDING.fetch(resource, options);


```

Note

The [VPC Service configurations](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#vpc-service-configuration) will always be used to connect and route requests to your services in external networks, even if a different URL or host is present in the actual `fetch()` operation of the Worker code.

The host provided in the `fetch()` operation is not used to route requests, and instead only populates the `Host` field for a HTTP request that can be parsed by the server and used for Server Name Indication (SNI), when the `https` scheme is specified.

The port provided in the `fetch()` operation is ignored — the port specified in the VPC Service configuration will be used.

### Parameters

* `resource` (string | URL | Request) - The URL to fetch. This must be an absolute URL including protocol, host, and path (for example, `http://internal-api/api/users`)
* `options` (optional RequestInit) - Standard fetch options including:  
   * `method` \- HTTP method (GET, POST, PUT, DELETE, etc.)  
   * `headers` \- Request headers  
   * `body` \- Request body  
   * `signal` \- AbortSignal for request cancellation

Absolute URLs Required

VPC Service fetch requests must use absolute URLs including the protocol (`http`/`https`), host, and path. Relative paths are not supported.

### Return value

Returns a `Promise<Response>` that resolves to a [standard Fetch API Response object ↗](https://developer.mozilla.org/en-US/docs/Web/API/Response).

### Examples

#### Basic GET request

JavaScript

```

export default {

  async fetch(request, env) {

    const privateRequest = new Request(

      "http://internal-api.company.local/users",

    );

    const response = await env.VPC_SERVICE_BINDING.fetch(privateRequest);

    const users = await response.json();


    return new Response(JSON.stringify(users), {

      headers: { "Content-Type": "application/json" },

    });

  },

};


```

#### POST request with body

JavaScript

```

export default {

  async fetch(request, env) {

    const privateRequest = new Request(

      "http://internal-api.company.local/users",

      {

        method: "POST",

        headers: {

          "Content-Type": "application/json",

          Authorization: `Bearer ${env.API_TOKEN}`,

        },

        body: JSON.stringify({

          name: "John Doe",

          email: "john@example.com",

        }),

      },

    );


    const response = await env.VPC_SERVICE_BINDING.fetch(privateRequest);


    if (!response.ok) {

      return new Response("Failed to create user", { status: response.status });

    }


    const user = await response.json();

    return new Response(JSON.stringify(user), {

      headers: { "Content-Type": "application/json" },

    });

  },

};


```

#### Request with HTTPS and IP address

JavaScript

```

export default {

  async fetch(request, env) {

    const privateRequest = new Request("https://10.0.1.50/api/data");

    const response = await env.VPC_SERVICE_BINDING.fetch(privateRequest);


    return response;

  },

};


```

## Next steps

* Configure [service bindings in your Wrangler configuration file](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/)
* Refer to [usage examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/api/","name":"Workers Binding API"}}]}
```

---

---
title: Cloudflare Tunnel
description: Cloudflare Tunnel creates secure connections from your infrastructure to Cloudflare's global network, providing the network connectivity that allows Workers to access your private resources.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/configuration/tunnel/index.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Cloudflare Tunnel

Cloudflare Tunnel creates secure connections from your infrastructure to Cloudflare's global network, providing the network connectivity that allows Workers to access your private resources.

When you create a VPC Service, you specify a tunnel ID and target service. Workers VPC then routes requests from your Worker to the specified tunnel, which establishes a connection to the specified hostname or IP address, such that the target service receives the request and returns a response back to your Worker.

To allow members to create VPC Services that represent a target service reachable via a tunnel, you must assign them the **Connectivity Directory Admin** role. Members must possess **Connectivity Directory Bind** role to bind to existing VPC Services from worker.

The tunnel maintains persistent connections to Cloudflare, eliminating the need for inbound firewall rules or public IP addresses.

Note

This section provides tunnel configuration specific to Workers VPC use cases. For comprehensive tunnel documentation including monitoring and advanced configurations, refer to the [full Cloudflare Tunnel documentation](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/).

## Create and run tunnel (`cloudflared`)

Cloudflare Tunnel requires the installation of a lightweight and highly scalable server-side daemon, `cloudflared`, to connect your infrastructure to Cloudflare.

Version and Configuration

Ensure you are running `cloudflared` version 2025.7.0 or later (latest version recommended) to ensure proper DNS resolution and connectivity. Older versions are not supported.

Workers VPC also requires Cloudflare Tunnel to connect using the [QUIC transport protocol](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/run-parameters/#protocol) using `auto` or `quic`. Ensure outbound UDP traffic on port 7844 is allowed through your firewall for QUIC connections.

Cloudflare Tunnels can be created one of two ways:

1. **Remotely-managed tunnels (recommended):** Remotely-managed configurations are stored on Cloudflare, allowing you to manage the tunnel from any machine using the dashboard, API, or Terraform.
2. **Locally-managed tunnels:** A locally-managed tunnel is created by running `cloudflared tunnel create <NAME>` on the command line. Tunnel configuration is stored in your local cloudflared directory.

For Workers VPC, we recommend creating a remotely-managed tunnel through the dashboard. Follow the [Tunnels for Workers VPC dashboard setup guide](https://developers.cloudflare.com/workers-vpc/get-started/) to create your tunnel with provided installation commands shown in the dashboard.

For locally-managed tunnels, refer to the [cloudflared locally-managed tunnels](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/) guide. For manual installation, refer to the [cloudflared downloads page](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/) for platform-specific installation instructions.

Note

Cloudflare Tunnels can either be configured for usage with [Cloudflare Zero Trust](https://developers.cloudflare.com/cloudflare-one/) or [Workers VPC](https://developers.cloudflare.com/workers-vpc/).

Use Tunnels with Zero Trust when you are exposing internal applications securely to your employees with Cloudflare Access and hostnames.

Use Tunnels with Workers VPC when you want to access private APIs, private databases, internal services or other HTTP services within your cloud or on-premise private network from Workers.

The same `cloudflared` instance can be used to cover both Zero Trust and Workers VPC use cases simultaneously.

Note

[Ingress configurations](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/configuration-file/) for locally-managed tunnels are only relevant when using tunnels to expose services to the public internet, and are not required for Workers VPC as routing is handled by the VPC Service configuration.

## Cloud platform setup guides

For platform-specific tunnel deployment instructions for production workloads:

* [AWS](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/aws/) \- Deploy tunnels in Amazon Web Services
* [Azure](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/azure/) \- Deploy tunnels in Microsoft Azure
* [Google Cloud](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/google-cloud-platform/) \- Deploy tunnels in Google Cloud Platform
* [Kubernetes](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/kubernetes/) \- Deploy tunnels in Kubernetes clusters
* [Terraform](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/terraform/) \- Deploy tunnels using Infrastructure as Code

Refer to the full Cloudflare Tunnel documentation on [how to setup Tunnels for high availability and failover with replicas](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-availability/).

Note

We do not recommend using `cloudflared` in autoscaling setups because downscaling (removing replicas) will break existing user connections to that replica. Additionally, `cloudflared` does not load balance across replicas; replicas are strictly for high availability and requests are routed to the nearest replica.

## Next steps

* Configure [VPC Services](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/) to connect your tunnels to Workers
* Review [hardware requirements](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/hardware-requirements/) for capacity planning
* Review the [complete Cloudflare Tunnel documentation](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) for advanced features

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/configuration/tunnel/","name":"Cloudflare Tunnel"}}]}
```

---

---
title: Hardware requirements
description: For production use cases, we recommend the following baseline configuration:
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/configuration/tunnel/hardware-requirements.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Hardware requirements

## Recommendations

For production use cases, we recommend the following baseline configuration:

* Run a cloudflared replica on two dedicated host machines per network location. Using two hosts enables server-side redundancy. See [tunnel availability and replicas](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-availability/) for setup instructions.
* Size each host with minimum 4GB of RAM and 4 CPU cores.

This setup is usually sufficient to handle traffic from small-medium sized applications. The actual amount of resources used by cloudflared will depend on many variables, including the number of requests per second, bandwidth, network path, and hardware. If usage increases beyond your existing tunnel capacity, you can scale your tunnel by increasing the hardware allocated to the cloudflared hosts.

## Capacity calculator

To estimate tunnel capacity requirements for your deployment, refer to the [tunnel capacity calculator in the Zero Trust documentation](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-availability/system-requirements/).

## Scaling considerations

Monitor tunnel performance and scale accordingly:

* **CPU utilization**: Keep below 70% average usage
* **Memory usage**: Maintain headroom for traffic spikes
* **Network bandwidth**: Ensure adequate throughput for peak loads
* **Connection count**: Scale cloudflared vertically when approaching capacity limits

## Next steps

* Configure [tunnel deployment](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/)
* Set up [high availability](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/) with multiple replicas

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/configuration/tunnel/","name":"Cloudflare Tunnel"}},{"@type":"ListItem","position":5,"item":{"@id":"/workers-vpc/configuration/tunnel/hardware-requirements/","name":"Hardware requirements"}}]}
```

---

---
title: VPC Services
description: VPC Services are the core building block of Workers VPC. They represent specific resources in your private network that Workers can access through Cloudflare Tunnel.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/configuration/vpc-services/index.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# VPC Services

VPC Services are the core building block of Workers VPC. They represent specific resources in your private network that Workers can access through Cloudflare Tunnel.

You can use bindings to connect to VPC Services from Workers. Every request made to a VPC Service using its `fetch` function will be securely routed to the configured service in the private network.

VPC Services enforce that requests are routed to their intended service without exposing the entire network, securing your workloads and preventing server-side request forgery (SSRF).

Members must possess **Connectivity Directory Bind** role to bind to existing VPC Services from Workers. Creating VPC Services requires members to possess the **Connectivity Directory Admin** role.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

## VPC Service configuration

A VPC Service consists of:

* **Type**: Currently only `http` is supported (support for `tcp` coming soon)
* **Tunnel ID**: The Cloudflare Tunnel that provides network connectivity
* **Hostname or IPv4/IPv6 addresses**: The hostname, or IPv4 and/or IPv6 addresses to use to route to your service from the tunnel in your private network
* **Ports**: HTTP and/or HTTPS port configuration (optional, defaults to 80/443)
* **Resolver IPs**: Optionally, a specific resolver IP can be provided — when not provided, `cloudflared` will direct DNS traffic to the currently configured default system resolver.

Requests are encrypted in flight until they reach your network via a tunnel, regardless of the scheme used in the URL provided to `fetch`. If the `http` scheme is used, a plaintext connection is established to the service from the tunnel.

The `https` scheme can be used for an encrypted connection within your network, between the tunnel and your service. When the `https` scheme is specified, a hostname provided to the `fetch()` operation is utilized as the Server Name Indication (SNI) value.

VPC Services default to allowing both `http` and `https` schemes to be used. You can provide values for only one of `http_port` or `https_port` to enforce the use of a particular scheme.

When Workers VPC is unable to establish a connection to your service, `fetch()` will throw an exception.

Note

The [VPC Service configuration](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#vpc-service-configuration) host and port(s) will always be used to connect and route requests to your services, even if a different host or port is present in the URL provided to the `fetch()` operation in the Worker code.

The host provided in the `fetch()` operation is not used to route requests, and instead only populates the `Host` field for a HTTP request, or `Host` and the Server Name Indication (SNI) value presented to your service for a HTTPS request.

The port provided in the `fetch()` operation is ignored — the port specified in the VPC Service configuration for the provided scheme will be used.

### Supported TLS certificates

When using the `https` scheme, the tunnel verifies the TLS certificate presented by your origin service. Workers VPC trusts the following certificate types:

* **Publicly trusted certificates** — Certificates issued by well-known public certificate authorities (for example, Let's Encrypt, DigiCert).
* **[Cloudflare Origin CA certificates](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/)** — Free certificates issued by Cloudflare that encrypt traffic between Cloudflare and your origin. Origin CA certificates are not trusted by browsers, but are trusted by Workers VPC when connecting to your private services.

If your origin service presents a certificate that is not issued by a publicly trusted CA or by Cloudflare Origin CA, the TLS handshake will fail and `fetch()` will throw an exception.

## Configuration example

The following is an example of a VPC Service for a service using custom HTTP and HTTPS ports, and both IPv4 and IPv6 addresses. These configurations represent the expected contract of the [REST API for creating a VPC Service](https://developers.cloudflare.com/api/resources/connectivity/subresources/directory/subresources/services/), a type of service within the broader connectivity directory.

```

{

  "type": "http",

  "name": "human-readable-name",


  // Port configuration (optional - defaults to 80/443)

  "http_port": 80,

  "https_port": 443,


  // Host configuration

  "host": {

    "ipv4": "10.0.0.1",

    "ipv6": "fe80::",

    "network": {

      "tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da",

    },

  },

}


```

The following is an example of a VPC Service for a service using custom HTTP and HTTPS ports as well, using a hostname. Note that since we are using a hostname, we must provide our service with a `resolver_network` that optionally has `resolver_ips`.

```

{

  "type": "http",

  "name": "human-readable-name",


  // Port configuration (optional - defaults to 80/443)

  "http_port": 80,

  "https_port": 443,


  // Hostname Host (with DNS resolver)

  "host": {

    "hostname": "example.com",

    "resolver_network": {

      "tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da",

      "resolver_ips": ["10.0.0.1"], // Optional

    },

  },

}


```

## Workers binding configuration

Once you have created a VPC Service, you can bind it to your Worker:

* [  wrangler.jsonc ](#tab-panel-6963)
* [  wrangler.toml ](#tab-panel-6964)

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "my-worker",

  "main": "src/index.js",

  "vpc_services": [

    {

      "binding": "PRIVATE_API",

      "service_id": "e6a0817c-79c5-40ca-9776-a1c019defe70",

      "remote": true // When true, utilizes [remote bindings](/workers/development-testing/#remote-bindings) to allow access to the VPC Service during local development.

    }

  ]

}


```

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "my-worker"

main = "src/index.js"


[[vpc_services]]

binding = "PRIVATE_API"

service_id = "e6a0817c-79c5-40ca-9776-a1c019defe70"

remote = true


```

You can have multiple VPC service bindings:

* [  wrangler.jsonc ](#tab-panel-6965)
* [  wrangler.toml ](#tab-panel-6966)

```

{

  "vpc_services": [

    {

      "binding": "PRIVATE_API",

      "service_id": "daf43e8c-a81a-4242-9912-4a2ebe4fdd79",

      "remote": true

    },

    {

      "binding": "PRIVATE_DATABASE",

      "service_id": "453b6067-1327-420d-89b3-2b6ad16e6551",

      "remote": true

    },

    {

      "binding": "INTERNAL_CACHE",

      "service_id": "6c39b574-237e-49f4-852a-cea5a93ed8f9",

      "remote": true

    }

  ]

}


```

```

[[vpc_services]]

binding = "PRIVATE_API"

service_id = "daf43e8c-a81a-4242-9912-4a2ebe4fdd79"

remote = true


[[vpc_services]]

binding = "PRIVATE_DATABASE"

service_id = "453b6067-1327-420d-89b3-2b6ad16e6551"

remote = true


[[vpc_services]]

binding = "INTERNAL_CACHE"

service_id = "6c39b574-237e-49f4-852a-cea5a93ed8f9"

remote = true


```

## Required roles

Workers VPC uses the following account roles:

* `Connectivity Directory Read` to view Workers VPC Services and Tunnels.
* `Connectivity Directory Bind` to list/read services and bind them in Workers.
* `Connectivity Directory Admin` to create, update, and delete services.

For role definitions, refer to [Roles](https://developers.cloudflare.com/fundamentals/manage-members/roles/#account-scoped-roles).

If your roles were recently updated and commands are still failing, refresh Wrangler authentication:

Terminal window

```

npx wrangler logout

npx wrangler login


```

If you authenticate with an API token (`CLOUDFLARE_API_TOKEN`), ensure the token belongs to a user with the required roles.

## Next steps

* [Configure VPC Services with Terraform](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/terraform/) for managing VPC Services as infrastructure
* Set up [Cloudflare Tunnel](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/) for your environment
* Learn about the [Service Binding API](https://developers.cloudflare.com/workers-vpc/api/)
* Refer to [examples](https://developers.cloudflare.com/workers-vpc/examples/) of common use cases

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/configuration/vpc-services/","name":"VPC Services"}}]}
```

---

---
title: Configure with Terraform
description: Learn how to manage VPC Services using the Cloudflare Terraform provider.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/configuration/vpc-services/terraform.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Configure with Terraform

VPC Services can be managed as infrastructure using the [cloudflare\_connectivity\_directory\_service ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/connectivity%5Fdirectory%5Fservice) resource in the [Cloudflare Terraform provider](https://developers.cloudflare.com/terraform/).

This maps directly to the [connectivity directory](https://developers.cloudflare.com/api/resources/connectivity/subresources/directory/subresources/services/) — the underlying API that the dashboard and Wrangler CLI also use to create and manage VPC Services. The same [VPC Service configuration fields](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#vpc-service-configuration) (type, host, ports, tunnel ID) apply regardless of how the service is created.

Note

Requires Cloudflare Terraform provider v5.13.0 or later.

## VPC Service resource

The `cloudflare_connectivity_directory_service` resource creates a VPC Service in the connectivity directory. Each resource corresponds to one VPC Service entry that a Worker can bind to.

### Hostname-based configuration

When using a hostname, provide `host.hostname` with a `resolver_network` block. This parallels the hostname-based [JSON configuration example](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#configuration-example).

```

resource "cloudflare_connectivity_directory_service" "my_private_api" {

  account_id = var.account_id

  name       = "my-private-api"

  type       = "http"

  http_port  = 80

  https_port = 443


  host = {

    hostname = "internal-api.example.com"

    resolver_network = {

      tunnel_id = var.tunnel_id

    }

  }

}


```

To use a custom DNS resolver within your private network, add `resolver_ips`:

```

resource "cloudflare_connectivity_directory_service" "my_private_api" {

  account_id = var.account_id

  name       = "my-private-api"

  type       = "http"


  host = {

    hostname = "internal-api.example.com"

    resolver_network = {

      tunnel_id    = var.tunnel_id

      resolver_ips = ["10.0.0.53"]

    }

  }

}


```

### IP-based configuration

When using IP addresses, provide `host.ipv4` and/or `host.ipv6` with a `network` block. This parallels the IP-based [JSON configuration example](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#configuration-example).

```

resource "cloudflare_connectivity_directory_service" "my_private_api" {

  account_id = var.account_id

  name       = "my-private-api"

  type       = "http"

  http_port  = 8080

  https_port = 8443


  host = {

    ipv4 = "10.0.1.50"

    ipv6 = "fe80::1"

    network = {

      tunnel_id = var.tunnel_id

    }

  }

}


```

### Port configuration

Ports are optional and default to 80 (HTTP) and 443 (HTTPS). To enforce a single scheme, provide only one of `http_port` or `https_port`. Refer to [VPC Service configuration](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#vpc-service-configuration) for how scheme enforcement and port behavior work.

## Workers binding configuration

Once a VPC Service exists, bind it to a Worker using the `vpc_service` binding type in the `bindings` array of a `cloudflare_worker_version` resource. This is equivalent to the [vpc\_services array in Wrangler configuration](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#workers-binding-configuration).

```

resource "cloudflare_worker_version" "my_worker_version" {

  account_id         = var.account_id

  worker_id          = cloudflare_worker.my_worker.id

  compatibility_date = "2025-02-21" # Set this to today's date

  main_module        = "worker.js"


  modules = [{

    name         = "worker.js"

    content_type = "application/javascript+module"

    content_file = "build/worker.js"

  }]


  bindings = [{

    type       = "vpc_service"

    name       = "PRIVATE_API"

    service_id = cloudflare_connectivity_directory_service.my_private_api.service_id

  }]

}


```

Multiple VPC Service bindings can be added to the same Worker:

```

bindings = [

  {

    type       = "vpc_service"

    name       = "PRIVATE_API"

    service_id = cloudflare_connectivity_directory_service.api.service_id

  },

  {

    type       = "vpc_service"

    name       = "PRIVATE_DATABASE"

    service_id = cloudflare_connectivity_directory_service.database.service_id

  }

]


```

The Worker code accesses each binding through `env.PRIVATE_API.fetch()` and `env.PRIVATE_DATABASE.fetch()`, as described in the [Workers Binding API](https://developers.cloudflare.com/workers-vpc/api/).

For more details on managing Workers and bindings with Terraform, refer to [Workers Infrastructure as Code](https://developers.cloudflare.com/workers/platform/infrastructure-as-code/).

## Data sources

The Terraform provider includes data sources for reading existing VPC Services without managing their lifecycle.

### Look up a single VPC Service

```

data "cloudflare_connectivity_directory_service" "existing" {

  account_id = var.account_id

  service_id = "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"

}


```

This is useful for binding to a VPC Service that is managed outside of your Terraform configuration (for example, created through the dashboard or Wrangler CLI).

### List VPC Services

```

data "cloudflare_connectivity_directory_services" "all_http" {

  account_id = var.account_id

  type       = "http"

}


```

## Resource schema reference

```

resource "cloudflare_connectivity_directory_service" "example" {

  # Required

  account_id = "your-account-id"        # Account identifier

  name       = "my-private-api"         # Human-readable name

  type       = "http"                   # Service type (only "http" supported)


  # Optional

  http_port  = 80                       # HTTP port (default: 80)

  https_port = 443                      # HTTPS port (default: 443)


  host = {

    # Use hostname OR ipv4/ipv6, not both


    # Option A: Hostname-based

    hostname = "internal-api.example.com"

    resolver_network = {

      tunnel_id    = "tunnel-uuid"      # Required — Cloudflare Tunnel ID

      resolver_ips = ["10.0.0.53"]      # Optional — custom DNS resolver IPs

    }


    # Option B: IP-based

    # ipv4 = "10.0.1.50"               # IPv4 address

    # ipv6 = "fe80::1"                 # IPv6 address

    # network = {

    #   tunnel_id = "tunnel-uuid"      # Required — Cloudflare Tunnel ID

    # }

  }


  # Read-only (computed by the API)

  # id         — Terraform resource ID

  # service_id — VPC Service ID (use this for Worker bindings)

  # created_at — Creation timestamp

  # updated_at — Last update timestamp

}


```

For the full schema, refer to the [Terraform registry documentation ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/connectivity%5Fdirectory%5Fservice).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/configuration/vpc-services/","name":"VPC Services"}},{"@type":"ListItem","position":5,"item":{"@id":"/workers-vpc/configuration/vpc-services/terraform/","name":"Configure with Terraform"}}]}
```

---

---
title: Access a private API or website
description: This example demonstrates how to access a private REST API that is not exposed to the public internet. In this guide, we will configure a VPC Service for an internal API, create a Worker that makes requests to that API, and deploy the Worker to validate our changes.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/examples/private-api.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Access a private API or website

**Last reviewed:**  5 months ago 

This example demonstrates how to access a private REST API that is not exposed to the public internet. In this guide, we will configure a VPC Service for an internal API, create a Worker that makes requests to that API, and deploy the Worker to validate our changes.

## Prerequisites

* A virtual machine/EC2 instance running in your VPC/virtual network
* A private API or website running in your VPC/virtual network with security rules allowing access to the virtual machine that will be running `cloudflared`
* Workers account with Workers VPC access

## 1\. Set up Cloudflare Tunnel

A Cloudflare Tunnel creates a secure connection from your private network to Cloudflare. This tunnel will allow Workers to securely access your private resources.

1. Navigate to the [Workers VPC dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc/tunnels) and select the **Tunnels** tab.
2. Select **Create** to create a new tunnel.
3. Enter a name for your tunnel (for example, `private-api-tunnel`) and select **Save tunnel**.
4. Choose your operating system and architecture. The dashboard will provide specific installation instructions for your environment.
5. Follow the provided commands to download and install `cloudflared` on your VM, and execute the service installation command with your unique token.

The dashboard will confirm when your tunnel is successfully connected. Note the tunnel ID for the next step.

## 2\. Create the Workers VPC Service

First, create a Workers VPC Service for your internal API:

Terminal window

```

npx wrangler vpc service create api-service \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --ipv4 10.0.1.50 \

  --http-port 8080


```

You can also create a VPC Service for a service using its hostname:

Terminal window

```

npx wrangler vpc service create api-service \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname internal-hostname.example.com


```

Note the service ID returned for the next step.

## 3\. Configure your Worker

Update your Wrangler configuration file:

* [  wrangler.jsonc ](#tab-panel-6967)
* [  wrangler.toml ](#tab-panel-6968)

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "private-api-gateway",

  "main": "src/index.js",

  // Set this to today's date

  "compatibility_date": "2026-04-03",

  "vpc_services": [

    {

      "binding": "INTERNAL_API",

      "service_id": "<YOUR_SERVICE_ID>",

      "remote": true

    }

  ]

}


```

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "private-api-gateway"

main = "src/index.js"

# Set this to today's date

compatibility_date = "2026-04-03"


[[vpc_services]]

binding = "INTERNAL_API"

service_id = "<YOUR_SERVICE_ID>"

remote = true


```

## 4\. Implement the Worker

In your Workers code, use the VPC Service binding in order to send requests to the service:

index.js

```

export default {

  async fetch(request, env, ctx) {

    try {

      // Fetch data from internal API and process it before returning

      const response = await env.INTERNAL_API.fetch("http://10.0.1.50:8080/api/data");


      // Use the response of the private API to perform more logic in Workers, before returning the final response

      return response;

    } catch (error) {

      return new Response("Service unavailable", { status: 503 });

    }

  },

};


```

This guide demonstrates how you could create a simple proxy in your Workers. However, you could use VPC Services to fetch APIs directly and manipulate the responses to enable you to build more full-stack and backend functionality on Workers.

## 5\. Deploy and test

Now, you can deploy and test your Worker that you have created:

Terminal window

```

npx wrangler deploy


```

Terminal window

```

# Test GET request

curl https://private-api-gateway.workers.dev


```

## Next steps

* Add [authentication and authorization](https://developers.cloudflare.com/workers/examples/auth-with-headers/)
* Implement [rate limiting](https://developers.cloudflare.com/durable-objects/api/)
* Set up [monitoring and alerting](https://developers.cloudflare.com/analytics/analytics-engine/)
* Explore [other examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/examples/","name":"Examples"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/examples/private-api/","name":"Access a private API or website"}}]}
```

---

---
title: Access a private S3 bucket
description: This example demonstrates how to access a private S3 bucket that is not exposed to the public internet. In this guide, we will configure a Workers VPC Service for an internal S3-compatible storage service, create a Worker that makes requests to that bucket, and deploy the Worker to validate our changes.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/examples/private-s3-bucket.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Access a private S3 bucket

**Last reviewed:**  5 months ago 

This example demonstrates how to access a private S3 bucket that is not exposed to the public internet. In this guide, we will configure a Workers VPC Service for an internal S3-compatible storage service, create a Worker that makes requests to that bucket, and deploy the Worker to validate our changes.

## Prerequisites

* A private S3-compatible storage service running in your VPC/virtual network (such as AWS S3 VPC endpoint, MinIO, or similar)
* A virtual machine/EC2 instance running in the same VPC as your S3 VPC endpoint
* Workers account with Workers VPC access

## 1\. Set up Cloudflare Tunnel

A Cloudflare Tunnel creates a secure connection from your private network to Cloudflare. This tunnel will allow Workers to securely access your private resources.

1. Navigate to the [Workers VPC dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc/tunnels) and select the **Tunnels** tab.
2. Select **Create** to create a new tunnel.
3. Enter a name for your tunnel (for example, `s3-tunnel`) and select **Save tunnel**.
4. Choose your operating system and architecture. The dashboard will provide specific installation instructions for your environment.
5. Follow the provided commands to download and install `cloudflared` on your VM, and execute the service installation command with your unique token.

The dashboard will confirm when your tunnel is successfully connected. Note the tunnel ID for the next step.

## 2\. Create the Workers VPC Service

First, create a Workers VPC Service for your internal S3 storage:

Terminal window

```

npx wrangler vpc service create s3-storage \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname s3.us-west-2.amazonaws.com


```

You can also create a Workers VPC Service using an IP address (for example, if using MinIO):

Terminal window

```

npx wrangler vpc service create s3-storage \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --ipv4 10.0.1.60 \

  --http-port 9000


```

Note the service ID returned for the next step.

## 3\. Configure S3 bucket policy

Configure your S3 bucket to allow anonymous access from your VPC endpoint. This works for unencrypted S3 objects:

```

{

  "Version": "2012-10-17",

  "Statement": [

    {

      "Sid": "AllowAnonymousAccessFromVPCE",

      "Effect": "Allow",

      "Principal": "*",

      "Action": ["s3:GetObject", "s3:ListBucket"],

      "Resource": [

        "arn:aws:s3:::your-bucket-name",

        "arn:aws:s3:::your-bucket-name/*"

      ],

      "Condition": {

        "StringEquals": {

          "aws:sourceVpce": "vpce-your-endpoint-id"

        }

      }

    }

  ]

}


```

### Testing S3 access directly

You can test S3 access directly from the VM where your Cloudflare Tunnel is running to verify the bucket policy is working correctly. These commands should work without any AWS credentials:

Terminal window

```

# Test listing bucket contents

curl -i https://s3.us-west-2.amazonaws.com/your-bucket-name/


# Test downloading a specific file

curl -i https://your-bucket-name.s3.us-west-2.amazonaws.com/test-file.txt


```

## 4\. Configure your Worker

Update your Wrangler configuration file:

* [  wrangler.jsonc ](#tab-panel-6969)
* [  wrangler.toml ](#tab-panel-6970)

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "private-s3-gateway",

  "main": "src/index.js",

  // Set this to today's date

  "compatibility_date": "2026-04-03",

  "vpc_services": [

    {

      "binding": "S3_STORAGE",

      "service_id": "<YOUR_SERVICE_ID>"

    }

  ]

}


```

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "private-s3-gateway"

main = "src/index.js"

# Set this to today's date

compatibility_date = "2026-04-03"


[[vpc_services]]

binding = "S3_STORAGE"

service_id = "<YOUR_SERVICE_ID>"


```

## 5\. Implement the Worker

In your Workers code, use the Workers VPC Service binding in order to send requests to the service:

index.js

```

export default {

  async fetch(request, env, ctx) {

    try {

      // Fetch a file from the private S3 bucket via VPC endpoint

      const response = await env.S3_STORAGE.fetch("https://s3.us-west-2.amazonaws.com/my-bucket/data.json");


      // Use the response from S3 to perform more logic in Workers, before returning the final response

      return response;

    } catch (error) {

      return new Response("Storage unavailable", { status: 503 });

    }

  },

};


```

This guide demonstrates how you could access private object storage from your Workers. You could use Workers VPC Services to fetch files directly and manipulate the responses to enable you to build more full-stack and backend functionality on Workers.

## 6\. Deploy and test

Now, you can deploy and test your Worker that you have created:

Terminal window

```

npx wrangler deploy


```

Terminal window

```

# Test GET request

curl https://private-s3-gateway.workers.dev


```

## Next steps

* Add [authentication and authorization](https://developers.cloudflare.com/workers/examples/auth-with-headers/)
* Implement [rate limiting](https://developers.cloudflare.com/durable-objects/api/)
* Set up [monitoring and alerting](https://developers.cloudflare.com/analytics/analytics-engine/)
* Explore [other examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/examples/","name":"Examples"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/examples/private-s3-bucket/","name":"Access a private S3 bucket"}}]}
```

---

---
title: Route to private services from Workers
description: This example shows how to use Workers VPC to create a centralized gateway that routes requests based on URL paths, provides authentication and rate limiting, and load balances across internal services.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/examples/route-across-private-services.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Route to private services from Workers

**Last reviewed:**  5 months ago 

This example shows how to use Workers VPC to create a centralized gateway that routes requests based on URL paths, provides authentication and rate limiting, and load balances across internal services.

## Prerequisites

* Multiple private APIs or services running in your VPC/virtual network (we'll use a user service and orders service)
* Cloudflare Tunnel configured and running (follow the [Get Started guide](https://developers.cloudflare.com/workers-vpc/get-started/#2-set-up-cloudflare-tunnel) to set up or [create a tunnel from the dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc/tunnels))
* Workers account with Workers VPC access

## 1\. Create the VPC Services

First, create services for your internal APIs using hostnames:

Terminal window

```

# Create user service

npx wrangler vpc service create user-service \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname user-api.internal.example.com


# Create orders service

npx wrangler vpc service create order-service \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname orders-api.internal.example.com


```

Note the service IDs returned for the next step.

## 2\. Configure your Worker

Update your Wrangler configuration file:

* [  wrangler.jsonc ](#tab-panel-6971)
* [  wrangler.toml ](#tab-panel-6972)

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "api-gateway",

  "main": "src/index.js",

  // Set this to today's date

  "compatibility_date": "2026-04-03",

  "vpc_services": [

    {

      "binding": "USER_SERVICE",

      "service_id": "<YOUR_USER_SERVICE_ID>"

    },

    {

      "binding": "ORDER_SERVICE",

      "service_id": "<YOUR_ORDER_SERVICE_ID>"

    }

  ]

}


```

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "api-gateway"

main = "src/index.js"

# Set this to today's date

compatibility_date = "2026-04-03"


[[vpc_services]]

binding = "USER_SERVICE"

service_id = "<YOUR_USER_SERVICE_ID>"


[[vpc_services]]

binding = "ORDER_SERVICE"

service_id = "<YOUR_ORDER_SERVICE_ID>"


```

## 3\. Implement the Worker

In your Workers code, use the VPC Service bindings to route requests to the appropriate services:

index.js

```

export default {

  async fetch(request, env, ctx) {

    const url = new URL(request.url);


    // Route to internal services

    if (url.pathname.startsWith('/api/users')) {

      const response = await env.USER_SERVICE.fetch("https://user-api.internal.example.com" + url.pathname);

      return response;

    } else if (url.pathname.startsWith('/api/orders')) {

      const response = await env.ORDER_SERVICE.fetch("https://orders-api.internal.example.com" + url.pathname);

      return response;

    }


    return new Response('Not Found', { status: 404 });

  },

};


```

## 4\. Deploy and test

Now, you can deploy and test your Worker:

Terminal window

```

npx wrangler deploy


```

Terminal window

```

# Test user service requests

curl https://api-gateway.workers.dev/api/users


# Test orders service requests

curl https://api-gateway.workers.dev/api/orders


```

## Next steps

* Add [authentication and authorization](https://developers.cloudflare.com/workers/examples/auth-with-headers/)
* Implement [rate limiting](https://developers.cloudflare.com/durable-objects/api/)
* Set up [monitoring and alerting](https://developers.cloudflare.com/analytics/analytics-engine/)
* Explore [other examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/examples/","name":"Examples"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/examples/route-across-private-services/","name":"Route to private services from Workers"}}]}
```

---

---
title: Limits
description: Standard Workers limits apply for request size, timeout, and subrequests.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/reference/limits.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Limits

## Service limits

| Resource                 | Limit |
| ------------------------ | ----- |
| VPC Services per account | 1000  |

Standard Workers limits apply for request size, timeout, and subrequests.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/reference/limits/","name":"Limits"}}]}
```

---

---
title: Pricing
description: Workers VPC requires a Workers plan. See Workers pricing for current rates.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/reference/pricing.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Pricing

Workers VPC requires a Workers plan. See [Workers pricing](https://developers.cloudflare.com/workers/platform/pricing/) for current rates.

Free during Open Beta

Workers VPC is free during the open beta period. Standard Workers pricing applies for compute time and requests.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/reference/pricing/","name":"Pricing"}}]}
```

---

---
title: Troubleshoot and debug
description: Troubleshoot and debug errors commonly associated with Workers VPC.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/reference/troubleshooting.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Troubleshoot and debug

Troubleshoot and debug errors commonly associated with Workers VPC.

## Connection error codes

When Workers VPC cannot establish a connection to your private service, `fetch()` will throw an exception with an error code describing what went wrong. These error codes are also visible in the **Metrics** tab of your VPC Service in the Cloudflare dashboard.

Errors are grouped into three categories based on the likely cause. These categories match the labels shown in the **Metrics** tab of your VPC Service in the dashboard.

* **Bad Upstream** — Your tunnel or private service is not reachable. Check tunnel health, service availability, and network/TLS configuration.
* **Client** — Your VPC Service configuration or Worker code caused the failure. Check your target hostname and Worker request behavior.
* **Internal** — A Cloudflare infrastructure issue. Contact Cloudflare support if this persists.

### Bad Upstream errors

These errors indicate that Cloudflare attempted to reach your private service but the connection failed. The tunnel may be down, the service may not be listening, or there is a network or TLS issue between Cloudflare and your origin.

| Error code                  | Description                                                                    | Recommended fix                                                                                                                                                                                                                                                         |
| --------------------------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| connection\_refused         | Your private service refused the TCP connection.                               | Verify your service is running and listening on the expected port. Check firewall rules.                                                                                                                                                                                |
| connection\_terminated      | The connection was closed by your service before a response was received.      | Check your service logs for crashes or resource exhaustion.                                                                                                                                                                                                             |
| connection\_timeout         | The connection attempt to your service timed out.                              | Verify your service is reachable from the tunnel. Check for network latency or firewall rules blocking traffic.                                                                                                                                                         |
| connection\_limit\_reached  | The maximum number of concurrent connections to your service has been reached. | Scale your service to handle more connections, or reduce connection concurrency in your Worker.                                                                                                                                                                         |
| destination\_unavailable    | Your service is considered unavailable.                                        | Verify your tunnel is running and your service is healthy.                                                                                                                                                                                                              |
| destination\_not\_found     | No route could be determined for this request.                                 | Check that your VPC Service configuration points to a valid host and that your tunnel is configured to route traffic to it.                                                                                                                                             |
| destination\_ip\_prohibited | The destination IP address is prohibited.                                      | Verify the IP address configured for your VPC Service is correct and not on a restricted list.                                                                                                                                                                          |
| destination\_ip\_unroutable | No network route exists to the destination IP.                                 | Check that the IP address is correct and reachable from within your private network.                                                                                                                                                                                    |
| proxy\_loop\_detected       | The request would be forwarded back to the same proxy, creating a loop.        | Review your VPC Service and tunnel configuration for circular routing.                                                                                                                                                                                                  |
| dns\_error                  | DNS resolution failed (for example, SERVFAIL).                                 | Check that the hostname configured for your VPC Service is resolvable from within your private network. Verify your DNS resolver is working correctly. Refer to [Tunnel errors](#tunnel-errors) for common DNS causes.                                                  |
| dns\_timeout                | DNS resolution timed out.                                                      | Check your DNS resolver is reachable and responding. Consider configuring a custom DNS resolver in your VPC Service settings.                                                                                                                                           |
| tls\_protocol\_error        | A TLS handshake or protocol error occurred when connecting to your service.    | Verify your service's TLS configuration. Ensure the TLS version and cipher suites are compatible.                                                                                                                                                                       |
| tls\_certificate\_error     | Your service's TLS certificate failed verification.                            | Ensure your service presents a valid certificate from a [publicly trusted CA](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) or a [Cloudflare Origin CA certificate](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/). |
| http\_request\_error        | An HTTP request error occurred.                                                | Check your service logs for details on what caused the error response.                                                                                                                                                                                                  |
| http\_upgrade\_failed       | An HTTP upgrade (for example, WebSocket) failed.                               | Verify your service supports the requested protocol upgrade.                                                                                                                                                                                                            |
| http\_request\_denied       | The request was rejected by policy before being forwarded.                     | Review your service's access policies and configuration.                                                                                                                                                                                                                |
| http\_protocol\_error       | An HTTP protocol error occurred when communicating with your service.          | Check that your service is responding with valid HTTP.                                                                                                                                                                                                                  |
| http\_response\_incomplete  | Your service returned an incomplete HTTP response.                             | Check your service for issues that may cause it to close connections mid-response.                                                                                                                                                                                      |

### Client errors

These errors indicate a problem with your VPC Service setup or your Worker's behavior — not with the private service itself.

| Error code                 | Description                                                                    | Recommended fix                                                                                                     |
| -------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| dns\_error (NXDOMAIN)      | The hostname configured for your VPC Service does not exist in DNS.            | Verify the hostname in your VPC Service configuration is correct and that a DNS record exists for it.               |
| connection\_read\_timeout  | The connection was established but no data was received within the time limit. | Check your Worker code for stalled or slow requests. Ensure your Worker is reading the response in a timely manner. |
| connection\_write\_timeout | Data could not be written to the connection (buffers full).                    | Check your Worker code for slow consumption of response data.                                                       |
| rate\_limited              | The connection rate limit to this origin has been exceeded.                    | Reduce the rate of new connections from your Worker to this service.                                                |

Note

The `dns_error` code can appear as either a **Bad Upstream** error or a **Client** error depending on the DNS failure type. An NXDOMAIN response (hostname does not exist) is classified as a Client error because it typically means the VPC Service hostname is misconfigured. All other DNS failures (SERVFAIL, timeouts, and similar) are classified as Bad Upstream errors.

### Internal errors

These errors indicate an issue within Cloudflare's infrastructure that is not caused by your configuration or your origin service.

| Error code             | Description                                             | Recommended fix                                                                                                                   |
| ---------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| proxy\_internal\_error | An internal error occurred within the Cloudflare proxy. | This is not caused by your configuration. If this error persists, contact [Cloudflare support ↗](https://support.cloudflare.com). |

## Tunnel errors

Workers VPC may return errors at runtime when connecting to private services through Cloudflare Tunnel.

| Error Message                   | Details                                                                                                                                                                                                                                                                                                      | Recommended fixes                                                                                                                                                                                                                                                                                                           |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Error: ProxyError: dns\_error   | DNS resolution failed when attempting to connect to your private service through the tunnel.                                                                                                                                                                                                                 | This error may occur if your cloudflared version is outdated. Ensure you are running cloudflared version 2025.7.0 or later (latest version recommended). See [Cloudflare Tunnel update instructions](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/update-cloudflared/). |
| Error: ProxyError: dns\_error   | Cloudflare Tunnel may be configured with http2 protocol (TUNNEL\_TRANSPORT\_PROTOCOL:http2), which works for Cloudflare Zero Trust [(see note)](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/#create-and-run-tunnel-cloudflared) traffic but prevents DNS resolution from Workers VPC. | Workers VPC requires Cloudflare Tunnel to connect using the [QUIC transport protocol](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/run-parameters/#protocol). Ensure outbound UDP traffic on port 7844 is allowed through your firewall.                        |
| Requests not staying within VPC | Worker requests using .fetch() with a public hostname are routing out of the VPC to the hostname configured for the VPC Service.                                                                                                                                                                             | Ensure your Worker code and the VPC Service use the internal VPC hostname for backend services, not a public hostname.                                                                                                                                                                                                      |

## Permission errors

If you cannot view, create, or bind VPC Services and Tunnels in the dashboard or via Wrangler, ensure your user has the required roles.

Workers VPC uses the following account roles:

* `Connectivity Directory Read` to view Workers VPC Services and Tunnels.
* `Connectivity Directory Bind` to list/read services and bind them in Workers.
* `Connectivity Directory Admin` to create, update, and delete services.

For role definitions, refer to [Roles](https://developers.cloudflare.com/fundamentals/manage-members/roles/#account-scoped-roles).

If your roles were recently updated and commands are still failing, refresh Wrangler authentication:

Terminal window

```

npx wrangler logout

npx wrangler login


```

If you authenticate with an API token (`CLOUDFLARE_API_TOKEN`), ensure the token belongs to a user with the required roles.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/reference/troubleshooting/","name":"Troubleshoot and debug"}}]}
```

---

---
title: Wrangler commands
description: The following Wrangler commands allow you to manage Workers VPC services.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/workers-vpc/reference/wrangler-commands.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Wrangler commands

The following [Wrangler commands](https://developers.cloudflare.com/workers/wrangler/) allow you to manage Workers VPC services.

## `vpc service create`

Create a new VPC service

* [  npm ](#tab-panel-6977)
* [  pnpm ](#tab-panel-6978)
* [  yarn ](#tab-panel-6979)

Terminal window

```

npx wrangler vpc service create [NAME]


```

Terminal window

```

pnpm wrangler vpc service create [NAME]


```

Terminal window

```

yarn wrangler vpc service create [NAME]


```

* `[NAME]` ` string ` required  
The name of the VPC service
* `--type` ` string ` required  
The type of the VPC service
* `--tcp-port` ` number `  
TCP port number
* `--app-protocol` ` string `  
Application protocol for the TCP service
* `--http-port` ` number `  
HTTP port (default: 80)
* `--https-port` ` number `  
HTTPS port number (default: 443)
* `--ipv4` ` string `  
IPv4 address for the host \[conflicts with --ipv6\]
* `--ipv6` ` string `  
IPv6 address for the host \[conflicts with --ipv4\]
* `--hostname` ` string `  
Hostname for the host
* `--resolver-ips` ` string `  
Comma-separated list of resolver IPs
* `--tunnel-id` ` string ` required  
UUID of the Cloudflare tunnel
* `--cert-verification-mode` ` string `  
TLS certificate verification mode for the connection to the origin

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources

## `vpc service delete`

Delete a VPC service

* [  npm ](#tab-panel-6980)
* [  pnpm ](#tab-panel-6981)
* [  yarn ](#tab-panel-6982)

Terminal window

```

npx wrangler vpc service delete [SERVICE-ID]


```

Terminal window

```

pnpm wrangler vpc service delete [SERVICE-ID]


```

Terminal window

```

yarn wrangler vpc service delete [SERVICE-ID]


```

* `[SERVICE-ID]` ` string ` required  
The ID of the service to delete

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources

## `vpc service get`

Get a VPC service

* [  npm ](#tab-panel-6983)
* [  pnpm ](#tab-panel-6984)
* [  yarn ](#tab-panel-6985)

Terminal window

```

npx wrangler vpc service get [SERVICE-ID]


```

Terminal window

```

pnpm wrangler vpc service get [SERVICE-ID]


```

Terminal window

```

yarn wrangler vpc service get [SERVICE-ID]


```

* `[SERVICE-ID]` ` string ` required  
The ID of the VPC service

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources

## `vpc service list`

List VPC services

* [  npm ](#tab-panel-6986)
* [  pnpm ](#tab-panel-6987)
* [  yarn ](#tab-panel-6988)

Terminal window

```

npx wrangler vpc service list


```

Terminal window

```

pnpm wrangler vpc service list


```

Terminal window

```

yarn wrangler vpc service list


```

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources

## `vpc service update`

Update a VPC service

* [  npm ](#tab-panel-6989)
* [  pnpm ](#tab-panel-6990)
* [  yarn ](#tab-panel-6991)

Terminal window

```

npx wrangler vpc service update [SERVICE-ID]


```

Terminal window

```

pnpm wrangler vpc service update [SERVICE-ID]


```

Terminal window

```

yarn wrangler vpc service update [SERVICE-ID]


```

* `[SERVICE-ID]` ` string ` required  
The ID of the VPC service to update
* `--name` ` string ` required  
The name of the VPC service
* `--type` ` string ` required  
The type of the VPC service
* `--tcp-port` ` number `  
TCP port number
* `--app-protocol` ` string `  
Application protocol for the TCP service
* `--http-port` ` number `  
HTTP port (default: 80)
* `--https-port` ` number `  
HTTPS port number (default: 443)
* `--ipv4` ` string `  
IPv4 address for the host \[conflicts with --ipv6\]
* `--ipv6` ` string `  
IPv6 address for the host \[conflicts with --ipv4\]
* `--hostname` ` string `  
Hostname for the host
* `--resolver-ips` ` string `  
Comma-separated list of resolver IPs
* `--tunnel-id` ` string ` required  
UUID of the Cloudflare tunnel
* `--cert-verification-mode` ` string `  
TLS certificate verification mode for the connection to the origin

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/reference/wrangler-commands/","name":"Wrangler commands"}}]}
```
