> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-detect-table-modification.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS PrivateLink

> This document describes how to connect to ClickHouse Cloud using AWS PrivateLink.

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>;
};

You can use [AWS PrivateLink](https://aws.amazon.com/privatelink/) to establish secure connectivity between VPCs, AWS services, your on-premises systems, and ClickHouse Cloud without exposing traffic to the public Internet. This document outlines the steps to connect to ClickHouse Cloud using AWS PrivateLink.

<Warning>
  AWS PrivateLink supports only connections initiated from your AWS 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).
</Warning>

To restrict access to your ClickHouse Cloud services exclusively through AWS PrivateLink addresses, follow the instructions provided by ClickHouse Cloud [IP Access Lists](/products/cloud/guides/security/connectivity/setting-ip-filters).

<Note>
  ClickHouse Cloud supports [cross-region PrivateLink](https://aws.amazon.com/about-aws/whats-new/2024/11/aws-privatelink-across-region-connectivity/) from the following regions:

  * sa-east-1
  * il-central-1
  * me-south-1
  * mx-central-1
  * eu-central-2
  * eu-north-1
  * eu-south-2
  * eu-west-3
  * eu-south-1
  * eu-west-2
  * eu-west-1
  * eu-central-1
  * ca-west-1
  * ca-central-1
  * ap-northeast-1
  * ap-southeast-2
  * ap-southeast-1
  * ap-northeast-2
  * ap-northeast-3
  * ap-south-1
  * ap-southeast-4
  * ap-southeast-3
  * ap-south-2
  * ap-east-1
  * af-south-1
  * us-west-2
  * us-west-1
  * us-east-2
  * us-east-1
    Pricing considerations: AWS will charge users for cross region data transfer, see pricing [here](https://aws.amazon.com/privatelink/pricing/).
</Note>

**Please complete the following to enable AWS PrivateLink**:

1. Obtain Endpoint "Service name".
2. Create AWS Endpoint.
3. Add "Endpoint ID" to ClickHouse Cloud organization.
4. Add "Endpoint ID" to ClickHouse service allow list.

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

<h2 id="considerations">
  Important considerations
</h2>

ClickHouse attempts to group your services to reuse the same published [service endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/privatelink-share-your-services.html#endpoint-service-overview) within the AWS region. However, this grouping isn't guaranteed, especially if you spread your services across multiple ClickHouse organizations.
If you already have PrivateLink 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 ClickHouse "Endpoint ID" to ClickHouse service allow list.

<h2 id="prerequisites">
  Prerequisites for this process
</h2>

Before you get started you will need:

1. Your AWS account.
2. [ClickHouse API key](/products/cloud/features/admin-features/api/openapi) with the necessary permissions to create and manage private endpoints on ClickHouse side.

<h2 id="steps">
  Steps
</h2>

Follow these steps to connect your ClickHouse Cloud services via AWS PrivateLink.

<h3 id="obtain-endpoint-service-info">
  Obtain endpoint "Service name"
</h3>

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

In the ClickHouse Cloud console, open the service you want to connect via PrivateLink, then navigate to the **Settings** menu.

<Image img="https://mintcdn.com/private-7c7dfe99-detect-table-modification/m2_tVxhtEg5OHgtu/images/cloud/security/aws-privatelink-pe-create.webp?fit=max&auto=format&n=m2_tVxhtEg5OHgtu&q=85&s=c75b506a893127594f72ab0dca8c5712" size="md" alt="Private Endpoints" border width="1556" height="740" data-path="images/cloud/security/aws-privatelink-pe-create.webp" />

Make a note of the `Service name` and `DNS name`, then [move onto next step](#create-aws-endpoint).

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

First, set the following environment variables before running any commands:

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

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)
```

Obtain `endpointServiceId` and `privateDnsHostname` for your PrivateLink configuration:

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

This command should return something like:

```result theme={null}
{
  "endpointServiceId": "com.amazonaws.vpce.us-west-2.vpce-svc-xxxxxxxxxxxxxxxxx",
  "privateDnsHostname": "xxxxxxxxxx.us-west-2.vpce.aws.clickhouse.cloud"
}
```

Make a note of the `endpointServiceId` and `privateDnsHostname` [move onto next step](#create-aws-endpoint).

<h3 id="create-aws-endpoint">
  Create AWS endpoint
</h3>

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

  Please note that ClickHouse isn't responsible for configuring the required AWS VPC endpoints, security group rules or DNS records.

  If you previously enabled "private DNS names" while setting up PrivateLink and are experiencing difficulties configuring new services via PrivateLink, please contact ClickHouse support. For any other issues related to AWS configuration tasks, contact AWS Support directly.
</Warning>

<h4 id="option-1-aws-console">
  Option 1: AWS console
</h4>

Open the AWS console and Go to **VPC** → **Endpoints** → **Create endpoints**.

Select **Endpoint services that use NLBs and GWLBs** and use `Service name`<sup>console</sup> or `endpointServiceId`<sup>API</sup> you got from [Obtain Endpoint "Service name" ](#obtain-endpoint-service-info) step in **Service Name** field. Click **Verify service**:

<Image img="https://mintcdn.com/private-7c7dfe99-detect-table-modification/m2_tVxhtEg5OHgtu/images/cloud/security/aws-privatelink-endpoint-settings.webp?fit=max&auto=format&n=m2_tVxhtEg5OHgtu&q=85&s=14f6eb58efad8c2262a197544ea898d1" size="md" alt="AWS PrivateLink Endpoint Settings" border width="1304" height="721" data-path="images/cloud/security/aws-privatelink-endpoint-settings.webp" />

If you want to establish a cross-regional connection via PrivateLink, enable the "Cross region endpoint" checkbox and specify the service region. The service region is where the ClickHouse instance is running.

If you get a "Service name couldn't be verified." error, please contact Customer Support to request adding new regions to the supported regions list.

Next, select your VPC and subnets:

<Image img="https://mintcdn.com/private-7c7dfe99-detect-table-modification/m2_tVxhtEg5OHgtu/images/cloud/security/aws-privatelink-select-vpc-and-subnets.webp?fit=max&auto=format&n=m2_tVxhtEg5OHgtu&q=85&s=7fc061663b331c0b13e1ecfaced2ac0f" size="md" alt="Select VPC and subnets" border width="1312" height="595" data-path="images/cloud/security/aws-privatelink-select-vpc-and-subnets.webp" />

As an optional step, assign Security groups/Tags:

<Note>
  Make sure that ports `443`, `8443`, `9440`, `3306` are allowed in the security group.
</Note>

After creating the VPC Endpoint, make a note of the `Endpoint ID` value; you'll need it for an upcoming step.

<Image img="https://mintcdn.com/private-7c7dfe99-detect-table-modification/m2_tVxhtEg5OHgtu/images/cloud/security/aws-privatelink-vpc-endpoint-id.webp?fit=max&auto=format&n=m2_tVxhtEg5OHgtu&q=85&s=e9d2da70dc16297e623fa3fe141453fe" size="md" alt="VPC Endpoint ID" border width="467" height="212" data-path="images/cloud/security/aws-privatelink-vpc-endpoint-id.webp" />

<h4 id="option-2-aws-cloudformation">
  Option 2: AWS CloudFormation
</h4>

Next, you need to create a VPC Endpoint using `Service name`<sup>console</sup> or `endpointServiceId`<sup>API</sup> you got from [Obtain Endpoint "Service name" ](#obtain-endpoint-service-info) step.
Make sure to use correct subnet IDs, security groups, and VPC ID.

```response theme={null}
Resources:
  ClickHouseInterfaceEndpoint:
    Type: 'AWS::EC2::VPCEndpoint'
    Properties:
      VpcEndpointType: Interface
      PrivateDnsEnabled: false
      ServiceName: <Service name(endpointServiceId), pls see above>
      VpcId: vpc-vpc_id
      SubnetIds:
        - subnet-subnet_id1
        - subnet-subnet_id2
        - subnet-subnet_id3
      SecurityGroupIds:
        - sg-security_group_id1
        - sg-security_group_id2
        - sg-security_group_id3
```

After creating the VPC Endpoint, make a note of the `Endpoint ID` value; you'll need it for an upcoming step.

<h4 id="option-3-terraform">
  Option 3: Terraform
</h4>

`service_name` below is `Service name`<sup>console</sup> or `endpointServiceId`<sup>API</sup> you got from [Obtain Endpoint "Service name" ](#obtain-endpoint-service-info) step

```json theme={null}
resource "aws_vpc_endpoint" "this" {
  vpc_id            = var.vpc_id
  service_name      = "<pls see comment above>"
  vpc_endpoint_type = "Interface"
  security_group_ids = [
    Var.security_group_id1,var.security_group_id2, var.security_group_id3,
  ]
  subnet_ids          = [var.subnet_id1,var.subnet_id2,var.subnet_id3]
  private_dns_enabled = false
  service_region      = "(Optional) If specified, the VPC endpoint will connect to the service in the provided region. Define it for multi-regional PrivateLink connections."
}
```

After creating the VPC Endpoint, make a note of the `Endpoint ID` value; you'll need it for an upcoming step.

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

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

You need to point "DNS name", taken from [Obtain Endpoint "Service name" ](#obtain-endpoint-service-info) step, to AWS Endpoint network interfaces. This ensures that services/components within your VPC/Network can resolve it properly.

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

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

To add, please navigate to the ClickHouse Cloud console, open the service that you would like to connect via PrivateLink then navigate to **Settings**. Click **Set up private endpoint** to open private endpoints settings. Enter the `Endpoint ID` obtained from the [Create AWS Endpoint](#create-aws-endpoint) step. Click "Create endpoint".

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

<Image img="https://mintcdn.com/private-7c7dfe99-detect-table-modification/m2_tVxhtEg5OHgtu/images/cloud/security/aws-privatelink-pe-filters.webp?fit=max&auto=format&n=m2_tVxhtEg5OHgtu&q=85&s=9e4316dcfd18e4852b7fa9cf7d723208" size="md" alt="Private Endpoints Filter" border width="1555" height="748" data-path="images/cloud/security/aws-privatelink-pe-filters.webp" />

To remove please navigate to the ClickHouse Cloud console, find the service, then navigate to **Settings** of the service, find endpoint you would like to remove.Remove it from the list of endpoints.

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

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

Set the `ENDPOINT_ID` environment variable using data from [Create AWS Endpoint](#create-aws-endpoint) step.

Set the following environment variables before running any commands:

```bash theme={null}
REGION=<Your region code using the AWS format, for example: us-west-2>
PROVIDER=aws
KEY_ID=<Your ClickHouse key ID>
KEY_SECRET=<Your ClickHouse key secret>
ORG_ID=<Your ClickHouse organization ID>
SERVICE_NAME=<Your ClickHouse service name>
```

To add an endpoint ID to an allow-list:

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

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
```

To remove an endpoint ID from an allow-list:

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

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
```

<h3 id="accessing-an-instance-using-privatelink">
  Accessing an instance using PrivateLink
</h3>

Each service with Private Link enabled has a public and private endpoint. In order to connect using Private Link, you need to use a private endpoint which will be `privateDnsHostname`<sup>API</sup> or `DNS Name`<sup>console</sup> taken from [Obtain Endpoint "Service name"](#obtain-endpoint-service-info).

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

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

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-detect-table-modification/m2_tVxhtEg5OHgtu/images/cloud/security/aws-privatelink-pe-dns-name.webp?fit=max&auto=format&n=m2_tVxhtEg5OHgtu&q=85&s=ecadf155e3f4d85bfa4dd354c107b4ae" size="md" alt="Private Endpoint DNS Name" border width="1551" height="740" data-path="images/cloud/security/aws-privatelink-pe-dns-name.webp" />

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

Set the following environment variables before running any commands:

```bash theme={null}
KEY_ID=<Your ClickHouse key ID>
KEY_SECRET=<Your ClickHouse key secret>
ORG_ID=<Your ClickHouse organization ID>
INSTANCE_ID=<Your ClickHouse service name>
```

You can retrieve `INSTANCE_ID` from [step](#option-2-api).

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

This should output something like:

```result theme={null}
{
  "endpointServiceId": "com.amazonaws.vpce.us-west-2.vpce-svc-xxxxxxxxxxxxxxxxx",
  "privateDnsHostname": "xxxxxxxxxx.us-west-2.vpce.aws.clickhouse.cloud"
}
```

In this example connection via value of `privateDnsHostname` host name will be routed to PrivateLink, but connection via `endpointServiceId` hostname will be routed over the Internet.

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

<h3 id="multiple-privatelinks-in-one-region">
  Multiple PrivateLinks in one region
</h3>

In most cases, you only need to create a single endpoint service for each VPC. This endpoint can route requests from the VPC to multiple ClickHouse Cloud services.
Please refer [here](#considerations)

<h3 id="connection-to-private-endpoint-timed-out">
  Connection to private endpoint timed out
</h3>

* Please attach security group to VPC Endpoint.
* Please verify `inbound` rules on security group attached to Endpoint and allow ClickHouse ports.
* Please verify `outbound` rules on security group attached to VM which is used to connectivity test and allow connections to ClickHouse ports.

<h3 id="private-hostname-not-found-address-of-host">
  Private Hostname: Not found address of host
</h3>

* Please check your DNS configuration

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

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

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

Set the following environment variables before running any commands:

```bash theme={null}
KEY_ID=<Key ID>
KEY_SECRET=<Key secret>
ORG_ID=<please set ClickHouse organization ID>
INSTANCE_ID=<Instance ID>
```

You can retrieve `INSTANCE_ID` from [step](#option-2-api).

```shell 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
```

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

According to the [AWS PrivateLink documentation](https://docs.aws.amazon.com/whitepapers/latest/building-scalable-secure-multi-vpc-network-infrastructure/aws-privatelink.html):

> Use AWS PrivateLink when you have a client/server set up where you want to allow one or more consumer VPCs unidirectional access to a specific service or set of instances in the service provider VPC. Only the clients in the consumer VPC can initiate a connection to the service in the service provider VPC.

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