> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Private Service Connect

> This document describes how to connect to ClickHouse Cloud using Google Cloud Platform (GCP) Private Service Connect (PSC), and how to disable access to your ClickHouse Cloud services from addresses other than GCP PSC addresses using ClickHouse Cloud IP access lists.

export const ScalePlanFeatureBadge = ({feature = 'This feature', linking_verb_are = false}) => {
  return <div className="scalePlanFeatureContainer">
            <div className="scalePlanFeatureBadge">
                Scale plan feature
            </div>
            <div>
                <p>{feature} {linking_verb_are ? 'are' : 'is'} available in the Scale and Enterprise plans. To upgrade, visit the plans page in the cloud console.</p>
            </div>
        </div>;
};

export const Image = ({img, alt, size = "lg"}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} />
      </Frame>
    </div>;
};

<ScalePlanFeatureBadge feature="GCP PSC" />

Private Service Connect (PSC) is a Google Cloud networking feature that allows consumers to access managed services privately inside their virtual private cloud (VPC) network. Similarly, it allows managed service producers to host these services in their own separate VPC networks and offer a private connection to their consumers.

Service producers publish their applications to consumers by creating Private Service Connect services. Service consumers access those Private Service Connect services directly through one of these Private Service Connect types.

<Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/security/gcp-psc-overview.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=de8d006ed836385f67b2f1d68811188b" size="lg" alt="Overview of Private Service Connect" border width="2048" height="713" data-path="images/cloud/security/gcp-psc-overview.webp" />

<Warning>
  GCP Private Service Connect supports only connections initiated from your GCP VPC to ClickHouse Cloud. It can't be used for connections initiated from ClickHouse Cloud to services in your VPC, such as a [private database](#connecting-to-a-remote-database).

  By default, a ClickHouse service isn't available over a Private Service connection even if the PSC connection is approved and established; you need to explicitly add the PSC ID to the allow list on an instance level by completing the [step](#add-endpoint-id-to-services-allow-list) below.
</Warning>

**Important considerations for using Private Service Connect Global Access**:

1. Regions utilizing Global Access must belong to the same VPC.
2. Global Access must be explicitly enabled at the PSC level (refer to the screenshot below).
3. Ensure that your firewall settings don't block access to PSC from other regions.
4. Be aware that you may incur GCP inter-region data transfer charges.

Cross-region connectivity isn't supported. The producer and consumer regions must be the same. However, you can connect from other regions within your VPC by enabling [Global Access](https://cloud.google.com/vpc/docs/about-accessing-vpc-hosted-services-endpoints#global-access) at the Private Service Connect (PSC) level.

**Complete the following steps to enable GCP PSC**:

1. Obtain GCP service attachment for Private Service Connect.
2. Create a service endpoint.
3. Add "Endpoint ID" to ClickHouse Cloud service.
4. Add "Endpoint ID" to ClickHouse service allow list.

<h2 id="attention">
  Attention
</h2>

