# Connectivity

> Network connectivity details for using Temporal Cloud

## Private network connectivity for namespaces

Temporal Cloud supports private connectivity to Namespaces via AWS PrivateLink or GCP Private Service Connect, in addition to the default public internet endpoints.

Namespace access is always securely authenticated via [API keys](/cloud/api-keys#overview) or [mTLS](/cloud/certificates), regardless of how you choose to connect.

For information about IP address stability and allowlisting, see [IP addresses](/cloud/connectivity/ip-addresses). If your security team requires allowlisting specific IP addresses for firewall rules, Temporal Cloud also offers a [Stable IPs configuration option](/cloud/connectivity/ip-addresses) that provides non-changing IP addresses for your Namespace endpoint.

### Required steps

Setting up private connectivity is a three-step process — and it's important to understand that **private connectivity** (the network path) and **Connectivity Rules** (Temporal's enforcement layer) are related but separate concepts:

1. **Set up the private connection** from your VPC to the region where your Temporal Namespace is located.
1. **Update your private DNS and/or client configuration** to actually use the private connection. Activating private connectivity does not change your Namespace Endpoint or Regional Endpoint automatically — clients keep resolving the public addresses until you do this step.
1. **(GCP PSC: required. AWS PrivateLink: optional.) Create a Connectivity Rule** for the private connection and attach it to the target Namespace(s). This blocks all access to the Namespace that does not arrive over a configured connection. You can mix private and public rules to also allow internet connectivity.

For steps 1 and 2, follow the guide for your Namespace's cloud provider:
- [AWS PrivateLink](/cloud/connectivity/aws-connectivity) creation and private DNS setup
- [Google Cloud Private Service Connect](/cloud/connectivity/gcp-connectivity) creation and private DNS setup

> **⚠️ Caution:**
> Finish client setup (complete step 2)
>
> After creating a private connection, you must set up private DNS or update the configuration of all clients you want to use the private connection.
>
> We recommend using private DNS.
>
> Without this step, your clients may connect to the Namespace over the internet if they were previously using public connectivity, or they will not be able to connect at all.
>
> If that's not an option for you, refer to [our guide for updating the server and TLS settings on your clients](/cloud/connectivity#update-dns-or-clients-to-use-private-connectivity).
>

