From 88310abc53c8833f322584f19943789319478d8c Mon Sep 17 00:00:00 2001 From: Matt Alonso Date: Wed, 25 Mar 2026 16:20:07 -0500 Subject: [PATCH 1/3] fix: correct broken anchor links and style issues in Workers VPC docs - Fix two broken cross-reference anchors in Terraform page (#configuration-example -> #configuration-examples) - Replace 'etc.' with 'and others' in Workers VPC overview --- .../docs/workers-vpc/configuration/vpc-services/terraform.mdx | 4 ++-- src/content/docs/workers-vpc/index.mdx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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..c1e3a9220a67f06 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" { diff --git a/src/content/docs/workers-vpc/index.mdx b/src/content/docs/workers-vpc/index.mdx index acbf66b75c83fb3..1df5411f6b02202 100644 --- a/src/content/docs/workers-vpc/index.mdx +++ b/src/content/docs/workers-vpc/index.mdx @@ -27,7 +27,7 @@ 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 and services 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. From 135281372ad8df94bb13c19d63ac0c90768490b7 Mon Sep 17 00:00:00 2001 From: Matt Alonso Date: Wed, 25 Mar 2026 16:21:25 -0500 Subject: [PATCH 2/3] [Workers VPC] Document TCP services, TLS cert verification, and Hyperdrive integration Add documentation for three new wrangler features: - TCP service type for VPC Services (--type tcp, --tcp-port, --app-protocol) including host:port convenience syntax on --hostname for TCP services - TLS certificate verification mode (--cert-verification-mode) with guidance on self-signed certificates and private CAs - Hyperdrive integration via --service-id for connecting to private databases through Workers VPC New pages: - hyperdrive/configuration/connect-to-private-database-vpc.mdx - workers-vpc/examples/private-database.mdx Updated pages: - workers-vpc/configuration/vpc-services/index.mdx (TCP type, TLS verification) - workers-vpc/configuration/vpc-services/terraform.mdx (TCP and TLS examples) - workers-vpc/get-started.mdx (TCP service creation in CLI tab) - workers-vpc/index.mdx (mention TCP and database support) - hyperdrive/configuration/connect-to-private-database.mdx (cross-ref to VPC approach) - hyperdrive/get-started.mdx (link both private DB approaches in prereqs) --- .../connect-to-private-database-vpc.mdx | 203 ++++++++++++++++++ .../connect-to-private-database.mdx | 4 + src/content/docs/hyperdrive/get-started.mdx | 32 ++- .../configuration/vpc-services/index.mdx | 86 +++++++- .../configuration/vpc-services/terraform.mdx | 74 ++++++- .../workers-vpc/examples/private-database.mdx | 133 ++++++++++++ src/content/docs/workers-vpc/get-started.mdx | 25 ++- src/content/docs/workers-vpc/index.mdx | 4 +- 8 files changed, 526 insertions(+), 35 deletions(-) create mode 100644 src/content/docs/hyperdrive/configuration/connect-to-private-database-vpc.mdx create mode 100644 src/content/docs/workers-vpc/examples/private-database.mdx 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..4fbe2f625e81bb0 --- /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`. For TCP services, `--hostname` accepts `host:port` syntax (for example, `--hostname db.internal:5432`), which sets the TCP port automatically. + +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..ff7aaf39490ea72 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,16 @@ 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. + +As a convenience, you can include the port in the `--hostname` flag using `host:port` syntax (for example, `--hostname db.internal:5432`). When a port is present in the hostname, it is used as the TCP port automatically. If `--tcp-port` is also provided, the values must match. + +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 optimize connections to the service. + +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 +74,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 +112,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 +136,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 c1e3a9220a67f06..43183707c4faf93 100644 --- a/src/content/docs/workers-vpc/configuration/vpc-services/terraform.mdx +++ b/src/content/docs/workers-vpc/configuration/vpc-services/terraform.mdx @@ -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..7bceed0f56c3f72 --- /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`). You can also use `--hostname` with a DNS name instead of `--ipv4`, including `host:port` syntax (for example, `--hostname db.internal:5432`). + +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..2428901a21422fa 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,29 @@ 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 +- For TCP services, include the port in `--hostname` using `host:port` syntax (for example, `--hostname db.internal:5432`) instead of specifying `--tcp-port` separately +- 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 +204,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 +220,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 1df5411f6b02202..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, and others) 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 From 44ac4577bec53f1a36f78024f04d8c402f37bed5 Mon Sep 17 00:00:00 2001 From: Matt Alonso Date: Thu, 16 Apr 2026 13:39:16 -0500 Subject: [PATCH 3/3] [Hyperdrive] Add migration guide and refine VPC docs tradeoffs Adds a how-to for migrating from Tunnel + Access to Workers VPC with two approaches (new config with gradual rollout vs. in-place update), and updates the private database docs to cross-link the migration guide and mark Workers VPC as recommended. Revises the option comparison table so the tradeoffs match the actual behavior described in each option's 'What happens during the update' section. --- .../connect-to-private-database-vpc.mdx | 18 +- .../connect-to-private-database.mdx | 2 +- .../migrate-from-access-to-vpc.mdx | 233 ++++++++++++++++++ src/content/docs/hyperdrive/get-started.mdx | 2 +- 4 files changed, 251 insertions(+), 4 deletions(-) create mode 100644 src/content/docs/hyperdrive/configuration/migrate-from-access-to-vpc.mdx 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 index 4fbe2f625e81bb0..6918c8b4bde6707 100644 --- a/src/content/docs/hyperdrive/configuration/connect-to-private-database-vpc.mdx +++ b/src/content/docs/hyperdrive/configuration/connect-to-private-database-vpc.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: how-to -title: Connect to a private database using Workers VPC +title: Connect to a private database using Workers VPC (Recommended) sidebar: order: 5 badge: @@ -11,7 +11,21 @@ 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/). +For the Tunnel and Access approach, refer to [Connect to a private database using Tunnel](/hyperdrive/configuration/connect-to-private-database/). If you are migrating from the Tunnel and Access approach, refer to [Migrate from Tunnel + Access to Workers VPC](/hyperdrive/configuration/migrate-from-access-to-vpc/). + +## 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. + +- [Cloudflare Tunnel](/cloudflare-one/networks/connectors/cloudflare-tunnel/) is used to establish a secure outbound connection from your private network to Cloudflare. +- A [VPC Service](/workers-vpc/configuration/vpc-services/) is used to route traffic from your Worker through the tunnel to your database, without requiring Cloudflare Access applications or service tokens. + +A request from the Cloudflare Worker to the origin database goes through Hyperdrive, the VPC Service, and the Cloudflare Tunnel established by `cloudflared`. `cloudflared` must be running in the private network in which your database is accessible. + +```mermaid +flowchart LR + A[Cloudflare Worker] --> B[Hyperdrive] --> C[VPC Service] --> D[Cloudflare Tunnel] --> E[Private Database] +``` 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 8c79168e3c84444..934fa626e5d7921 100644 --- a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx +++ b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx @@ -12,7 +12,7 @@ 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. +You can also connect Hyperdrive to a private database using [Workers VPC (Recommended)](/hyperdrive/configuration/connect-to-private-database-vpc/), which does not require configuring Access applications or service tokens. If you are migrating from the Tunnel and Access approach described on this page, refer to [Migrate from Tunnel + Access to Workers VPC](/hyperdrive/configuration/migrate-from-access-to-vpc/). ::: ## How it works diff --git a/src/content/docs/hyperdrive/configuration/migrate-from-access-to-vpc.mdx b/src/content/docs/hyperdrive/configuration/migrate-from-access-to-vpc.mdx new file mode 100644 index 000000000000000..796aa21c2701347 --- /dev/null +++ b/src/content/docs/hyperdrive/configuration/migrate-from-access-to-vpc.mdx @@ -0,0 +1,233 @@ +--- +pcx_content_type: how-to +title: Migrate from Tunnel + Access to Workers VPC +sidebar: + order: 5 +--- + +import { Tabs, TabItem, WranglerConfig, Steps } from "~/components"; + +If you currently connect Hyperdrive to a private database using [Cloudflare Tunnel and Cloudflare Access](/hyperdrive/configuration/connect-to-private-database/), you can migrate to [Workers VPC](/hyperdrive/configuration/connect-to-private-database-vpc/) to simplify your setup. Workers VPC removes the need for Access applications, service tokens, and policies — you create a TCP VPC Service that points to your database and pass its service ID to Hyperdrive. + +This guide covers two migration approaches. Both start with the same first step: creating a TCP VPC Service that points to your existing database. + +| Approach | Best for | Tradeoff | +| -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| [Create a new Hyperdrive configuration](#option-1-create-a-new-hyperdrive-configuration-recommended) | Production workloads that need incremental traffic shifting and instant rollback | More steps, temporarily requires two Hyperdrive configurations, and the new configuration starts with an empty query cache. | +| [Update your existing Hyperdrive configuration](#option-2-update-your-existing-hyperdrive-configuration) | Simpler setups where preserving the existing query cache is preferable to easy rollback | Fewer steps and the query cache is preserved, but rolling back requires the original Access credentials to still exist. | + +## Prerequisites + +- An existing Hyperdrive configuration that uses [Cloudflare Tunnel and Cloudflare Access](/hyperdrive/configuration/connect-to-private-database/) to connect to a private database. +- A [Cloudflare Tunnel](/workers-vpc/configuration/tunnel/) running in the same network as your database. You can reuse the tunnel from your existing setup. +- The **Connectivity Directory Admin** role on your Cloudflare account to create VPC Services. + +## Create a TCP VPC Service + +Both migration options require a TCP VPC Service that points to your database. This step is non-disruptive and does not affect your existing Hyperdrive configuration. + + + + +```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 ID of the tunnel connected to your database network. +- `` 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`. + +Save the service ID returned by the command. You will use it in the next step. + +For full VPC Service configuration options including TLS certificate verification, refer to [Connect to a private database using Workers VPC](/hyperdrive/configuration/connect-to-private-database-vpc/#2-create-a-tcp-vpc-service). + +## Option 1: Create a new Hyperdrive configuration (recommended) + +This approach creates a second Hyperdrive configuration that uses the VPC Service, then uses [gradual deployments](/workers/configuration/versions-and-deployments/gradual-deployments/) to incrementally shift traffic from the old configuration to the new one. This gives you zero-downtime migration and the ability to roll back instantly at any point. + + + +1. Create a new Hyperdrive configuration that uses the VPC Service: + + + + + + ```sh + npx wrangler hyperdrive create my-hyperdrive-vpc \ + --service-id \ + --database \ + --user \ + --password \ + --scheme postgresql + ``` + + + + + + ```sh + npx wrangler hyperdrive create my-hyperdrive-vpc \ + --service-id \ + --database \ + --user \ + --password \ + --scheme mysql + ``` + + + + + + Use the same database name, username, and password as your existing Hyperdrive configuration. Save the new Hyperdrive configuration ID. + +2. Add a second Hyperdrive binding to your Wrangler configuration file. Keep the existing binding and add the new one alongside it: + + + + ```toml + [[hyperdrive]] + binding = "HYPERDRIVE" + id = "" + + [[hyperdrive]] + binding = "HYPERDRIVE_VPC" + id = "" + ``` + + + +3. Update your Worker code to use the new binding. For example, if you use `node-postgres`: + + ```ts + const client = new Client({ + // Change from env.HYPERDRIVE to env.HYPERDRIVE_VPC + connectionString: env.HYPERDRIVE_VPC.connectionString, + }); + ``` + +4. Upload the new Worker version without deploying it: + + ```sh + npx wrangler versions upload + ``` + +5. Use gradual deployments to shift traffic incrementally. Start with a small percentage to verify the VPC connection works: + + ```sh + npx wrangler versions deploy + ``` + + The interactive prompt will ask you to set traffic percentages for each version. Start with 10% on the new version and 90% on the old version. Monitor your application and increase the percentage as you gain confidence. + +6. Once you have shifted 100% of traffic to the new version, remove the old binding from your Wrangler configuration file: + + + + ```toml + [[hyperdrive]] + binding = "HYPERDRIVE" + id = "" + ``` + + + + Update your Worker code to use the original binding name (`HYPERDRIVE` instead of `HYPERDRIVE_VPC`) and redeploy: + + ```sh + npx wrangler deploy + ``` + +7. Delete the old Hyperdrive configuration: + + ```sh + npx wrangler hyperdrive delete + ``` + +8. Clean up the Cloudflare Access resources that were used by the old configuration. If no other services depend on them, delete the Access application, service token, and policy from the [Zero Trust dashboard](https://one.dash.cloudflare.com/). + + + +### Rolling back + +At any point during the gradual deployment, you can shift traffic back to 100% on the old version by running `wrangler versions deploy` again and setting the old version to 100%. The old Hyperdrive configuration and Access setup remain unchanged until you explicitly delete them. + +### What happens during the update + +- **Query cache:** The new configuration does not share the cache with the old configuration. The speed of the progressive rollout should be managed to maintain an acceptable cache hit ratio, if your origin database cannot handle a thundering herd of uncached queries. +- **Connection latency:** There may be a brief increase in latency as new connections are established through the VPC Service, until the connection pool is filled. + +## Option 2: Update your existing Hyperdrive configuration + +This approach updates your existing Hyperdrive configuration in place to use the VPC Service instead of Access. It requires fewer steps but does not allow instant rollback. + + + +1. Update the existing Hyperdrive configuration to use the VPC Service: + + ```sh + npx wrangler hyperdrive update \ + --service-id + ``` + + The `--service-id` flag replaces the Access-based connection with the VPC Service. The Hyperdrive configuration ID stays the same, so your Worker binding does not need to change. + +2. Redeploy your Worker to pick up the updated configuration: + + ```sh + npx wrangler deploy + ``` + +3. Verify that your application is working correctly. Check that queries return expected results and review [Hyperdrive metrics](/hyperdrive/observability/metrics/) for errors. + +4. Clean up the Cloudflare Access resources that were used by the old configuration. If no other services depend on them, delete the Access application, service token, and policy from the [Zero Trust dashboard](https://one.dash.cloudflare.com/). + + + +### What happens during the update + +- **Query cache:** Updating the configuration does not purge the Hyperdrive query cache. Cached query results continue to be served until their TTL expires (default [`max_age`](/hyperdrive/concepts/query-caching/) of 60 seconds). +- **Connection pool:** The existing connection pool is rebuilt. New connections are established through the VPC Service. In-flight queries on existing connections complete normally. +- **Connection latency:** There may be a brief increase in latency as new connections are established through the VPC Service. Queries that were being served from cache are unaffected. + +### Rolling back + +To revert to the Access-based setup, run `wrangler hyperdrive update` with the original Access credentials: + +```sh +npx wrangler hyperdrive update \ + --access-client-id \ + --access-client-secret \ + --origin-host \ + --origin-port +``` + +This requires that the Access application and service token still exist. If you have already deleted them, you will need to recreate them by following the [Tunnel + Access setup guide](/hyperdrive/configuration/connect-to-private-database/). + +## Next steps + +- Review [VPC Service configuration options](/workers-vpc/configuration/vpc-services/) including TLS certificate verification modes. +- Configure [query caching](/hyperdrive/concepts/query-caching/) for your Hyperdrive configuration. +- Set up [high availability tunnels](/workers-vpc/configuration/tunnel/hardware-requirements/) for production workloads. +- Learn more about [gradual deployments](/workers/configuration/versions-and-deployments/gradual-deployments/) for Workers. diff --git a/src/content/docs/hyperdrive/get-started.mdx b/src/content/docs/hyperdrive/get-started.mdx index 170773e82ee42ab..7df3b537dbc0564 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_, 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/). +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/). ## 1. Log in