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

# Gateway deployment

> Complete guide to deploying Infisical Gateways including network configuration and firewall requirements

Infisical Gateways run inside your network and let Infisical reach systems that aren't exposed to the internet, such as a database in a private subnet or an internal API.
This guide covers everything you need to deploy and configure Infisical Gateways.

> [!TIP]
>
> For a complete Helm chart reference for Kubernetes deployments, see the [Gateway Helm chart documentation](https://infisical.com/docs/self-hosting/helm-charts/gateway.md).

## Choose a connection mode

There are two ways to connect a Gateway, and your network usually decides which one you can use:

* **On Infisical Cloud?** Use relay mode. Cloud runs outside your network and has no route into it, so there's no address it could dial.
* **Self-hosted, and you can open an inbound port on the Gateway host?** Use direct listen. It's the simpler setup, with no relay in the path.
* **Self-hosted, but the Gateway sits behind NAT or a firewall you can't change?** Use relay mode.

| | Direct listen | Relay |
| - | - | - |
| Firewall change | Inbound port open to the Infisical host | None, outbound only |
| Relay to run | None | Managed on Cloud (US/EU), otherwise your own |
| Stable Gateway address | Required | Not needed |
| Infisical Cloud | Not available | Yes |
| PAM CLI from outside the network | No | Yes |

The difference underneath is which side opens the connection, and that's what drives every row above.

You can also run both at once. See [Running both modes](#running-both-modes).

For the ports, certificates, and traffic flow behind each mode, see [Network architecture](https://infisical.com/docs/documentation/platform/gateways/network-architecture.md).

## Host requirements

| Workload | Minimum |
| - | - |
| General use | 2 vCPU, 1 GB memory |
| PAM | 4 vCPU, 8 GB memory |

General use is the gateway acting as a network path to a private resource, such as a database reached through an app connection or a dynamic secret, a secret rotation target, or an ADCS or HSM server. For PAM, the gateway runs the session protocols and records the sessions, so its CPU, memory, and disk use grow with the number of sessions open at once.

## Deployment steps

**1. Set up a relay server (relay mode only)**

Skip this step if you're using direct listen.

For relay mode, a relay server has to be running and reachable before you deploy any gateways. You have two options:

* **Managed relay (Infisical Cloud, US/EU only):** If you're using Infisical Cloud in the US or EU regions, you can use the provided managed relay.
* **Self-hosted relay:** For all other cases, deploy your own relay server. See the [Relay Deployment Guide](https://infisical.com/docs/documentation/platform/gateways/relay-deployment).

**2. Create the gateway in the UI**

To create the gateway as code instead, see [Terraform](https://infisical.com/docs/documentation/platform/gateways/terraform.md). The rest of this guide still applies, since Terraform manages the gateway record and the host is deployed the same way.

1. Go to **Organization Settings > Networking > Gateways**.
2. Select **Create Gateway**.

   ![Create Gateway button](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/gateways/gateway-create-button.png)
3. Enter a name for the gateway, then select **Create Gateway**.

   ![Create Gateway form](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/gateways/gateway-create-form.png)
4. (Optional) Open the new gateway's detail page and change the method under **Authentication** in the **Details** card. Four methods are supported:
   * **Token** (default): a one-time enrollment token (1h expiry) bootstraps the gateway.
   * **AWS**: the gateway authenticates by signing an `sts:GetCallerIdentity` request with whatever AWS credentials it can resolve on the host (instance role, env vars, shared profile). Configure the allowed principal ARNs and/or account IDs that match your hosts.
   * **GCP**: the gateway authenticates with a token from the GCP metadata server, so no credential has to be distributed to the instance or cluster. Configure the allowed service accounts, and optionally the allowed projects and zones.
   * **Kubernetes**: the gateway authenticates with the projected service account token of the pod it runs in, so no credential has to be distributed to the cluster. Configure the cluster's API server URL and the allowed namespaces and/or service account names.
5. In the **Deployment** card, select **Generate deploy command**. For the AWS, GCP and Kubernetes methods the command is shown without this step.
6. Under **Connection Mode**, select **Direct Listen** or **Relay**.
   * For **Direct Listen**, enter the **Listen Address** that Infisical will dial, as `host:port`.
   * For **Relay**, pick a relay, or leave **Auto Select Relay** so the gateway chooses the healthiest one.
7. Copy the generated CLI command.

**3. Install the Infisical CLI**

Make sure the Infisical CLI is installed on the target machine. See the [CLI Installation Guide](https://infisical.com/docs/cli/install.md) for instructions.

**4. Configure network and firewall**

What you open depends on the connection mode you chose.

**Relay mode.** All connections are outbound, so no inbound ports need to be opened.

| Protocol | Destination | Port | Purpose |
| - | - | - | - |
| TCP | Relay Server IP/Hostname | 2222 | SSH reverse tunnel establishment |
| TCP | Infisical instance host (US/EU, other) | 443 | API communication and certificate requests |

For managed relays, allow outbound traffic to the provided relay server IP/hostname. For self-hosted relays, allow outbound traffic to your own relay server address.

If you're in a corporate environment with strict egress filtering, ensure outbound TCP 2222 to relay servers and outbound HTTPS 443 to Infisical API endpoints are allowed.

**Direct listen mode.** The Gateway accepts inbound connections. On the Gateway host, allow:

* **Inbound** on the port in your listen address, from the Infisical instance host only
* **Outbound TCP 443** to the Infisical instance host

> [!TIP]
>
> For the full connection model, a complete port reference, and firewall details (including self-hosted relays and HTTP forward proxies), see the [Network Architecture](https://infisical.com/docs/documentation/platform/gateways/network-architecture.md) page.

**5. Run the CLI command**

Run the command you copied from the UI on the target machine. This single command enrolls the gateway and starts it immediately.

The examples below are grouped by authentication method. The connection mode is set by two flags, which you can add to any of them:

* `--listen-address=<host:port>` for direct listen, where `host:port` is the address Infisical dials
* `--target-relay-name=<relay-name>` to pin a relay, or omit it to let the gateway pick the healthiest one

Passing both runs the gateway in both modes.

```bash theme={"dark"}
# Direct listen
infisical gateway start my-gateway \
  --listen-address=gateway.internal:8443 \
  --enroll-method=token \
  --token=<enrollment-token> \
  --domain=<your-infisical-domain>

# Both modes
infisical gateway start my-gateway \
  --listen-address=gateway.internal:8443 \
  --target-relay-name=my-relay \
  --enroll-method=token \
  --token=<enrollment-token> \
  --domain=<your-infisical-domain>
```

For Kubernetes, set `gateway.listenAddress` to the address Infisical dials:

```bash theme={"dark"}
helm install infisical-gateway infisical/infisical-gateway \
  --set gateway.name=my-gateway \
  --set gateway.listenAddress=infisical-gateway.default.svc.cluster.local:8443 \
  --set gateway.enrollment.method=token \
  --set gateway.enrollment.token.existingSecretRef=gateway-enrollment-token \
  --set gateway.domain=<your-infisical-domain>
```

> [accordion] Token Auth
>
> A one-time enrollment token (1h expiry) bootstraps the gateway.
>
> > [tab] Linux (Production)
> >
> > ```bash theme={"dark"}
> > sudo infisical gateway systemd install <gateway-name> \
> >   --enroll-method=token \
> >   --token=<enrollment-token> \
> >   --domain=<your-infisical-domain>
> > sudo systemctl start <gateway-name>
> > ```
>
> > [tab] Foreground
> >
> > ```bash theme={"dark"}
> > infisical gateway start <gateway-name> \
> >   --enroll-method=token \
> >   --token=<enrollment-token> \
> >   --domain=<your-infisical-domain>
> > ```
>
> > [tab] Kubernetes (Helm)
> >
> > Install the Infisical Helm chart repository:
> >
> > ```bash theme={"dark"}
> > helm repo add infisical https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/
> > helm repo update
> > ```
> >
> > Create a Kubernetes Secret with your enrollment token:
> >
> > ```bash theme={"dark"}
> > kubectl create secret generic gateway-enrollment-token \
> >   --from-literal=enrollment-token=<enrollment-token>
> > ```
> >
> > Install the gateway:
> >
> > ```bash theme={"dark"}
> > helm install infisical-gateway infisical/infisical-gateway \
> >   --set gateway.name=<gateway-name> \
> >   --set gateway.enrollment.method=token \
> >   --set gateway.enrollment.token.existingSecretRef=gateway-enrollment-token \
> >   --set gateway.domain=<your-infisical-domain>
> > ```
> >
> > > [!NOTE]
> > >
> > > A PersistentVolumeClaim is created by default to store enrollment credentials across pod restarts. The enrollment token is single-use. Without persistent storage, the gateway can't restart after the initial enrollment.
> >
> > You can also pass the token inline (the chart creates the Secret for you):
> >
> > ```bash theme={"dark"}
> > helm install infisical-gateway infisical/infisical-gateway \
> >   --set gateway.name=<gateway-name> \
> >   --set gateway.enrollment.method=token \
> >   --set gateway.enrollment.token.value=<enrollment-token> \
> >   --set gateway.domain=<your-infisical-domain>
> > ```

> [accordion] AWS Auth
>
> The host must have AWS credentials whose principal matches your allowlist. The gateway re-authenticates via STS on every start.
>
> > [tab] Linux (Production)
> >
> > ```bash theme={"dark"}
> > sudo infisical gateway systemd install <gateway-name> \
> >   --enroll-method=aws \
> >   --gateway-id=<gateway-id> \
> >   --domain=<your-infisical-domain>
> > sudo systemctl start <gateway-name>
> > ```
>
> > [tab] Foreground
> >
> > ```bash theme={"dark"}
> > infisical gateway start <gateway-name> \
> >   --enroll-method=aws \
> >   --gateway-id=<gateway-id> \
> >   --domain=<your-infisical-domain>
> > ```
>
> > [tab] Kubernetes (Helm)
> >
> > Install the Infisical Helm chart repository:
> >
> > ```bash theme={"dark"}
> > helm repo add infisical https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/
> > helm repo update
> > ```
> >
> > Install the gateway with [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html):
> >
> > ```bash theme={"dark"}
> > helm install infisical-gateway infisical/infisical-gateway \
> >   --set gateway.name=<gateway-name> \
> >   --set gateway.enrollment.method=aws \
> >   --set gateway.enrollment.aws.gatewayId=<gateway-id> \
> >   --set gateway.domain=<your-infisical-domain> \
> >   --set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::<account-id>:role/<role-name>
> > ```
> >
> > > [!NOTE]
> > >
> > > Ensure the IAM role's trust policy allows the Kubernetes service account to assume it, and that the role's ARN or account ID is in the gateway's AWS auth allowlist in the Infisical UI.

> [accordion] GCP Auth
>
> The gateway sends a token proving which GCP service account it runs as, and Infisical verifies that token against Google's signing keys. Nothing has to be copied onto the instance, so this is the method to use when gateway creation is automated on GCP. The gateway re-authenticates on every start.
>
> The token carries the gateway's ID as its audience, so a token minted for one gateway cannot authenticate as another.
>
> Before deploying, configure the GCP auth method on the gateway's detail page:
>
> | Field | Description |
> | - | - |
> | **Type** | **GCP ID Token Auth** reads a token from the instance metadata server, which covers Compute Engine VMs, GKE pods using workload identity, and other surfaces with a metadata server such as Cloud Run, Cloud Functions and App Engine. **GCP IAM Auth** signs one through the IAM Credentials API, for hosts outside Compute Engine. |
> | **Allowed Service Account Emails** | Service account emails that may authenticate as this gateway. |
> | **Allowed Projects** | Optional. Project IDs whose Compute Engine instances may authenticate as this gateway. |
> | **Allowed Zones** | Optional, and only a narrowing of the two above. Zones whose Compute Engine instances may authenticate as this gateway. |
>
> **Allowed Service Account Emails** or **Allowed Projects** is required. Either one names something inside your organization that nobody else can create.
>
> Prefer the service account where you can. Restricting by project alone trusts every instance in that project, including one created by anyone who holds `compute.instances.create` there.
>
> > [!WARNING]
> >
> > **Allowed Zones** is a narrowing on top of one of those. Zone names are a global namespace, so any GCP customer can place an instance in `us-central1-a` and match a zone-only configuration. A config carrying only zones is refused.
>
> > [!WARNING]
> >
> > **Allowed Projects** and **Allowed Zones** are matched against Compute Engine instance details carried inside the token. Only a token from a Compute Engine VM carries them. A GKE workload identity token does not, nor does an IAM service account token, and a login presenting one is refused rather than skipping the check. On GKE, restrict by service account instead.
>
> > [tab] GKE (Helm)
> >
> > Install the Infisical Helm chart repository:
> >
> > ```bash theme={"dark"}
> > helm repo add infisical https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/
> > helm repo update
> > ```
> >
> > Install the gateway with [Workload Identity Federation](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity):
> >
> > ```bash theme={"dark"}
> > helm install infisical-gateway infisical/infisical-gateway \
> >   --namespace infisical-gateway --create-namespace \
> >   --set gateway.name=<gateway-name> \
> >   --set gateway.enrollment.method=gcp \
> >   --set gateway.enrollment.gcp.gatewayId=<gateway-id> \
> >   --set gateway.domain=<your-infisical-domain> \
> >   --set serviceAccount.annotations."iam\.gke\.io/gcp-service-account"=<gsa-name>@<project-id>.iam.gserviceaccount.com
> > ```
> >
> > > [!NOTE]
> > >
> > > The Google service account in that annotation is the one Infisical sees, so put its email in the gateway's **Allowed Service Account Emails**. Its IAM policy also needs a `roles/iam.workloadIdentityUser` binding for the Kubernetes service account the chart creates.
>
> > [tab] Compute Engine (Production)
> >
> > ```bash theme={"dark"}
> > sudo infisical gateway systemd install <gateway-name> \
> >   --enroll-method=gcp \
> >   --gateway-id=<gateway-id> \
> >   --domain=<your-infisical-domain>
> > sudo systemctl start <gateway-name>
> > ```
>
> > [tab] Foreground
> >
> > ```bash theme={"dark"}
> > infisical gateway start <gateway-name> \
> >   --enroll-method=gcp \
> >   --gateway-id=<gateway-id> \
> >   --domain=<your-infisical-domain>
> > ```
> >
> > Add `--gcp-auth-type=iam` to sign the token through the IAM Credentials API instead of reading it from the metadata server. That path needs the IAM Service Account Credentials API enabled and `roles/iam.serviceAccountTokenCreator` on the service account being signed as. On a Compute Engine instance it also needs the `cloud-platform` scope, because the default scopes omit `iamcredentials`. Point `--service-account-key-file-path` at a key file when the host has no credentials of its own.

> [accordion] Kubernetes Auth
>
> The gateway sends the projected service account token of its own pod, and Infisical verifies it against your cluster's TokenReview API. Nothing has to be copied into the cluster, so this is the method to use when gateway creation is automated. The gateway re-authenticates on every start.
>
> Before deploying, configure the Kubernetes auth method on the gateway's detail page:
>
> | Field | Description |
> | - | - |
> | **Gateway** | Optional. Routes the check through an existing gateway or gateway pool instead of Infisical calling the API server directly. Use this when the API server has no address Infisical can reach. |
> | **Review Mode** | Shown once a proxy is selected. See the private cluster section below. |
> | **Kubernetes Host** | The cluster API server URL, reachable from Infisical (for example `https://my-cluster.example.com:6443`). Not required when Review Mode is Gateway as Reviewer. |
> | **Allowed Namespaces** | Namespaces whose service accounts may authenticate as this gateway. Supports `*` wildcards. |
> | **Allowed Service Account Names** | Service account names that may authenticate as this gateway. Supports `*` wildcards. |
> | **Allowed Audience** | Optional. The audience the token must carry. |
> | **CA Certificate** | The CA that issued the API server's certificate. Needed unless that certificate is already trusted by the public trust store, which for a cluster CA it won't be. |
> | **Token Reviewer JWT** | Optional. A token with the `system:auth-delegator` ClusterRole. Leave empty to let the gateway's own service account review its token, which the Helm chart configures by default. |
>
> At least one of **Allowed Namespaces** or **Allowed Service Account Names** must be set, so that not every pod in the cluster can enroll as the gateway.
>
> ### Clusters with a private API server
>
> By default Infisical calls your API server directly, which requires an address it can reach. If your API server is private, select a gateway or gateway pool under **Gateway** and the check is tunnelled through it instead. Two modes are available:
>
> | Review Mode | Who performs the check | Requires |
> | - | - | - |
> | **Gateway as Reviewer** | The selected gateway, using its own service account | That gateway runs as a pod in the same cluster. No host or reviewer token needed. |
> | **Manual Token Reviewer JWT (API)** | Infisical, tunnelling through the gateway | A Kubernetes host and a reviewer token. Works from any gateway that can reach the API server, including one on a VM in the same network. |
>
> A gateway pool can only be used with **Manual Token Reviewer JWT (API)**, where any healthy member performs the check and one gateway going offline doesn't stop the others from authenticating. **Gateway as Reviewer** requires a specific gateway, because in that mode the selected gateway decides the outcome and pool membership can change after the config is saved.
>
> > [!WARNING]
> >
> > A gateway can't review its own token. The proxy runs over the gateway's own tunnel, which only exists once it has already authenticated, so the reviewer must be a different gateway that is already enrolled and connected.
> >
> > This means the **first** gateway in a private cluster can't use Kubernetes auth. Enroll it with an enrollment token, AWS auth or GCP auth, then point later gateways at it. Deleting a gateway that other gateways use as their reviewer is refused until they're pointed elsewhere.
>
> > [tab] Kubernetes (Helm)
> >
> > Install the Infisical Helm chart repository:
> >
> > ```bash theme={"dark"}
> > helm repo add infisical https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/
> > helm repo update
> > ```
> >
> > Install the gateway:
> >
> > ```bash theme={"dark"}
> > helm install infisical-gateway infisical/infisical-gateway \
> >   --namespace infisical-gateway --create-namespace \
> >   --set gateway.name=<gateway-name> \
> >   --set gateway.enrollment.method=kubernetes \
> >   --set gateway.enrollment.kubernetes.gatewayId=<gateway-id> \
> >   --set gateway.domain=<your-infisical-domain>
> > ```
> >
> > > [!NOTE]
> > >
> > > The chart binds the gateway's service account to the `system:auth-delegator` ClusterRole by default, which is what lets its own token act as the token reviewer. Set `serviceAccount.createAsAuthDelegator=false` only if you configure a separate **Token Reviewer JWT** on the gateway instead.
> >
> > Make sure the release namespace and service account name match the allowlists you configured. With the command above, that is namespace `infisical-gateway` and service account `infisical-gateway`.
>
> > [tab] Other in-cluster deployment
> >
> > If you deploy the gateway container yourself rather than through the chart, run it with:
> >
> > ```bash theme={"dark"}
> > infisical gateway start <gateway-name> \
> >   --enroll-method=kubernetes \
> >   --gateway-id=<gateway-id> \
> >   --domain=<your-infisical-domain>
> > ```
> >
> > The pod needs its service account token automounted (the default), and either the service account must hold the `system:auth-delegator` ClusterRole or a separate **Token Reviewer JWT** must be configured on the gateway.
>
> > [!WARNING]
> >
> > Infisical must be able to reach the cluster's API server to review the token. For a cluster with no publicly reachable API server, use Token, AWS or GCP auth instead. On GKE, GCP auth needs no inbound path at all.

> [!WARNING]
>
> The systemd install command requires Linux with root/sudo privileges.

> [!NOTE]
>
> Token-method enrollment tokens are single-use and expire after 1 hour. If the token expires before deployment, select **Generate deploy command** again on the detail page to generate a new one.

> [!NOTE]
>
> You can safely re-run the same command to restart the gateway. The CLI detects the token has already been used locally and skips enrollment automatically.

**6. Verify your gateway deployment**

After deployment, verify your gateway is working:

1. **Check logs** for the "Gateway started successfully" message. In direct listen mode you'll also see "Direct gateway listener started" with the listen address it's advertising and the port it bound.
2. **Verify registration** in the Infisical UI. Go to **Networking > Gateways** and confirm the gateway shows a **Healthy** status. A gateway running both modes stays healthy while either one works.
3. **Test connectivity** by creating a resource that uses the gateway to access a private service.

### Managing a gateway

From the gateway's detail page (select the gateway row in the list):

* **Generate deploy command**: Generates a fresh enrollment token (token method) or re-displays the start command for the AWS, GCP and Kubernetes methods. Selecting this on a token-method gateway doesn't disconnect the running gateway; the next login with the new token rotates credentials atomically.
* **Edit auth method**: Switch between Token, AWS, GCP, and Kubernetes, or update the allowlists of the current method. Existing gateways keep their JWT until they restart and re-authenticate.
* **Options → Revoke Access** — Disconnects the running gateway and invalidates outstanding enrollment tokens. The gateway must re-authenticate to reconnect. Gated by the dedicated `revoke-gateway-access` permission, separate from `edit-gateways`.
* **Options → Delete Gateway** — Permanently removes the gateway; Infisical refuses the delete while an app connection is assigned directly to it and names those connections. This guard doesn't cover connections using a gateway pool.

To migrate a gateway to a different host with zero downtime: select **Generate deploy command** to generate a fresh token, run it on the new host, and the new login will rotate credentials away from the old host.

## Running both modes

A Gateway can run both modes at once. Pass `--target-relay-name` and `--listen-address` together, and Infisical uses the listen address first, falling back to the relay when that address stops answering. Health checks probe each mode separately, so the Gateway stays healthy while either one works.

A Gateway declares its transports every time it registers, so its mode is set by which flags it starts with:

| Flags | Mode |
| - | - |
| `--target-relay-name=my-relay` | Relay only |
| `--listen-address=gateway.internal:8443` | Direct only |
| `--target-relay-name=my-relay --listen-address=gateway.internal:8443` | Both |

Running both permanently only helps clients that can reach the listen address. PAM CLI sessions dial the Gateway from the user's own machine, so a user outside the network waits for that attempt to time out before the session falls back to the relay. If most of your CLI users are outside the network, relay mode alone serves them better.

## Frequently asked questions

> [accordion] Do I need to open any inbound ports on my firewall?
>
> That depends on the connection mode.
>
> In relay mode, no. The gateway only makes outbound connections:
>
> * **Outbound SSH** to relay servers on port 2222
> * **Outbound HTTPS** to Infisical API endpoints on port 443
> * **SSH reverse tunnels** carry all return traffic, so nothing needs to be configured for it
>
> In direct listen mode, one inbound port has to be open: the port in your listen address, reachable from the Infisical instance host. Scope the rule to that host so the port isn't open to anything else.

> [accordion] Can I switch a gateway between relay and direct listen?
>
> Yes. Open the gateway's detail page, choose the mode you want under **Connection Mode**, and re-run the generated command on the host. The gateway re-registers with the new mode and is issued the certificate it needs for it.
>
> The new mode replaces the old one. To switch without an outage, start the Gateway with both flags first. If the listen address is wrong, the relay keeps serving and the Gateway page shows the direct path as unreachable. Once direct is healthy, drop `--target-relay-name`.

> [accordion] Why does my direct listen gateway fail to register?
>
> The listen address has to be `host:port`, with a port in the range 1 to 65535. Use `gateway.internal:8443`, not `https://gateway.internal` or `gateway.internal`: an address is rejected if it has no port, or if it carries a scheme or a path.
>
> Direct listen is also unavailable on Infisical Cloud, which runs outside your network and has no route into it. On Cloud, use relay mode.

> [accordion] Do PAM sessions work in direct listen mode?
>
> Only from a machine that can reach the gateway's listen address. The CLI connects to the gateway from the user's own machine rather than through Infisical, so a laptop outside the network can't reach a gateway listening on an internal address. Give those users a VPN into the network, or run a relay on the gateway alongside direct listen.
>
> Browser-based PAM access works in either mode, because the platform brokers that connection.

> [accordion] How do I test network connectivity from the gateway?
>
> Test relay connectivity and outbound API access from the gateway:
>
> 1. Test SSH port to relay:
>
> ```bash theme={"dark"}
> nc -zv <relay-ip> 2222
> ```
>
> 2. Test outbound API access (replace with your Infisical domain if different):
>
> ```bash theme={"dark"}
> curl -I https://app.infisical.com
> ```

> [accordion] How do I troubleshoot relay connectivity issues?
>
> If the gateway can't connect to the relay:
>
> 1. Verify the relay server is running and accessible
> 2. Check firewall rules allow outbound connections on port 2222
> 3. Confirm the relay name matches exactly
> 4. Test SSH port to relay:
>
> ```bash theme={"dark"}
> nc -zv <relay-ip> 2222
> ```

> [accordion] How do I troubleshoot direct listen connectivity issues?
>
> The gateway registers and looks healthy only once Infisical can reach it, so start from the Infisical host:
>
> 1. Confirm the gateway logged "Direct gateway listener started" and check the port it bound
> 2. From the Infisical instance host, test the listen address:
>
> ```bash theme={"dark"}
> nc -zv gateway.internal 8443
> ```
>
> 3. Check the inbound firewall rule allows the Infisical instance host on that port
> 4. Confirm the listen address resolves from the Infisical host, not just from your own machine
>
> If the gateway binds a different local port than the one you advertise, such as behind a load balancer, pass `--bind` to set the local address and keep `--listen-address` as the address Infisical dials.

> [accordion] How do I troubleshoot authentication failures?
>
> For token method: ensure the enrollment token hasn't expired or already been used. Open the gateway's detail page and select **Generate deploy command** to generate a fresh token.
>
> For AWS method: ensure the host has AWS credentials available (instance role, env vars, or shared profile) and the resolved principal/account is in the allowlist on the gateway's detail page.
>
> For Kubernetes method: ensure Infisical can reach the configured Kubernetes host, that the pod's namespace and service account are in the allowlists, and that the reviewer (the gateway's own service account by default) holds the `system:auth-delegator` ClusterRole. The gateway's audit log records the reviewed namespace and service account name for each login, and the reason code for each failure.

> [accordion] Where can I find gateway logs?
>
> Check gateway logs for detailed error information:
>
> * **systemd service:**
>   ```bash theme={"dark"}
>   sudo journalctl -u <gateway-name> -f
>   ```
> * **Local installation:** Logs appear in the terminal where you started the gateway

> [accordion] What happens if my enrollment token expires?
>
> Enrollment tokens expire after 1 hour. If the token expires before deployment, open the gateway's detail page and select **Generate deploy command** to generate a new one.

> [accordion] Where are gateway credentials stored?
>
> For **token-method** gateways, the access token and domain are saved to a config file scoped by gateway name:
>
> * **Running as root/sudo:** `/etc/infisical/gateways/<gateway-name>.conf`
> * **Running as a regular user:** `~/.infisical/gateways/<gateway-name>.conf`
>
> For **AWS-method**, **GCP-method** and **Kubernetes-method** gateways, no JWT is persisted to disk. The gateway re-authenticates on every start, by signing a fresh STS request with the host's AWS credentials, by presenting a GCP identity token, or by presenting the pod's service account token. Only the gateway id and domain are stored locally.
>
> For systemd-based installations, the configuration is at `/etc/infisical/gateways/<gateway-name>.conf`. All config files are created with restricted permissions (0600).

> [accordion] Can I run multiple gateways on the same machine?
>
> Yes. Each gateway stores its credentials in a separate config file scoped by name (e.g., `~/.infisical/gateways/my-gateway.conf`). You can enroll and start multiple gateways in separate terminal sessions using different names.

> [accordion] What happens if there is a network interruption?
>
> The gateway is designed to handle network interruptions gracefully:
>
> * **Automatic reconnection**: The gateway will automatically attempt to reconnect to relay servers if the SSH connection is lost
> * **Transport fallback**: A gateway running both modes falls back to its relay when its listen address stops answering, and returns to direct connections once it recovers
> * **Connection retry logic**: Built-in retry mechanisms handle temporary network outages without manual intervention
> * **Automatic failover**: Gateways configured with automatic relay selection will switch to a different healthy relay if the current one becomes unreachable
> * **Gateway Pools**: If the gateway itself becomes unavailable, a [Gateway Pool](https://infisical.com/docs/documentation/platform/gateways/gateway-pools.md) will automatically route through a healthy member
> * **Persistent SSH tunnels**: SSH connections are automatically re-established when connectivity is restored
> * **Certificate rotation**: The gateway handles certificate renewal automatically during reconnection
> * **Graceful degradation**: The gateway logs connection issues and continues attempting to restore connectivity
>
> No manual intervention is typically required during network interruptions.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.