Skip to content

Commit 028aa77

Browse files
add workers vpc terraform to docs (#28492)
* add workers vpc terraform to docs * fix: broken link, code block langs, frontmatter, and unused imports * fix: pre-existing style issues (em dash, contraction, vague links, $today in tf block) --------- Co-authored-by: ask-bonk[bot] <ask-bonk[bot]@users.noreply.github.com>
1 parent d7b475e commit 028aa77

3 files changed

Lines changed: 234 additions & 20 deletions

File tree

src/content/docs/workers-vpc/configuration/vpc-services.mdx renamed to src/content/docs/workers-vpc/configuration/vpc-services/index.mdx

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,7 @@ sidebar:
55
order: 1
66
---
77

8-
import {
9-
GlossaryTooltip,
10-
Tabs,
11-
TabItem,
12-
Example,
13-
Render,
14-
WranglerConfig,
15-
} from "~/components";
8+
import { Render, WranglerConfig } from "~/components";
169

1710
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.
1811

@@ -36,7 +29,7 @@ A VPC Service consists of:
3629
- **Tunnel ID**: The Cloudflare Tunnel that provides network connectivity
3730
- **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
3831
- **Ports**: HTTP and/or HTTPS port configuration (optional, defaults to 80/443)
39-
- **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.
32+
- **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.
4033

4134
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.
4235

@@ -69,7 +62,7 @@ If your origin service presents a certificate that is not issued by a publicly t
6962

7063
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](/api/resources/connectivity/subresources/directory/subresources/services/), a type of service within the broader connectivity directory.
7164

72-
```json
65+
```jsonc
7366
{
7467
"type": "http",
7568
"name": "human-readable-name",
@@ -83,15 +76,15 @@ The following is an example of a VPC Service for a service using custom HTTP and
8376
"ipv4": "10.0.0.1",
8477
"ipv6": "fe80::",
8578
"network": {
86-
"tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da"
87-
}
88-
}
79+
"tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da",
80+
},
81+
},
8982
}
9083
```
9184

9285
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`.
9386