ClickHouse attempts to group your services to reuse the same published [PSC endpoint](https://cloud.google.com/vpc/docs/private-service-connect) within the GCP region. However, this grouping isn't guaranteed, especially if you spread your services across multiple ClickHouse organizations.
If you already have PSC configured for other services in your ClickHouse organization, you can often skip most of the steps because of that grouping and proceed directly to the final step: [Add "Endpoint ID" to ClickHouse service allow list](#add-endpoint-id-to-services-allow-list).

Find Terraform examples [here](https://github.com/ClickHouse/terraform-provider-clickhouse/tree/main/examples/).

<h2 id="before-you-get-started">
  Before you get started
</h2>

<Note>
  Code examples are provided below to show how to set up Private Service Connect within a ClickHouse Cloud service. In our examples below, we will use:

  * GCP region: `us-central1`
  * GCP project (customer GCP project): `my-gcp-project`
  * GCP private IP address in customer GCP project: `10.128.0.2`
  * GCP VPC in customer GCP project: `default`
</Note>

You'll need to retrieve information about your ClickHouse Cloud service. You can do this either via the ClickHouse Cloud console or the ClickHouse API. If you're going to use the ClickHouse API, please set the following environment variables before proceeding:

```shell theme={null}
REGION=<Your region code using the GCP format, for example: us-central1>
PROVIDER=gcp
KEY_ID=<Your ClickHouse key ID>
KEY_SECRET=<Your ClickHouse key secret>
ORG_ID=<Your ClickHouse organization ID>
SERVICE_NAME=<Your ClickHouse service name>
```

You can [create a new ClickHouse Cloud API key](/docs/products/cloud/features/admin-features/api/openapi) or use an existing one.

Get your ClickHouse `INSTANCE_ID` by filtering by region, provider and service name:

```shell theme={null}
INSTANCE_ID=$(curl --silent --user "${KEY_ID:?}:${KEY_SECRET:?}" \
"https://api.clickhouse.cloud/v1/organizations/${ORG_ID:?}/services" | \
jq ".result[] | select (.region==\"${REGION:?}\" and .provider==\"${PROVIDER:?}\" and .name==\"${SERVICE_NAME:?}\") | .id " -r)
```

<Note>
  * You can retrieve your Organization ID from the ClickHouse console (Organization -> Organization Details).
  * You can [create a new key](/docs/products/cloud/features/admin-features/api/openapi) or use an existing one.
</Note>

<h2 id="obtain-gcp-service-attachment-and-dns-name-for-private-service-connect">
  Obtain GCP service attachment and DNS name for Private Service Connect
</h2>

<h3 id="option-1-clickhouse-cloud-console">
  Option 1: ClickHouse Cloud console
</h3>

In the ClickHouse Cloud console, open the service that you would like to connect via Private Service Connect, then open the **Settings** menu. Click on the **Set up private endpoint** button. Make a note of the **Service name** (`endpointServiceId`) and **DNS name** (`privateDnsHostname`). You'll use them in the next steps.

<Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/security/gcp-privatelink-pe-create.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=db46b1232ff16b903a9d763d58fb859f" size="lg" alt="Private Endpoints" border width="1368" height="719" data-path="images/cloud/security/gcp-privatelink-pe-create.webp" />

<h3 id="option-2-api">
  Option 2: API
</h3>

<Note>
  You need at least one instance deployed in the region to perform this step.
</Note>

Obtain GCP service attachment and DNS name for Private Service Connect:

```bash theme={null}
curl --silent --user "${KEY_ID:?}:${KEY_SECRET:?}" "https://api.clickhouse.cloud/v1/organizations/${ORG_ID:?}/services/${INSTANCE_ID:?}/privateEndpointConfig" | jq  .result
{
  "endpointServiceId": "projects/.../regions/us-central1/serviceAttachments/production-us-central1-clickhouse-cloud",
  "privateDnsHostname": "xxxxxxxxxx.us-central1.p.gcp.clickhouse.cloud"
}
```

Make a note of the `endpointServiceId` and `privateDnsHostname`. You'll use them in the next steps.

<h2 id="create-service-endpoint">
  Create service endpoint
</h2>

<Warning>
  This section covers ClickHouse-specific details for configuring ClickHouse via GCP PSC (Private Service Connect). GCP-specific steps are provided as a reference to guide you on where to look, but they may change over time without notice from the GCP cloud provider. Please consider GCP configuration based on your specific use case.

  Please note that ClickHouse isn't responsible for configuring the required GCP PSC endpoints or DNS records.

  For any issues related to GCP configuration tasks, contact GCP Support directly.
</Warning>

In this section, you'll create a service endpoint.

<h3 id="adding-a-private-service-connection">
  Adding a private service connection
</h3>

First, you'll create a Private Service Connection.

<h4 id="option-1-using-google-cloud-console">
  Option 1: Using Google Cloud console
</h4>

In the Google Cloud console, navigate to **Network services -> Private Service Connect**.

<Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/security/gcp-psc-open.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=74e5b5d8bca1216cddc5d4182f982022" size="lg" alt="Open Private Service Connect in Google Cloud console" border width="1892" height="737" data-path="images/cloud/security/gcp-psc-open.webp" />

Open the Private Service Connect creation dialog by clicking on the **Connect Endpoint** button.

* **Target**: use **Published service**
* **Target service**: use `endpointServiceId`<sup>API</sup> or `Service name`<sup>console</sup> from [Obtain GCP service attachment for Private Service Connect](#obtain-gcp-service-attachment-and-dns-name-for-private-service-connect) step.
* **Endpoint name**: set a name for the PSC **Endpoint name**.
* **Network/Subnetwork/IP address**: Choose the network you want to use for the connection. You will need to create an IP address or use an existing one for the Private Service Connect endpoint. In our example, we pre-created an address with the name **your-ip-address** and assigned IP address `10.128.0.2`.
* To make the endpoint available from any region, you can enable the **Enable global access** checkbox.

<Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/security/gcp-psc-enable-global-access.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=4dc2a06daf8bc6dfe133b23251547853" size="md" alt="Enable Global Access for Private Service Connect" border width="545" height="660" data-path="images/cloud/security/gcp-psc-enable-global-access.webp" />

To create the PSC Endpoint, use the **ADD ENDPOINT** button.

The **Status** column will change from **Pending** to **Accepted** once the connection is approved.

<Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/security/gcp-psc-copy-connection-id.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=6278569f43eb260ef1f628811078e214" size="lg" alt="Copy PSC Connection ID" border width="1441" height="116" data-path="images/cloud/security/gcp-psc-copy-connection-id.webp" />

Copy ***PSC Connection ID***; you'll use it as ***Endpoint ID*** in the next steps.

<h4 id="option-2-using-terraform">
  Option 2: Using Terraform
</h4>

```json theme={null}
provider "google" {
  project = "my-gcp-project"
  region  = "us-central1"
}

variable "region" {
  type    = string
  default = "us-central1"
}

variable "subnetwork" {
  type = string
  default = "https://www.googleapis.com/compute/v1/projects/my-gcp-project/regions/us-central1/subnetworks/default"
}

variable "network" {
  type = string
  default = "https://www.googleapis.com/compute/v1/projects/my-gcp-project/global/networks/default"
}

resource "google_compute_address" "psc_endpoint_ip" {
  address      = "10.128.0.2"
  address_type = "INTERNAL"
  name         = "your-ip-address"
  purpose      = "GCE_ENDPOINT"
  region       = var.region
  subnetwork   = var.subnetwork
}

resource "google_compute_forwarding_rule" "clickhouse_cloud_psc" {
  ip_address            = google_compute_address.psc_endpoint_ip.self_link
  name                  = "ch-cloud-${var.region}"
  network               = var.network
  region                = var.region
  load_balancing_scheme = ""
  # service attachment
  target = "https://www.googleapis.com/compute/v1/$TARGET" # See below in notes
}

output "psc_connection_id" {
  value       = google_compute_forwarding_rule.clickhouse_cloud_psc.psc_connection_id
  description = "Add GCP PSC Connection ID to allow list on instance level."
}
```

<Note>
  use `endpointServiceId`<sup>API</sup> or `Service name`<sup>console</sup> from [Obtain GCP service attachment for Private Service Connect](#obtain-gcp-service-attachment-and-dns-name-for-private-service-connect) step
</Note>

<h2 id="set-private-dns-name-for-endpoint">
  Set private DNS name for endpoint
</h2>

<Note>
  There are various ways to configure DNS. Please set up DNS according to your specific use case.
</Note>

You need to point the "DNS name", taken from [Obtain GCP service attachment for Private Service Connect](#obtain-gcp-service-attachment-and-dns-name-for-private-service-connect) step, to the GCP Private Service Connect endpoint IP address. This ensures that services/components within your VPC/Network can resolve it properly.

<Warning>
  Connecting to the PSC endpoint IP address directly is not sufficient. ClickHouse Cloud routes connections based on the DNS name (via SNI in the TLS handshake), so you must configure DNS to resolve the private DNS hostname (`privateDnsHostname`) to the endpoint IP address. Without this, ClickHouse Cloud cannot identify which service the connection is intended for and the connection will fail.
</Warning>

<h2 id="add-endpoint-id-to-clickhouse-cloud-organization">
  Add Endpoint ID to ClickHouse Cloud organization
</h2>

<h3 id="option-1-clickhouse-cloud-console-1">
  Option 1: ClickHouse Cloud console
</h3>

To add an endpoint to your organization, proceed to the [Add "Endpoint ID" to ClickHouse service allow list](#add-endpoint-id-to-services-allow-list) step. Adding the `PSC Connection ID` using the ClickHouse Cloud console to the service allow list automatically adds it to the organization.

To remove an endpoint, open **Organization details -> Private Endpoints** and click the delete button to remove the endpoint.

<Image img="https://mintcdn.com/private-7c7dfe99/Ph2XgLY43sq6v4yO/images/cloud/security/gcp-pe-remove-private-endpoint.webp?fit=max&auto=format&n=Ph2XgLY43sq6v4yO&q=85&s=1585cc2fc5e987fd190e4347adc69dfb" size="lg" alt="Remove Private Endpoint from ClickHouse Cloud" border width="2900" height="1242" data-path="images/cloud/security/gcp-pe-remove-private-endpoint.webp" />

<h3 id="option-2-api-1">
  Option 2: API
</h3>

Set these environment variables before running any commands:

Replace `ENDPOINT_ID` below with the value from **Endpoint ID** from the [Adding a Private Service Connection](#adding-a-private-service-connection) step.

To add an endpoint, run:

```bash theme={null}
cat <<EOF | tee pl_config_org.json
{
  "privateEndpoints": {
    "add": [
      {
        "cloudProvider": "gcp",
        "id": "${ENDPOINT_ID:?}",
        "description": "A GCP private endpoint",
        "region": "${REGION:?}"
      }
    ]
  }
}
EOF
```

To remove an endpoint, run:

```bash theme={null}
cat <<EOF | tee pl_config_org.json
{
  "privateEndpoints": {
    "remove": [
      {
        "cloudProvider": "gcp",
        "id": "${ENDPOINT_ID:?}",
        "region": "${REGION:?}"
      }
    ]
  }
}
EOF
```

Add/remove a Private Endpoint for an organization:

```bash theme={null}
curl --silent --user "${KEY_ID:?}:${KEY_SECRET:?}" -X PATCH -H "Content-Type: application/json" "https://api.clickhouse.cloud/v1/organizations/${ORG_ID:?}" -d @pl_config_org.json
```

<h2 id="add-endpoint-id-to-services-allow-list">
  Add "Endpoint ID" to ClickHouse service allow list
</h2>

You need to add an Endpoint ID to the allow-list for each instance that should be available using Private Service Connect.

<h3 id="option-1-clickhouse-cloud-console-2">
  Option 1: ClickHouse Cloud console
</h3>

In the ClickHouse Cloud console, open the service that you would like to connect via Private Service Connect, then navigate to **Settings**. Enter the `Endpoint ID` retrieved from the [Adding a Private Service Connection](#adding-a-private-service-connection) step. Click **Create endpoint**.

<Note>
  If you want to allow access from an existing Private Service Connect connection, use the existing endpoint drop-down menu.
</Note>

<Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/security/gcp-privatelink-pe-filters.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=8b64bf4735e877c0ed6ea9fcf0676b19" size="lg" alt="Private Endpoints Filter" border width="1367" height="768" data-path="images/cloud/security/gcp-privatelink-pe-filters.webp" />

<h3 id="option-2-api-2">
  Option 2: API
</h3>

Set these environment variables before running any commands:

Replace **ENDPOINT\_ID** below with the value from **Endpoint ID** from the [Adding a Private Service Connection](#adding-a-private-service-connection) step.

Execute it for each service that should be available using Private Service Connect.

To add:

```bash theme={null}
cat <<EOF | tee pl_config.json
{
  "privateEndpointIds": {
    "add": [
      "${ENDPOINT_ID}"
    ]
  }
}
EOF
```

To remove:

```bash theme={null}
cat <<EOF | tee pl_config.json
{
  "privateEndpointIds": {
    "remove": [
      "${ENDPOINT_ID}"
    ]
  }
}
EOF
```

```bash theme={null}
curl --silent --user "${KEY_ID:?}:${KEY_SECRET:?}" -X PATCH -H "Content-Type: application/json" "https://api.clickhouse.cloud/v1/organizations/${ORG_ID:?}/services/${INSTANCE_ID:?}" -d @pl_config.json | jq
```

<h2 id="accessing-instance-using-private-service-connect">
  Accessing instance using Private Service Connect
</h2>

Each service with Private Service Connect enabled has a public and private endpoint. To connect using Private Service Connect, you need to use the private endpoint, which is the `privateDnsHostname` from the [Obtain GCP service attachment for Private Service Connect](#obtain-gcp-service-attachment-and-dns-name-for-private-service-connect) step.

<h3 id="getting-private-dns-hostname">
  Getting private DNS hostname
</h3>

<h4 id="option-1-clickhouse-cloud-console-3">
  Option 1: ClickHouse Cloud console
</h4>

In the ClickHouse Cloud console, navigate to **Settings**. Click on the **Set up private endpoint** button. In the opened flyout, copy the **DNS Name**.

<Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/security/gcp-privatelink-pe-dns.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=897499a179f8f630ff1b70f95b07bd75" size="lg" alt="Private Endpoint DNS Name" border width="1367" height="768" data-path="images/cloud/security/gcp-privatelink-pe-dns.webp" />

<h4 id="option-2-api-3">
  Option 2: API
</h4>

```bash theme={null}
curl --silent --user "${KEY_ID:?}:${KEY_SECRET:?}" "https://api.clickhouse.cloud/v1/organizations/${ORG_ID:?}/services/${INSTANCE_ID:?}/privateEndpointConfig" | jq  .result
```

```response theme={null}
{
  ...
  "privateDnsHostname": "xxxxxxx.<region code>.p.gcp.clickhouse.cloud"
}
```

In this example, connection to the `xxxxxxx.yy-xxxxN.p.gcp.clickhouse.cloud` hostname will be routed to Private Service Connect. Meanwhile, `xxxxxxx.yy-xxxxN.gcp.clickhouse.cloud` will be routed over the internet.

<h2 id="troubleshooting">
  Troubleshooting
</h2>

<h3 id="test-dns-setup">
  Test DNS setup
</h3>

DNS\_NAME - Use `privateDnsHostname` from [Obtain GCP service attachment for Private Service Connect](#obtain-gcp-service-attachment-and-dns-name-for-private-service-connect) step

```bash theme={null}
nslookup $DNS_NAME
```

```response theme={null}
Non-authoritative answer:
...
Address: 10.128.0.2
```

<h3 id="connection-reset-by-peer">
  Connection reset by peer
</h3>

* Most likely, the Endpoint ID wasn't added to the service allow-list. Revisit the [*Add endpoint ID to services allow-list* step](#add-endpoint-id-to-services-allow-list).

<h3 id="test-connectivity">
  Test connectivity
</h3>

If you have problems connecting using a PSC link, check your connectivity using `openssl`. Make sure the Private Service Connect endpoint status is `Accepted`:

OpenSSL should be able to connect (see CONNECTED in the output). `errno=104` is expected.

DNS\_NAME - Use `privateDnsHostname` from [Obtain GCP service attachment for Private Service Connect](#obtain-gcp-service-attachment-and-dns-name-for-private-service-connect) step

```bash theme={null}
openssl s_client -connect ${DNS_NAME}:9440
```

```response highlight={1} theme={null}
CONNECTED(00000003)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 335 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
```

<h3 id="checking-endpoint-filters">
  Checking endpoint filters
</h3>

<h4 id="rest-api">
  REST API
</h4>

```bash theme={null}
curl --silent --user "${KEY_ID:?}:${KEY_SECRET:?}" -X GET -H "Content-Type: application/json" "https://api.clickhouse.cloud/v1/organizations/${ORG_ID:?}/services/${INSTANCE_ID:?}" | jq .result.privateEndpointIds
[
  "102600141743718403"
]
```

<h3 id="connecting-to-a-remote-database">
  Connecting to a remote database
</h3>

According to the [GCP Private Service Connect documentation](https://cloud.google.com/vpc/docs/private-service-connect):

> Service-oriented design: Producer services are published through load balancers that expose a single IP address to the consumer VPC network. Consumer traffic that accesses producer services is unidirectional and can only access the service IP address, rather than having access to an entire peered VPC network.

To connect [MySQL](/docs/reference/functions/table-functions/mysql) or [PostgreSQL](/docs/reference/functions/table-functions/postgresql) table functions in ClickHouse Cloud to a database hosted in your GCP VPC, configure your GCP VPC firewall rules to allow connections from ClickHouse Cloud. Check the [default egress IP addresses for ClickHouse Cloud regions](/docs/products/cloud/guides/data-sources/cloud-endpoints-api), along with the [available static IP addresses](https://api.clickhouse.cloud/static-ips.json).

<h2 id="more-information">
  More information
</h2>

For more detailed information, visit [cloud.google.com/vpc/docs/configure-private-service-connect-services](https://cloud.google.com/vpc/docs/configure-private-service-connect-services).
