diff --git a/src/content/docs/hyperdrive/configuration/connect-to-private-database-vpc.mdx b/src/content/docs/hyperdrive/configuration/connect-to-private-database-vpc.mdx new file mode 100644 index 000000000000000..bf37b42537b0310 --- /dev/null +++ b/src/content/docs/hyperdrive/configuration/connect-to-private-database-vpc.mdx @@ -0,0 +1,203 @@ +--- +pcx_content_type: how-to +title: Connect to a private database using Workers VPC +sidebar: + order: 5 + badge: + text: Beta +--- + +import { Render, Tabs, TabItem, Steps } from "~/components"; + +[Workers VPC](/workers-vpc/) provides a way to connect Hyperdrive to a private database without configuring Cloudflare Access applications or service tokens. Instead, you create a TCP [VPC Service](/workers-vpc/configuration/vpc-services/) that points to your database and pass its service ID to Hyperdrive. + +For the Tunnel and Access approach, refer to [Connect to a private database using Tunnel](/hyperdrive/configuration/connect-to-private-database/). + + + +## Prerequisites + +- A database in your private network, [configured to use TLS/SSL](/hyperdrive/examples/connect-to-postgres/#supported-tls-ssl-modes). +- A [Cloudflare Tunnel](/workers-vpc/configuration/tunnel/) running in a network that can reach your database. +- The **Connectivity Directory Admin** role on your Cloudflare account to create VPC Services. + +## 1. Set up a Cloudflare Tunnel + +If you do not already have a tunnel running in the same network as your database, create one. + + + +1. Go 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 tunnel. + +3. Enter a name for your tunnel and select **Save tunnel**. + +4. Choose your operating system and architecture. The dashboard will provide installation instructions. + +5. Follow the provided commands to download, install, and run `cloudflared` with your unique token. + + + +The dashboard will confirm when the tunnel is connected. The tunnel must be able to reach your database host and port from within the private network. + +For full tunnel documentation, refer to [Cloudflare Tunnel for Workers VPC](/workers-vpc/configuration/tunnel/). + +## 2. Create a TCP VPC Service + +Create a VPC Service of type `tcp` that points to your database. Set the `--app-protocol` flag to `postgresql` or `mysql` so that Hyperdrive can optimize connections. + + + + +```sh +npx wrangler vpc service create my-postgres-db \ + --type tcp \ + --tcp-port 5432 \ + --app-protocol postgresql \ + --tunnel-id \ + --ipv4 +``` + + + + +```sh +npx wrangler vpc service create my-mysql-db \ + --type tcp \ + --tcp-port 3306 \ + --app-protocol mysql \ + --tunnel-id \ + --ipv4 +``` + + + + +Replace: + +- `` with the tunnel ID from step 1. +- `` with the private IP address of your database (for example, `10.0.0.5`). You can also use `--hostname` with a DNS name instead of `--ipv4`. + +The command will return a service ID. Save this value for the next step. + +You can also create a TCP VPC Service from the [Workers VPC dashboard](https://dash.cloudflare.com/?to=/:account/workers/vpc). Refer to [VPC Services](/workers-vpc/configuration/vpc-services/) for all configuration options. + +### TLS certificate verification + +Unlike Hyperdrive, which does not verify the origin server certificate by default, Workers VPC defaults to `verify_full` — it verifies both the certificate chain and the hostname. If your database uses a self-signed certificate or a certificate from a private certificate authority (CA), the TLS handshake will fail unless you adjust the verification mode. + +For databases with self-signed certificates, add `--cert-verification-mode` when creating the VPC Service: + +- `verify_ca` — Verifies the certificate chain but skips hostname verification. Use this when your database has a certificate signed by a CA you control but the hostname does not match the certificate. +- `disabled` — Skips certificate verification entirely. Use this only for development or testing. + +For example, to create a VPC Service for a PostgreSQL database with a self-signed certificate: + +```sh +npx wrangler vpc service create my-postgres-db \ + --type tcp \ + --tcp-port 5432 \ + --app-protocol postgresql \ + --tunnel-id \ + --ipv4 \ + --cert-verification-mode verify_ca +``` + +To update an existing VPC Service, use `wrangler vpc service update` with the same flag. + +:::note +Workers VPC trusts publicly trusted certificates and [Cloudflare Origin CA certificates](/ssl/origin-configuration/origin-ca/). Uploading a custom CA certificate to Workers VPC is not supported yet. If your database uses a certificate signed by a private CA, set `--cert-verification-mode` to `verify_ca` or `disabled` until custom CA support is available. +::: + +For the full list of verification modes, refer to [TLS certificate verification mode](/workers-vpc/configuration/vpc-services/#tls-certificate-verification-mode). + +## 3. Create a Hyperdrive configuration + +Use the `--service-id` flag to point Hyperdrive at the VPC Service you created. When you use `--service-id`, you do not provide `--origin-host`, `--origin-port`, or `--connection-string`. Hyperdrive routes traffic through the VPC Service instead. + + + + +```sh +npx wrangler hyperdrive create \ + --service-id \ + --database \ + --user \ + --password \ + --scheme postgresql +``` + + + + +```sh +npx wrangler hyperdrive create \ + --service-id \ + --database \ + --user \ + --password \ + --scheme mysql +``` + + + + +Replace: + +- `` with the service ID from step 2. +- `` with the name of your database. +- `` and `` with your database credentials. + +If successful, the command will output a Hyperdrive configuration with an `id` field. Copy this ID for the next step. + +:::note +The `--service-id` flag conflicts with `--origin-host`, `--origin-port`, `--connection-string`, `--access-client-id`, and `--access-client-secret`. You cannot combine these options. To update an existing Hyperdrive configuration to use a VPC Service, run `wrangler hyperdrive update` with the `--service-id` flag. +::: + +## 4. Bind Hyperdrive to a Worker + + + +## 5. Query the database + + + + +Use [node-postgres](https://node-postgres.com/) (`pg`) to send a test query. + + + +Deploy your Worker: + +```sh +npx wrangler deploy +``` + +If you receive a list of `pg_tables` from your database when you access your deployed Worker, Hyperdrive is connected to your private database through Workers VPC. + + + + +Use [mysql2](https://github.com/sidorares/node-mysql2) to send a test query. + + + +Deploy your Worker: + +```sh +npx wrangler deploy +``` + +If you receive a list of tables from your database when you access your deployed Worker, Hyperdrive is connected to your private database through Workers VPC. + + + + +## Next steps + +- Learn more about [how Hyperdrive works](/hyperdrive/concepts/how-hyperdrive-works/). +- Configure [query caching](/hyperdrive/concepts/query-caching/) for Hyperdrive. +- Review [VPC Service configuration options](/workers-vpc/configuration/vpc-services/) including TLS certificate verification. +- Set up [high availability tunnels](/workers-vpc/configuration/tunnel/hardware-requirements/) for production workloads. +- [Troubleshoot common issues](/hyperdrive/observability/troubleshooting/) when connecting a database to Hyperdrive. diff --git a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx index 517674505f4e77a..8c79168e3c84444 100644 --- a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx +++ b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx @@ -11,6 +11,10 @@ import { TabItem, Tabs, Render, Steps, Details } from "~/components"; Hyperdrive can securely connect to your private databases using [Cloudflare Tunnel](/cloudflare-one/networks/connectors/cloudflare-tunnel/) and [Cloudflare Access](/cloudflare-one/access-controls/policies/). +:::note +You can also connect Hyperdrive to a private database using [Workers VPC](/hyperdrive/configuration/connect-to-private-database-vpc/), which does not require configuring Access applications or service tokens. +::: + ## How it works When your database is isolated within a private network (such as a [virtual private cloud](https://www.cloudflare.com/learning/cloud/what-is-a-virtual-private-cloud) or an on-premise network), you must enable a secure connection from your network to Cloudflare. diff --git a/src/content/docs/hyperdrive/get-started.mdx b/src/content/docs/hyperdrive/get-started.mdx index 0788b033ff4f8a8..170773e82ee42ab 100644 --- a/src/content/docs/hyperdrive/get-started.mdx +++ b/src/content/docs/hyperdrive/get-started.mdx @@ -33,7 +33,7 @@ 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) if you have not already. 2. Install [`Node.js`](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). Use a Node version manager like [nvm](https://github.com/nvm-sh/nvm) or [Volta](https://volta.sh/) to avoid permission issues and change Node.js versions. [Wrangler](/workers/wrangler/install-and-update/) requires a Node version of `16.17.0` or later. -3. Have a publicly accessible PostgreSQL or MySQL (or compatible) database. _If your database is in a private network (like a VPC)_, refer to [Connect to a private database](/hyperdrive/configuration/connect-to-private-database/) for instructions on using Cloudflare Tunnel with Hyperdrive. +3. Have a publicly accessible PostgreSQL or MySQL (or compatible) database. _If your database is in a private network_, refer to [Connect to a private database using Workers VPC](/hyperdrive/configuration/connect-to-private-database-vpc/) or [Connect to a private database using Tunnel](/hyperdrive/configuration/connect-to-private-database/). ## 1. Log in @@ -280,17 +280,16 @@ Populate your `index.ts` file with the following code: ```typescript // mysql2 v3.13.0 or later is required -import { createConnection } from 'mysql2/promise'; +import { createConnection } from "mysql2/promise"; export interface Env { - // If you set another name in the Wrangler config file as the value for 'binding', - // replace "HYPERDRIVE" with the variable name you defined. - HYPERDRIVE: Hyperdrive; + // If you set another name in the Wrangler config file as the value for 'binding', + // replace "HYPERDRIVE" with the variable name you defined. + HYPERDRIVE: Hyperdrive; } export default { - async fetch(request, env, ctx): Promise { - + async fetch(request, env, ctx): Promise { // Create a new connection on each request. Hyperdrive maintains the underlying // database connection pool, so creating a new connection is fast. const connection = await createConnection({ @@ -303,34 +302,29 @@ export default { // The following line is needed for mysql2 compatibility with Workers // mysql2 uses eval() to optimize result parsing for rows with > 100 columns // Configure mysql2 to use static parsing instead of eval() parsing with disableEval - disableEval: true + disableEval: true, }); - try{ + try { // Sample query - const [results, fields] = await connection.query( - 'SHOW tables;' - ); + const [results, fields] = await connection.query("SHOW tables;"); // Return result rows as JSON return new Response(JSON.stringify({ results, fields }), { headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': '*', + "Content-Type": "application/json", + "Access-Control-Allow-Origin": "*", }, }); - } - catch(e){ + } catch (e) { console.error(e); return Response.json( { error: e instanceof Error ? e.message : e }, { status: 500 }, ); } - - }, + }, } satisfies ExportedHandler; - ``` Upon receiving a request, the code above does the following: diff --git a/src/content/docs/workers-vpc/configuration/vpc-services/index.mdx b/src/content/docs/workers-vpc/configuration/vpc-services/index.mdx index 8633fee384d1461..51fba7861b6a17a 100644 --- a/src/content/docs/workers-vpc/configuration/vpc-services/index.mdx +++ b/src/content/docs/workers-vpc/configuration/vpc-services/index.mdx @@ -25,12 +25,18 @@ Workers VPC is currently in beta. Features and APIs may change before general av A VPC Service consists of: -- **Type**: Currently only `http` is supported (support for `tcp` coming soon) +- **Type**: `http` for HTTP/HTTPS services, or `tcp` for TCP services (for example, PostgreSQL, MySQL) - **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) +- **Ports**: For `http` type, HTTP and/or HTTPS port configuration (optional, defaults to 80/443). For `tcp` type, a TCP port (required). +- **Application protocol** (TCP only): Optionally, specify `postgresql` or `mysql` to indicate the application-layer protocol for the TCP service +- **TLS certificate verification mode**: Optionally, configure how the connection to the origin verifies TLS certificates - **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. +### HTTP services + +HTTP VPC Services allow Workers to make `fetch()` requests to private HTTP/HTTPS endpoints. + 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. @@ -39,6 +45,14 @@ VPC Services default to allowing both `http` and `https` schemes to be used. You When Workers VPC is unable to establish a connection to your service, `fetch()` will throw an exception. +### TCP services + +TCP VPC Services allow connections to TCP-based services such as PostgreSQL and MySQL databases. Use the `tcp` service type with a `--tcp-port` to expose a TCP service. + +You can optionally specify an `--app-protocol` of `postgresql` or `mysql` to indicate the application-layer protocol. This metadata is used by other Cloudflare products, such as [Hyperdrive](/hyperdrive/), to locate TCP services using a supported wire protocol. + +TCP VPC Services are used with [Hyperdrive](/hyperdrive/) to connect Workers to private databases. Refer to [Connect to a private database using Workers VPC](/hyperdrive/configuration/connect-to-private-database-vpc/) for a complete guide. + :::note The [VPC Service configuration](/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. @@ -58,9 +72,23 @@ When using the `https` scheme, the tunnel verifies the TLS certificate presented 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 +### TLS certificate verification mode + +You can configure how the connection to your origin service verifies TLS certificates by setting the `--cert-verification-mode` option when creating or updating a VPC Service. This applies to both HTTP and TCP service types. + +| Mode | Description | +| ------------- | ------------------------------------------------------------- | +| `verify_full` | Verify the full certificate chain and hostname (default) | +| `verify_ca` | Verify the certificate chain only, skip hostname verification | +| `disabled` | Do not verify the server certificate | + +## Configuration examples + +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. -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. +### HTTP service with IP addresses + +The following is an example of an HTTP VPC Service using custom HTTP and HTTPS ports, and both IPv4 and IPv6 addresses. ```jsonc { @@ -82,7 +110,9 @@ The following is an example of a VPC Service for a service using custom HTTP and } ``` -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`. +### HTTP service with hostname + +The following is an example of an HTTP VPC Service using a hostname. When using a hostname, provide a `resolver_network` that optionally includes `resolver_ips`. ```jsonc { @@ -104,6 +134,50 @@ The following is an example of a VPC Service for a service using custom HTTP and } ``` +### TCP service (for example, PostgreSQL) + +The following is an example of a TCP VPC Service for a PostgreSQL database. + +```jsonc +{ + "type": "tcp", + "name": "my-postgres-db", + "tcp_port": 5432, + "app_protocol": "postgresql", // Optional: "postgresql" or "mysql" + + "host": { + "ipv4": "10.0.0.5", + "network": { + "tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da", + }, + }, +} +``` + +### Service with TLS certificate verification + +The following example creates a TCP service with `verify_ca` certificate verification mode. + +```jsonc +{ + "type": "tcp", + "name": "my-postgres-db", + "tcp_port": 5432, + "app_protocol": "postgresql", + + "host": { + "ipv4": "10.0.0.5", + "network": { + "tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da", + }, + }, + + "tls_settings": { + "cert_verification_mode": "verify_ca", + }, +} +``` + ## Workers binding configuration Once you have created a VPC Service, you can bind it to your Worker: diff --git a/src/content/docs/workers-vpc/configuration/vpc-services/terraform.mdx b/src/content/docs/workers-vpc/configuration/vpc-services/terraform.mdx index e99014102681962..43183707c4faf93 100644 --- a/src/content/docs/workers-vpc/configuration/vpc-services/terraform.mdx +++ b/src/content/docs/workers-vpc/configuration/vpc-services/terraform.mdx @@ -20,7 +20,7 @@ The `cloudflare_connectivity_directory_service` resource creates a VPC Service i ### Hostname-based configuration -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). +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-examples). ```tf resource "cloudflare_connectivity_directory_service" "my_private_api" { @@ -59,7 +59,7 @@ resource "cloudflare_connectivity_directory_service" "my_private_api" { ### 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](/workers-vpc/configuration/vpc-services/#configuration-example). +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-examples). ```tf resource "cloudflare_connectivity_directory_service" "my_private_api" { @@ -79,9 +79,59 @@ resource "cloudflare_connectivity_directory_service" "my_private_api" { } ``` +### TCP service configuration + +For TCP services (for example, databases), set `type = "tcp"` and provide a `tcp_port`. You can optionally specify an `app_protocol` of `postgresql` or `mysql`. + +```tf +resource "cloudflare_connectivity_directory_service" "my_database" { + account_id = var.account_id + name = "my-postgres-db" + type = "tcp" + tcp_port = 5432 + app_protocol = "postgresql" + + host = { + ipv4 = "10.0.0.5" + network = { + tunnel_id = var.tunnel_id + } + } +} +``` + +### TLS certificate verification + +To configure the TLS certificate verification mode for the connection to the origin, add a `tls_settings` block: + +```tf +resource "cloudflare_connectivity_directory_service" "my_database" { + account_id = var.account_id + name = "my-postgres-db" + type = "tcp" + tcp_port = 5432 + app_protocol = "postgresql" + + host = { + ipv4 = "10.0.0.5" + network = { + tunnel_id = var.tunnel_id + } + } + + tls_settings = { + cert_verification_mode = "verify_ca" + } +} +``` + +Valid values for `cert_verification_mode` are `verify_full` (default), `verify_ca`, and `disabled`. Refer to [TLS certificate verification mode](/workers-vpc/configuration/vpc-services/#tls-certificate-verification-mode) for details. + ### 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](/workers-vpc/configuration/vpc-services/#vpc-service-configuration) for how scheme enforcement and port behavior work. +For HTTP services, 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. + +For TCP services, `tcp_port` is required. ## Workers binding configuration @@ -151,6 +201,11 @@ data "cloudflare_connectivity_directory_services" "all_http" { account_id = var.account_id type = "http" } + +data "cloudflare_connectivity_directory_services" "all_tcp" { + account_id = var.account_id + type = "tcp" +} ``` ## Resource schema reference @@ -160,11 +215,15 @@ 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) + type = "http" # Service type: "http" or "tcp" - # Optional - http_port = 80 # HTTP port (default: 80) - https_port = 443 # HTTPS port (default: 443) + # HTTP-specific (optional, defaults to 80/443) + http_port = 80 # HTTP port + https_port = 443 # HTTPS port + + # TCP-specific (tcp_port is required when type = "tcp") + # tcp_port = 5432 # TCP port + # app_protocol = "postgresql" # Optional: "postgresql" or "mysql" host = { # Use hostname OR ipv4/ipv6, not both @@ -184,6 +243,11 @@ resource "cloudflare_connectivity_directory_service" "example" { # } } + # Optional TLS settings + # tls_settings = { + # cert_verification_mode = "verify_full" # "verify_full", "verify_ca", or "disabled" + # } + # Read-only (computed by the API) # id — Terraform resource ID # service_id — VPC Service ID (use this for Worker bindings) diff --git a/src/content/docs/workers-vpc/examples/private-database.mdx b/src/content/docs/workers-vpc/examples/private-database.mdx new file mode 100644 index 000000000000000..d348d9c3930b40a --- /dev/null +++ b/src/content/docs/workers-vpc/examples/private-database.mdx @@ -0,0 +1,133 @@ +--- +title: Connect to a private database +pcx_content_type: example +--- + +import { WranglerConfig } from "~/components"; + +This example demonstrates how to query a private PostgreSQL database from a Worker using [Workers VPC](/workers-vpc/) and [Hyperdrive](/hyperdrive/). The Worker connects to a database that is not exposed to the public Internet, with Hyperdrive providing connection pooling and query acceleration. + +## Prerequisites + +- A PostgreSQL database running in your private network (for example, on port 5432) +- A [Cloudflare Tunnel](/workers-vpc/configuration/tunnel/) connected to the private network where your database runs +- A Cloudflare account with Workers VPC access + +## 1. Create a TCP VPC Service + +Create a [VPC Service](/workers-vpc/configuration/vpc-services/) of type `tcp` that points to your PostgreSQL database. The `--app-protocol postgresql` flag allows Hyperdrive to optimize connections. + +```sh +npx wrangler vpc service create my-postgres-db \ + --type tcp \ + --tcp-port 5432 \ + --app-protocol postgresql \ + --tunnel-id \ + --ipv4 +``` + +Replace `` with the ID of the tunnel connected to your database network. Replace `` with the private IP address of your database (for example, `10.0.1.50`). + +Note the service ID returned for the next step. + +## 2. Create a Hyperdrive configuration + +Use `wrangler hyperdrive create` with the `--service-id` flag to route traffic through the VPC Service. When you use `--service-id`, you do not provide `--origin-host`, `--origin-port`, or `--connection-string`. + +```sh +npx wrangler hyperdrive create my-private-db \ + --service-id \ + --database \ + --user \ + --password \ + --scheme postgresql +``` + +If successful, the command will output a Hyperdrive configuration with an `id` field. Copy this ID for the next step. + +## 3. Configure your Worker + +Update your Wrangler configuration file with the Hyperdrive binding. Replace `` with the ID from the previous step. + + +```jsonc +{ + "$schema": "./node_modules/wrangler/config-schema.json", + "name": "private-db-worker", + "main": "src/index.ts", + "compatibility_date": "$today", + "compatibility_flags": ["nodejs_compat"], + "hyperdrive": [ + { + "binding": "HYPERDRIVE", + "id": "" + } + ] +} +``` + + +The `nodejs_compat` compatibility flag is required for the `pg` database driver. + +## 4. Implement the Worker + +Install the [node-postgres](https://node-postgres.com/) driver: + +```sh +npm install pg +``` + +Create a Worker that connects to your database through Hyperdrive: + +```ts title="src/index.ts" +import { Client } from "pg"; + +export interface Env { + HYPERDRIVE: Hyperdrive; +} + +export default { + async fetch(request, env, ctx): Promise { + const client = new Client({ + connectionString: env.HYPERDRIVE.connectionString, + }); + + try { + await client.connect(); + const result = await client.query("SELECT * FROM pg_tables LIMIT 10"); + return Response.json(result.rows); + } catch (e) { + console.error(e); + return Response.json( + { error: e instanceof Error ? e.message : e }, + { status: 500 }, + ); + } + }, +} satisfies ExportedHandler; +``` + +The Worker creates a new `Client` on each request using the Hyperdrive connection string. Hyperdrive maintains the underlying connection pool, so creating a new client is fast. + +## 5. Deploy and test + +Deploy your Worker: + +```sh +npx wrangler deploy +``` + +Send a request to verify the connection: + +```sh +curl https://private-db-worker..workers.dev +``` + +A successful response returns a JSON array of rows from your database. + +## Next steps + +- Learn more about [how Hyperdrive works](/hyperdrive/concepts/how-hyperdrive-works/) +- Configure [query caching](/hyperdrive/concepts/query-caching/) for Hyperdrive +- Review [VPC Service configuration options](/workers-vpc/configuration/vpc-services/) including TLS certificate verification +- Explore [other examples](/workers-vpc/examples/) diff --git a/src/content/docs/workers-vpc/get-started.mdx b/src/content/docs/workers-vpc/get-started.mdx index a5748e2dc78a7af..bb5b423b66a9be9 100644 --- a/src/content/docs/workers-vpc/get-started.mdx +++ b/src/content/docs/workers-vpc/get-started.mdx @@ -128,6 +128,8 @@ The dashboard will display your new VPC Service with a unique Service ID. Save t +For an HTTP service: + ```sh npx wrangler vpc service create my-private-api \ --type http \ @@ -135,15 +137,28 @@ npx wrangler vpc service create my-private-api \ --hostname ``` +For a TCP service (for example, a PostgreSQL database): + +```sh +npx wrangler vpc service create my-database \ + --type tcp \ + --tcp-port 5432 \ + --app-protocol postgresql \ + --tunnel-id \ + --ipv4 +``` + Replace: - `` with your tunnel ID from step 2 - `` with your internal service hostname (for example, `internal-api.company.local`) +- `` with the private IP address of your service (for example, `10.0.1.50`) You can also: -- Create services using IP addresses by replacing `--hostname ` with `--ipv4 ` (for example, `--ipv4 10.0.1.50`), `--ipv6 ` (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 ` and/or `--https-port ` (for example, `--http-port 8080 --https-port 8443`) +- Create services using IP addresses by replacing `--hostname ` with `--ipv4 `, `--ipv6 `, or both for dual-stack configuration +- Specify custom ports for HTTP services by adding `--http-port ` and/or `--https-port ` (for example, `--http-port 8080 --https-port 8443`) +- Set the TLS certificate verification mode with `--cert-verification-mode` (`verify_full`, `verify_ca`, or `disabled`) The command will return a service ID. Save this for the next step. @@ -188,7 +203,9 @@ export default { // 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://:${url.pathname}${url.search}`); + const targetUrl = new URL( + `http://:${url.pathname}${url.search}`, + ); // Create new request with the target URL but preserve all other properties const proxyRequest = new Request(targetUrl, { @@ -202,7 +219,6 @@ export default { return response; }, } satisfies ExportedHandler; - ``` ## 6. Test locally diff --git a/src/content/docs/workers-vpc/index.mdx b/src/content/docs/workers-vpc/index.mdx index acbf66b75c83fb3..f25314b18613867 100644 --- a/src/content/docs/workers-vpc/index.mdx +++ b/src/content/docs/workers-vpc/index.mdx @@ -27,9 +27,9 @@ Securely connect your private cloud to Cloudflare to build cross-cloud apps. -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. +Workers VPC allows you to connect your Workers to your private APIs, services, and databases in external clouds (AWS, Azure, GCP, on-premise, and others) that are not accessible from the public Internet. -With Workers VPC, you can configure a [Cloudflare Tunnel](/cloudflare-one/networks/connectors/cloudflare-tunnel/) to establish secure, private connections from your private networks to Cloudflare. Then, you can configure a [VPC Service](/workers-vpc/configuration/vpc-services/) for each service in the external private network you need to connect to, and use [VPC Service bindings](/workers-vpc/api/) to connect from Workers. +With Workers VPC, you can configure a [Cloudflare Tunnel](/cloudflare-one/networks/connectors/cloudflare-tunnel/) to establish secure, private connections from your private networks to Cloudflare. Then, you can configure a [VPC Service](/workers-vpc/configuration/vpc-services/) for each service in the external private network you need to connect to, and use [VPC Service bindings](/workers-vpc/api/) to connect from Workers. VPC Services support both HTTP and TCP service types, allowing you to connect to web APIs and databases (through [Hyperdrive](/hyperdrive/)). :::note