For step 3, keep reading for details on [Connectivity Rules](/cloud/connectivity#connectivity-rules).

## Connectivity rules

> **ℹ️ Info:**
> Web UI Connectivity
>
> The Temporal Cloud Web UI is not currently subject to connectivity rule enforcement.
> Even if a namespace is configured with private connectivity rules, the Web UI for that namespace remains accessible over the public internet.
>

### Definition

Connectivity Rules are Temporal Cloud's mechanism for restricting the network paths that can reach a Namespace. They are enforced by Temporal Cloud — they do not create or modify the underlying network connection.

By default, a Namespace has zero Connectivity Rules and is reachable over (1) the public internet and (2) any private connections you've already configured to the region containing the Namespace. Namespace access is always securely authenticated via [API keys](/cloud/api-keys#overview) or [mTLS](/cloud/certificates), regardless of Connectivity Rules.

When you attach one or more Connectivity Rules to a Namespace, Temporal Cloud immediately blocks any traffic that does not match a rule on that Namespace. A Namespace can have multiple Connectivity Rules, and you can mix public and private rules.

Each Connectivity Rule specifies either generic public (internet) access or a specific private connection.

#### When you need a Connectivity Rule

| Provider | Connectivity Rule for private access | Why |
| -------- | ------------------------------------ | --- |
| AWS PrivateLink | **Optional.** Add one only if you want to enforce private-only access (block internet traffic to that Namespace). | AWS PrivateLink connections become usable as soon as the VPC endpoint is `Available`. Adding a Connectivity Rule restricts access; it does not establish it. |
| GCP Private Service Connect | **Required.** The PSC endpoint stays in `Pending` until a matching Connectivity Rule is created. | The Connectivity Rule is what tells Temporal Cloud to accept the PSC connection. |

A public Connectivity Rule has one optional parameter:

- `enable-stable-ips`: When set, Namespaces attached to this rule resolve their Namespace endpoint to a published, fixed set of IP addresses you can allowlist in your firewall. See [Stable IPs](/cloud/connectivity/ip-addresses#stable-ip-addresses) for details.

Only one public Connectivity Rule is allowed per account (see [Permissions and limits](#permissions-and-limits) below). 

> **⚠️ Caution:**
>
> Connectivity Rules cannot be updated in place. If you already have a public Connectivity Rule and want to turn on Stable IPs, you must delete the existing public rule, create a new one with `enable-stable-ips` set, and re-attach it to every Namespace that needs it. Attempting to create a second public rule alongside the existing one returns an error.
>

An AWS PrivateLink (PL) private Connectivity Rule requires:

- `connection-id`: The **VPC endpoint identifier** of the PL connection — the `vpce-…` value from your AWS account, *not* the endpoint service or DNS name (ex: `vpce-00939a7ed9EXAMPLE`).
- `region`: The region of the PL connection, prefixed with `aws-` (ex: `aws-us-east-1`). Must be the same region as the Namespace. Refer to the [Temporal Cloud region list](/cloud/regions) for supported regions.

A GCP Private Service Connect (PSC) private Connectivity Rule requires:

- `connection-id`: The **PSC connection identifier** of the endpoint (ex: `1234567890123456789`). Find it on the endpoint's detail page in the Google Cloud console.
- `region`: The region of the PSC connection, prefixed with `gcp-` (ex: `gcp-us-east1`). Must be the same region as the Namespace. Refer to the [Temporal Cloud region list](/cloud/regions) for supported regions.
- `gcp-project-id`: The identifier of the GCP project where you created the PSC connection (ex: `my-example-project-123`).

Connectivity Rules can be created and managed with [tcld](https://docs.temporal.io/cloud/tcld/), [Terraform](https://github.com/temporalio/terraform-provider-temporalcloud/), the Web UI (under **Connectivity** in your account settings), or the [Cloud Ops API](/ops).

> **💡 Tip:**
> Connectivity Rules give Temporal visibility into your private connections
>
> Without a Connectivity Rule, Temporal Cloud has no record that your PrivateLink or PSC endpoint exists. If you open a support ticket about a private-connectivity issue, having a Connectivity Rule attached to the affected Namespace lets us correlate the connection on our side and is the fastest path to debugging.
>

### Permissions and limits

Only [Account Admins and Account Owners](/cloud/manage-access/roles-and-permissions#account-level-roles) can create and manage connectivity rules. Connectivity rules are visible to Account Developers, Account Admins, and Account Owners.

By default each namespace is limited to 5 private connectivity rules, and each account is limited to 50 private connectivity rules. You can [contact support](/cloud/support#support-ticket) to request a higher limit.

There is only one public rule allowed per account, because it's generic and can be reused for all namespaces that you want to be available on the internet. Trying to create more than one public rule will throw an error.

## Creating a connectivity rule

### Temporal Cloud CLI (tcld)

Create private connectivity rule (AWS):

```bash
tcld connectivity-rule create --connectivity-type private --connection-id "vpce-abcde" --region "aws-us-east-1"
```

Create private connectivity rule (GCP):

```bash
tcld connectivity-rule create --connectivity-type private --connection-id "1234567890" --region "gcp-us-central1" --gcp-project-id "my-project-123"
```

Create public connectivity rule (you only need to do this once ever in your account):

```bash
tcld connectivity-rule create --connectivity-type public
```

Create a public Connectivity Rule with [Stable IPs](/cloud/connectivity/ip-addresses#stable-ip-addresses) enabled:

```bash
tcld connectivity-rule create --connectivity-type public --enable-stable-ips
```

The `cr` alias works the same way:

Private connectivity rule:

```bash
tcld cr create --connectivity-type private --connection-id "vpce-abcde" --region "aws-us-east-1"
```

```bash
tcld cr create --connectivity-type public
```

### Terraform

[Examples in the Terraform repo](https://github.com/temporalio/terraform-provider-temporalcloud/blob/main/examples/resources/temporalcloud_connectivity_rule/resource.tf)

## Attach connectivity rules to a namespace

Be careful! When any connectivity rules are set on a namespace, that namespace is ONLY accessible via the connections defined in those rules. If you remove a connectivity rule that your workers are using, your traffic will be interrupted.

If you already have workers using a namespace, adding both a public rule and any private rules simultaneously can help you avoid unintended loss of access. You can then ensure all workers are using private connections, and then remove the public rule.

### Temporal Cloud CLI (tcld)

Setting the connectivity rules on a namespace:

```bash
tcld namespace set-connectivity-rules --namespace "my-namespace.abc123" --connectivity-rule-ids "rule-id-1" --connectivity-rule-ids "rule-id-2"
```

Or using aliases:

```bash
tcld n scrs -n "my-namespace.abc123" --ids "rule-id-1" --ids "rule-id-2"
```

Connectivity rules are attached as a set, so if rules `rule-a`, `rule-b`, and `rule-c` were attached to a namespace and you wanted to detach `rule-c` only, you'd make one call attaching both `rule-a` and `rule-b`:

```bash
tcld namespace set-connectivity-rules --namespace "my-namespace.abc123 --ids rule-a --ids rule-b
```

Remove all connectivity rules (this will make the namespace public):

```bash
tcld namespace set-connectivity-rules --namespace "my-namespace.abc123" --remove-all
```

### Terraform

[Example in the Terraform repo](https://github.com/temporalio/terraform-provider-temporalcloud/tree/main/examples/resources/temporalcloud_namespace/resource.tf#L113-L128)

## View the connectivity rules for a namespace

You have two ways to view the connectivity rules attached to a particular namespace.

### Get namespace

Connectivity rules are included in the namespace details returned by the `namespace get` command. 

```bash
tcld namespace get -n "my-namespace.abc123"
```

### List connectivity rules by namespace

To see only the connectivity rules for a specific namespace (without other namespace details), use the `connectivity-rule list` command with a namespace argument.

```bash
tcld connectivity-rule list -n "my-namespace.abc123"
```

## Update DNS or clients to use private connectivity

We strongly recommend using private DNS instead of updating client server and TLS settings:

- [How to set up private DNS in AWS](/cloud/connectivity/aws-connectivity#configuring-private-dns-for-aws-privatelink)
- [How to set up private DNS in GCP](/cloud/connectivity/gcp-connectivity#configuring-private-dns-for-gcp-private-service-connect)

If you are unable to configure private DNS, you must update two settings in your Temporal clients:

1. Set the endpoint server address to the PrivateLink or Private Service Connect endpoint (e.g. `vpce-0123456789abcdef-abc.us-east-1.vpce.amazonaws.com:7233` or `<GCP PSC IP address>:7233`).
2. Set TLS configuration to override the TLS server name (the Namespace Endpoint, e.g., `my-namespace.my-account.tmprl.cloud`).

The TLS server name override depends on your authentication method:

| Authentication | TLS server name to use |
| -------------- | ---------------------- |
| mTLS (single-region Namespace) | The Namespace Endpoint, e.g. `my-namespace.my-account.tmprl.cloud` |
| API key (single-region Namespace) | The regional API endpoint, e.g. `us-east-1.aws.api.temporal.io` or `us-central1.gcp.api.temporal.io` |
| Multi-region Namespace (mTLS or API key) | The active region endpoint, e.g. `aws-us-east-1.region.tmprl.cloud` |

If you authenticate with an API key over PrivateLink/PSC and use the wrong server name, the TLS handshake will fail with errors such as `connection reset by peer` even though `nc` reports the port as open.

Updating these settings depends on the client you're using.

#### temporal CLI
```bash
TEMPORAL_ADDRESS=vpce-0123456789abcdef-abc.us-east-1.vpce.amazonaws.com:7233
TEMPORAL_NAMESPACE=my-namespace.my-account
TEMPORAL_TLS_CERT=<path/to/cert.pem>
TEMPORAL_TLS_KEY=<path/to/cert.key>
TEMPORAL_TLS_SERVER_NAME=my-namespace.my-account.tmprl.cloud

temporal workflow count -n $TEMPORAL_NAMESPACE
```

#### grpcurl
```bash
grpcurl \
    -servername my-namespace.my-account.tmprl.cloud \
    -cert path/to/cert.pem \
    -key path/to/cert.key \
    vpce-0123456789abcdef-abc.us-east-1.vpce.amazonaws.com:7233 \
    temporal.api.workflowservice.v1.WorkflowService/GetSystemInfo
```

#### Temporal SDKs
**Go**

```go
c, err := client.Dial(client.Options{
	HostPort:  "vpce-0123456789abcdef-abc.us-east-1.vpce.amazonaws.com:7233",
	Namespace: "namespace-name.accId",
	ConnectionOptions: client.ConnectionOptions{
		TLS: &tls.Config{
			Certificates: []tls.Certificate{cert},
			ServerName:   "my-namespace.my-account.tmprl.cloud",
		},
	},
})
```

**Java**

```java
WorkflowServiceStubs service =
        WorkflowServiceStubs.newServiceStubs(
            WorkflowServiceStubsOptions.newBuilder()
                .setSslContext(sslContext)
                .setTarget("vpce-0123456789abcdef-abc.us-east-1.vpce.amazonaws.com:7233")
                .setChannelInitializer(
                    c -> c.overrideAuthority("my-namespace.my-account.tmprl.cloud"))
                .build());
```

**TypeScript**

```ts
const connection = await NativeConnection.connect({
  address: "vpce-0123456789abcdef-abc.us-east-1.vpce.amazonaws.com:7233",
  tls: {
    serverNameOverride: "my-namespace.my-account.tmprl.cloud",
    //serverRootCACertificate,
    // See docs for other TLS options
    clientCertPair: {
      crt: fs.readFileSync(clientCertPath),
      key: fs.readFileSync(clientKeyPath),
    },
  },
});
```

**Python**

```python
client_config["tls"] = TLSConfig(
    client_cert=bytes(crt, "utf-8"),
    client_private_key=bytes(key, "utf-8"),
    domain="my-namespace.my-account.tmprl.cloud",
)

client = await Client.connect("vpce-0123456789abcdef-abc.us-east-1.vpce.amazonaws.com:7233")
```

**.NET**

```dotnet
// Create client 
var client = await TemporalClient.ConnectAsync(
  new(ctx.ParseResult.GetValueForOption(targetHostOption)!)
  {
    Namespace = ctx.ParseResult.GetValueForOption (namespaceOption)!,
    // Set TLS options with client certs. Note, more options could 
    // be added here for server CA (i.e. "ServerRootCACert") or SNI 
    // override (i.e. "Domain") for self-hosted environments with 
    // self-signed certificates. 
    Tls = new() 
    {
      ClientCert = 
        await File.ReadAllBytesAsync(ctx.ParseResult.GetValueForOption(clientCertOption) !.FullName), 
      ClientPrivateKey = 
        await File.ReadAllBytesAsync(ctx.ParseResult.GetValueFor0ption(clientKey0ption)!.FullName), Domain = "my-namespace.my-account.tmprl.cloud",
  },
});

// dotnet run --target-host "vpce-0123456789abcdef-abc.us-east-1.vpce.amazonaws.com:7233"
```

To check whether your client has network connectivity to the private endpoint in question, run:
```bash
nc -zv vpce-0123456789abcdef-abc.us-east-1.vpce.amazonaws.com 7233
```

## Control plane connectivity

Using the Temporal Cloud [web UI](/web-ui), [Terraform provider](/cloud/terraform-provider), [`tcld` CLI](/cloud/tcld), or [Cloud Ops APIs](/ops) requires network access to the Temporal Cloud Control Plane. 

### Control plane hostnames

Different hostnames are used for different parts of the service.

- `saas-api.tmprl.cloud` (required for Terraform, tcld, and Cloud Ops APIs) 
- `web.onboarding.tmprl.cloud` (required for Web UI)
- `web.saas-api.tmprl.cloud` (required for Web UI)

### AWS PrivateLink connectivity to Temporal Cloud Control Plane

Temporal Cloud supports [AWS PrivateLink](https://aws.amazon.com/privatelink/) connections to the Control Plane, which allows access from applications running in VPCs that cannot egress to the public internet. Temporal Cloud does **not** support restricting an account so that private connectivity is the sole connectivity method to the Control Plane; the Control Plane is always accessible via public internet.

Control Plane access is always securely authenticated via [API keys](/cloud/api-keys#overview) or JWT tokens, regardless of how you choose to connect.

To set up a PrivateLink connection to the Temporal Cloud Control Plane, follow [these instructions](/cloud/connectivity/aws-connectivity), but use the Control Plane endpoint information below:

| Hostname               | Region      | Control Plane PrivateLink Service Name                    |
| ---------------------- | ----------- | --------------------------------------------------------- |
| `saas-api.tmprl.cloud` | `us-west-2` | `com.amazonaws.vpce.us-west-2.vpce-svc-0c57a5930b6f6be0e` |

The Control Plane PrivateLink endpoint includes a [private DNS name](https://docs.aws.amazon.com/vpc/latest/privatelink/manage-dns-names.html), which lets your clients use the PrivateLink connection without having to set up private DNS or having to override client configuration. To use the DNS name, make sure your VPC has the `Enable DNS hostnames` and `Enable DNS support` options enabled. If you cannot use the DNS name, you can also manually [set up private DNS](/cloud/connectivity/aws-connectivity#configuring-private-dns-for-aws-privatelink) or [override the server and TLS settings on your clients](/cloud/connectivity#update-dns-or-clients-to-use-private-connectivity).

> **⚠️ Caution:**
> Finish client setup to programmatically access Temporal Cloud Control Plane over PrivateLink
>
> For Temporal clients to access the Control Plane over AWS PrivateLink, you must either use the provided DNS name, set up private DNS, or update the client configuration, as described above.
>
> Without this step, your clients may connect to the Temporal Cloud Control Plane over the internet, or they may not connect at all.

#### Extend the Control Plane PrivateLink endpoint to other AWS regions with VPC Peering

The Temporal Cloud Control Plane PrivateLink Service is only exposed in `us-west-2`. To reach the Control Plane privately from another AWS region, set up a us-west-2 VPC with a VPC Endpoint to the Control Plane, then [VPC-Peer](https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html) that VPC to your other-region VPCs.

To set this up:

1. Create a VPC in `us-west-2`.
2. Create the [VPC Endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/concepts.html) to the Control Plane in that us-west-2 VPC, using the service name from the table above. Follow the [standard PrivateLink setup steps](/cloud/connectivity/aws-connectivity), but use the Control Plane service name.
3. Peer the us-west-2 VPC to each VPC in another region that needs Control Plane access. [VPC Peering shares VPC Endpoints](https://docs.aws.amazon.com/vpc/latest/peering/peering-configurations-partial-access.html) across peered VPCs, which gives each peered VPC a private path to the Control Plane.

Peering is per-VPC, so you must peer the us-west-2 VPC to every VPC that needs Control Plane access. There is no limit on how many regions you can extend to using this approach.