94-
```json
87+
```jsonc
9588
{
9689
"type": "http",
9790
"name": "human-readable-name",
@@ -105,9 +98,9 @@ The following is an example of a VPC Service for a service using custom HTTP and
10598
"hostname": "example.com",
10699
"resolver_network": {
107100
"tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da",
108-
"resolver_ips": ["10.0.0.1"] // Optional
109-
}
110-
}
101+
"resolver_ips": ["10.0.0.1"], // Optional
102+
},
103+
},
111104
}
112105
```
113106

@@ -165,6 +158,7 @@ You can have multiple VPC service bindings:
165158

166159
## Next steps
167160

161+
- [Configure VPC Services with Terraform](/workers-vpc/configuration/vpc-services/terraform/) for managing VPC Services as infrastructure
168162
- Set up [Cloudflare Tunnel](/workers-vpc/configuration/tunnel/) for your environment
169163
- Learn about the [Service Binding API](/workers-vpc/api/)
170164
- Refer to [examples](/workers-vpc/examples/) of common use cases
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
---
2+
title: Configure with Terraform
3+
pcx_content_type: how-to
4+
description: Learn how to manage VPC Services using the Cloudflare Terraform provider.
5+
sidebar:
6+
order: 2
7+
---
8+
9+
VPC Services can be managed as infrastructure using the [`cloudflare_connectivity_directory_service`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/connectivity_directory_service) resource in the [Cloudflare Terraform provider](/terraform/).
10+
11+
This maps directly to the [connectivity directory](/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](/workers-vpc/configuration/vpc-services/#vpc-service-configuration) (type, host, ports, tunnel ID) apply regardless of how the service is created.
12+
13+
:::note
14+
Requires Cloudflare Terraform provider v5.13.0 or later.
15+
:::
16+
17+
## VPC Service resource
18+
19+
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.
20+
21+
### Hostname-based configuration
22+
23+
When using a hostname, provide `host.hostname` with a `resolver_network` block. This parallels the hostname-based [JSON configuration example](/workers-vpc/configuration/vpc-services/#configuration-example).
24+
25+
```tf
26+
resource "cloudflare_connectivity_directory_service" "my_private_api" {
27+
account_id = var.account_id
28+
name = "my-private-api"
29+
type = "http"
30+
http_port = 80
31+
https_port = 443
32+
33+
host = {
34+
hostname = "internal-api.example.com"
35+
resolver_network = {
36+
tunnel_id = var.tunnel_id
37+
}
38+
}
39+
}
40+
```
41+
42+
To use a custom DNS resolver within your private network, add `resolver_ips`:
43+
44+
```tf
45+
resource "cloudflare_connectivity_directory_service" "my_private_api" {
46+
account_id = var.account_id
47+
name = "my-private-api"
48+
type = "http"
49+
50+
host = {
51+
hostname = "internal-api.example.com"
52+
resolver_network = {
53+
tunnel_id = var.tunnel_id
54+
resolver_ips = ["10.0.0.53"]
55+
}
56+
}
57+
}
58+
```
59+
60+
### IP-based configuration
61+
62+
When using IP addresses, provide `host.ipv4` and/or `host.ipv6` with a `network` block. This parallels the IP-based [JSON configuration example](/workers-vpc/configuration/vpc-services/#configuration-example).
63+
64+
```tf
65+
resource "cloudflare_connectivity_directory_service" "my_private_api" {
66+
account_id = var.account_id
67+
name = "my-private-api"
68+
type = "http"
69+
http_port = 8080
70+
https_port = 8443
71+
72+
host = {
73+
ipv4 = "10.0.1.50"
74+
ipv6 = "fe80::1"
75+
network = {
76+
tunnel_id = var.tunnel_id
77+
}
78+
}
79+
}
80+
```
81+
82+
### Port configuration
83+
84+
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](/workers-vpc/configuration/vpc-services/#vpc-service-configuration) for how scheme enforcement and port behavior work.
85+
86+
## Workers binding configuration
87+
88+
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](/workers-vpc/configuration/vpc-services/#workers-binding-configuration).
89+
90+
```tf
91+
resource "cloudflare_worker_version" "my_worker_version" {
92+
account_id = var.account_id
93+
worker_id = cloudflare_worker.my_worker.id
94+
compatibility_date = "2025-02-21" # Set this to today's date
95+
main_module = "worker.js"
96+
97+
modules = [{
98+
name = "worker.js"
99+
content_type = "application/javascript+module"
100+
content_file = "build/worker.js"
101+
}]
102+
103+
bindings = [{
104+
type = "vpc_service"
105+
name = "PRIVATE_API"
106+
service_id = cloudflare_connectivity_directory_service.my_private_api.service_id
107+
}]
108+
}
109+
```
110+
111+
Multiple VPC Service bindings can be added to the same Worker:
112+
113+
```tf
114+
bindings = [
115+
{
116+
type = "vpc_service"
117+
name = "PRIVATE_API"
118+
service_id = cloudflare_connectivity_directory_service.api.service_id
119+
},
120+
{
121+
type = "vpc_service"
122+
name = "PRIVATE_DATABASE"
123+
service_id = cloudflare_connectivity_directory_service.database.service_id
124+
}
125+
]
126+
```
127+
128+
The Worker code accesses each binding through `env.PRIVATE_API.fetch()` and `env.PRIVATE_DATABASE.fetch()`, as described in the [Workers Binding API](/workers-vpc/api/).
129+
130+
For more details on managing Workers and bindings with Terraform, refer to [Workers Infrastructure as Code](/workers/platform/infrastructure-as-code/).
131+
132+
## Data sources
133+
134+
The Terraform provider includes data sources for reading existing VPC Services without managing their lifecycle.
135+
136+
### Look up a single VPC Service
137+
138+
```tf
139+
data "cloudflare_connectivity_directory_service" "existing" {
140+
account_id = var.account_id
141+
service_id = "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"
142+
}
143+
```
144+
145+
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).
146+
147+
### List VPC Services
148+
149+
```tf
150+
data "cloudflare_connectivity_directory_services" "all_http" {
151+
account_id = var.account_id
152+
type = "http"
153+
}
154+
```
155+
156+
## Resource schema reference
157+
158+
```tf
159+
resource "cloudflare_connectivity_directory_service" "example" {
160+
# Required
161+
account_id = "your-account-id" # Account identifier
162+
name = "my-private-api" # Human-readable name
163+
type = "http" # Service type (only "http" supported)
164+
165+
# Optional
166+
http_port = 80 # HTTP port (default: 80)
167+
https_port = 443 # HTTPS port (default: 443)
168+
169+
host = {
170+
# Use hostname OR ipv4/ipv6, not both
171+
172+
# Option A: Hostname-based
173+
hostname = "internal-api.example.com"
174+
resolver_network = {
175+
tunnel_id = "tunnel-uuid" # Required — Cloudflare Tunnel ID
176+
resolver_ips = ["10.0.0.53"] # Optional — custom DNS resolver IPs
177+
}
178+
179+
# Option B: IP-based
180+
# ipv4 = "10.0.1.50" # IPv4 address
181+
# ipv6 = "fe80::1" # IPv6 address
182+
# network = {
183+
# tunnel_id = "tunnel-uuid" # Required — Cloudflare Tunnel ID
184+
# }
185+
}
186+
187+
# Read-only (computed by the API)
188+
# id — Terraform resource ID
189+
# service_id — VPC Service ID (use this for Worker bindings)
190+
# created_at — Creation timestamp
191+
# updated_at — Last update timestamp
192+
}
193+
```
194+
195+
For the full schema, refer to the [Terraform registry documentation](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/connectivity_directory_service).

src/content/docs/workers/platform/infrastructure-as-code.mdx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ When using Wrangler for building and a different method for uploading, make sure
3030

3131
## Terraform
3232

33-
In this example, you need a local file named `my-script.mjs` with script content similar to the below examples. Learn more about the Cloudflare Terraform Provider [here](/terraform), and see an example with all the Workers script resource settings [here](https://github.com/cloudflare/terraform-provider-cloudflare/blob/main/examples/resources/cloudflare_workers_script/resource.tf).
33+
In this example, you need a local file named `my-script.mjs` with script content similar to the below examples. Learn more about the [Cloudflare Terraform Provider](/terraform/), and refer to the [Workers script resource example](https://github.com/cloudflare/terraform-provider-cloudflare/blob/main/examples/resources/cloudflare_workers_script/resource.tf) for all available resource settings.
3434

3535
```tf
3636
variable "account_id" {
@@ -48,7 +48,7 @@ resource "cloudflare_worker" "my_worker" {
4848
resource "cloudflare_worker_version" "my_worker_version" {
4949
account_id = var.account_id
5050
worker_id = cloudflare_worker.my_worker.id
51-
compatibility_date = "$today"
51+
compatibility_date = "2025-02-21" # Set this to today's date
5252
main_module = "my-script.mjs"
5353
modules = [
5454
{
@@ -71,7 +71,7 @@ resource "cloudflare_workers_deployment" "my_worker_deployment" {
7171
}
7272
```
7373

74-
Notice how you don't have to manage all of these resources in Terraform. For example, you could just the `cloudflare_worker` resource and seamlessly use Wrangler or your own deployment tools for Versions or Deployments.
74+
Notice how you do not have to manage all of these resources in Terraform. For example, you could use just the `cloudflare_worker` resource and seamlessly use Wrangler or your own deployment tools for Versions or Deployments.
7575

7676
## Bindings in Terraform
7777

@@ -245,6 +245,26 @@ bindings = [{
245245
- `name`: The binding name to access via `env.HYPERDRIVE`
246246
- `id`: The ID of your Hyperdrive configuration
247247

248+
### VPC Service Binding
249+
250+
Bind to a [VPC Service](/workers-vpc/configuration/vpc-services/) for accessing resources in your private network:
251+
252+
```tf
253+
bindings = [{
254+
type = "vpc_service"
255+
name = "PRIVATE_API"
256+
service_id = "your-vpc-service-id"
257+
}]
258+
```
259+
260+
**Properties:**
261+
262+
- `type`: `"vpc_service"`
263+
- `name`: The binding name to access via `env.PRIVATE_API`
264+
- `service_id`: The ID of your VPC Service (from `cloudflare_connectivity_directory_service` or the dashboard)
265+
266+
You can create the VPC Service with Terraform using the `cloudflare_connectivity_directory_service` resource. For a full walkthrough, refer to [Configure VPC Services with Terraform](/workers-vpc/configuration/vpc-services/terraform/).
267+
248268
### Analytics Engine Binding
249269

250270
Bind to an [Analytics Engine](/analytics/analytics-engine/) dataset:
@@ -346,6 +366,11 @@ resource "cloudflare_worker_version" "my_worker_version" {
346366
type = "secret_text"
347367
name = "API_KEY"
348368
text = var.api_key
369+
},
370+
{
371+
type = "vpc_service"
372+
name = "PRIVATE_API"
373+
service_id = var.vpc_service_id
349374
}
350375
]
351376
}

0 commit comments

Comments
 (0)