---
title: Add an infrastructure application · Cloudflare Zero Trust docs
description: Access for Infrastructure allows you to have granular control over how users access individual servers, clusters, or databases. By adding an infrastructure application to Cloudflare Access, you can configure how users authenticate to the resource as well as control and authorize the ports, protocols, and usernames that they can connect with. Access and command logs ensure regulatory compliance and allow for auditing of user activity in case of a security breach.
lastUpdated: 2025-03-31T21:46:42.000Z
source_url:
  html: https://patricia-pcx17119-l7-overrides.preview.developers.cloudflare.com/cloudflare-one/applications/non-http/infrastructure-apps/index.md
  md: https://patricia-pcx17119-l7-overrides.preview.developers.cloudflare.com/cloudflare-one/applications/non-http/infrastructure-apps/
---

Access for Infrastructure allows you to have granular control over how users access individual servers, clusters, or databases. By adding an infrastructure application to Cloudflare Access, you can configure how users authenticate to the resource as well as control and authorize the ports, protocols, and usernames that they can connect with. Access and command logs ensure regulatory compliance and allow for auditing of user activity in case of a security breach.

Note

Access for Infrastructure currently only supports [SSH](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/). To connect using other protocols, [add a self-hosted private application](https://developers.cloudflare.com/cloudflare-one/applications/non-http/self-hosted-private-app/). For browser-based SSH, RDP, or VNC, refer to [browser-rendered terminal](https://developers.cloudflare.com/cloudflare-one/applications/non-http/browser-rendering/).

## Prerequisites

* [Connect your infrastructure](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/private-net/) to Cloudflare using `cloudflared` or WARP Connector.
* [Deploy the WARP client](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/deployment/) on user devices in Gateway with WARP mode.

## 1. Add a target

A target represents a single resource in your infrastructure (such as a server, Kubernetes cluster, database, or container) that users will connect to through Cloudflare.

Targets are protocol-agnostic, meaning that you do not need to define a new target for each protocol that runs on the server. To create a new target:

* Dashboard

  1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Targets**.
  2. Select **Add a target**.
  3. In **Target hostname**, enter a user-friendly name for the target resource. We recommend using the server hostname, for example `production-server`. The hostname does not need to be unique and can be reused for multiple targets. Hostnames are used to define the subset of targets included in an infrastructure application and are not used in DNS address resolution.
  4. In **IP addresses**, enter the IPv4 and/or IPv6 address of the target resource. The dropdown menu will not populate until you type in the full IP address.

  Note

  If the target IP does not appear in the dropdown, go to **Networks** > **Routes** and confirm that the IP routes through Cloudflare Tunnel.

  1. In the dropdown menu, select the IP address and [virtual network](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks/) where the resource is located. This IP address and virtual network pairing is now assigned to this target and cannot be reused in another target by design.
  2. Select **Add target**.

* API

  1. [Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with the following permissions:

     | Type | Item | Permission |
     | - | - | - |
     | Account | Zero Trust | Edit |

  2. Make a `POST` request to the [Infrastructure Access Targets](https://developers.cloudflare.com/api/resources/zero_trust/subresources/access/subresources/infrastructure/subresources/targets/methods/create/) endpoint:

     ```sh
     curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/infrastructure/targets \
     --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
     --data '{
       "hostname": "infra-access-target",
       "ip": {
         "ipv4": {
           "ip_addr": "187.26.29.249",
           "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55"
         },
         "ipv6": {
           "ip_addr": "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0",
           "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55"
         }
       }
     }'
     ```

* Terraform

  Provider versions

  The following example requires Cloudflare provider version `>=4.45.0`.

  1. Add the following permission to your [`cloudflare_api_token`](https://registry.terraform.io/providers/cloudflare/cloudflare/4.45.0/docs/resources/api_token):

     * `Zero Trust Write`

  2. Configure the [`cloudflare_zero_trust_infrastructure_access_target`](https://registry.terraform.io/providers/cloudflare/cloudflare/4.45.0/docs/resources/zero_trust_infrastructure_access_target) resource:

     ```tf
     resource "cloudflare_zero_trust_infrastructure_access_target" "infra-ssh-target" {
       account_id = var.cloudflare_account_id
         hostname   = "infra-access-target"
         ip = {
           ipv4 = {
             ip_addr = "187.26.29.249"
             virtual_network_id = "c77b744e-acc8-428f-9257-6878c046ed55"
           }
           ipv6 = {
             ip_addr = "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0"
             virtual_network_id = "c77b744e-acc8-428f-9257-6878c046ed55"
           }
         }
     }
     ```

Next, create an Access application to secure the target.

## 2. Add an infrastructure application

* Dashboard

  1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Access** > **Applications**.

  2. Select **Add an application**.

  3. Select **Infrastructure**.

  4. Enter any name for the application.

  5. In **Target criteria**, select the target hostname(s) that will represent the application. The application definition will apply to all targets that share the selected hostname, including any targets added in the future.

  6. Enter the **Protocol** and **Port** that will be used to connect to the server.

  7. (Optional) If a protocol runs on more than one port, select **Add new target criteria** and reconfigure the same target hostname and protocol with a different port number.

     Note

     Access for Infrastructure only supports assigning one protocol per port. You can reuse a port/protocol pairing across infrastructure applications, but the port cannot be reassigned to another protocol.

  8. Select **Next**.

  9. To secure your targets, configure a policy that defines who can connect and how they can connect:

     1. Enter any name for your policy.

     2. Create a rule that matches the users who are allowed to reach the targets. For more information, refer to [Access policies](https://developers.cloudflare.com/cloudflare-one/policies/access/) and review the list of [infrastructure policy selectors](https://developers.cloudflare.com/cloudflare-one/applications/non-http/infrastructure-apps/#infrastructure-policy-selectors).

     3. In **Connection context**, configure the following settings:

        * **SSH user**: Enter the UNIX usernames that users can log in as (for example, `root` or `ec2-user`).
        * **Allow users to log in as their email alias**: (Optional) When selected, users who match your policy definition will be able to access the target using their lowercased email address prefix. For example, `Jdoe@company.com` could log in as `jdoe`.

        Note

        Cloudflare will not create new users on the target. UNIX users must already be present on the server.

  10. Select **Add application**.

* API

  1. [Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with the following permissions:

     | Type | Item | Permission |
     | - | - | - |
     | Account | Access: Apps & Policies | Edit |

  2. Make a `POST` request to the [Access applications](https://developers.cloudflare.com/api/resources/zero_trust/subresources/access/subresources/applications/methods/create/) endpoint:

     ```sh
     curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps \
     --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
     --header "Content-Type: application/json" \
     --data '{
       "name": "Example infrastructure app",
       "type": "infrastructure",
       "target_criteria": [
         {
           "target_attributes": {
             "hostname": [
               "infra-access-target"
             ]
           },
           "port": 22,
           "protocol": "SSH"
         }
       ],
       "policies": [
         {
           "name": "Allow a specific email",
           "decision": "allow",
           "include": [
             {
               "email": {
                 "email": "jdoe@company.com"
               }
             }
           ],
           "connection_rules": {
             "ssh": {
               "usernames": [
                 "root",
                 "ec2-user"
               ]
             }
           }
         }
       ]
     }'
     ```

* Terraform (v4)

  Provider versions

  The following example requires Cloudflare provider version `>=4.45.0`.

  1. Add the following permission to your [`cloudflare_api_token`](https://registry.terraform.io/providers/cloudflare/cloudflare/4.45.0/docs/resources/api_token):

     * `Access: Apps and Policies Write`

  2. Use the [`cloudflare_zero_trust_access_application`](https://registry.terraform.io/providers/cloudflare/cloudflare/4.45.0/docs/resources/zero_trust_access_application) resource to create an infrastructure application:

     ```tf
     resource "cloudflare_zero_trust_access_application" "infra-app" {
       account_id = var.cloudflare_account_id
       name       = "Example infrastructure app"
       type       = "infrastructure"


       target_criteria {
         port     = 22
         protocol = "SSH"
         target_attributes {
           name = "hostname"
           values = ["infra-access-target"]
         }
       }
     }
     ```

  3. Use the [`cloudflare_zero_trust_access_policy`](https://registry.terraform.io/providers/cloudflare/cloudflare/4.45.0/docs/resources/zero_trust_access_policy) resource to add an infrastructure policy to the application:

     ```tf
     resource "cloudflare_zero_trust_access_policy" "infra-app-policy" {
       application_id = cloudflare_zero_trust_access_application.infra-app.id
       account_id = var.cloudflare_account_id
       name       = "Allow a specific email"
       decision   = "allow"
       precedence = 1


       include {
         email = ["jdoe@company.com"]
       }


       connection_rules {
         ssh {
           usernames = ["root", "ec2-user"]
         }
       }
     }
     ```

The targets in this application are now secured by your infrastructure policies.

Note

Gateway [network policies](https://developers.cloudflare.com/cloudflare-one/policies/gateway/network-policies/) take precedence over infrastructure policies. For example, if you block port `22` for all users in Gateway, then no one can SSH over port `22` to your targets.

## 3. Configure the server

Certain protocols require configuring the server to trust connections through Access for Infrastructure. For more information, refer to the protocol-specific tutorial:

* [SSH](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/#6-configure-ssh-server)

## 4. Connect as a user

Users connect to the target's IP address using their preferred client software. The user must be logged into WARP on their device, but no other system configuration is required. You can optionally configure a [private DNS resolver](https://developers.cloudflare.com/cloudflare-one/policies/gateway/resolver-policies/) to allow connections to the target's private hostname.

### Connect to different VNET

To connect to targets that are in different VNETS, users will need to [switch their connected virtual network](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks/#connect-to-a-virtual-network) in the WARP client.

Note

If a user is connected to a target in VNET-A and needs to connect to a target in VNET-B, switching their VNET will not break any existing connections to targets within VNET-A. At present, connections are maintained between VNETs.

### Display available targets

Users can use `warp-cli` to display a list of targets they can access. On the WARP device, open a terminal and run the following command:

```sh
warp-cli target list
```

```sh
╭──────────────────────────────────────┬──────────┬───────┬───────────────────────┬──────────────────────┬────────────╮
│ Target ID                            │ Protocol │ Port  │ Attributes            │ IP (Virtual Network) │ Usernames  │
├──────────────────────────────────────┼──────────┼───────┼───────────────────────┼──────────────────────┼────────────┤
│ 0193f22a-9df3-78e3-b5bb-7ab631903306 │ SSH      │ 22    │ hostname: do-target   │ 10.116.0.3 (a1net)   │ alice      │
├──────────────────────────────────────┼──────────┼───────┼───────────────────────┼──────────────────────┼────────────┤
│ 0193f22a-9df3-78e3-b5bb-7ab631903306 │ SSH      │ 23    │ hostname: do-target   │ 10.116.0.3 (a1net)   │ root       │
├──────────────────────────────────────┼──────────┼───────┼───────────────────────┼──────────────────────┼────────────┤
│ 01943cff-6130-7989-8bff-cbc02b59a2b1 │ SSH      │ 80    │ hostname: az-target   │ 172.16.0.0 (b1net)   │ alice, bob │
╰──────────────────────────────────────┴──────────┴───────┴───────────────────────┴──────────────────────┴────────────╯
```

You can optionally add flags to filter the output. For example:

```sh
warp-cli target list --attribute hostname=do-target --username root
```

To view all available filters, type `warp-cli target list --help`.

## Revoke a user's session

To revoke a user's access to all infrastructure targets, you can either [revoke the user from Zero Trust](https://developers.cloudflare.com/cloudflare-one/identity/users/session-management/#per-user) or revoke their device. Cloudflare does not currently support revoking a user's session for a specific target.

## Infrastructure policy selectors

The following [Access policy selectors](https://developers.cloudflare.com/cloudflare-one/policies/access/#selectors) are available for securing infrastructure applications:

* Email
* Emails ending in
* SAML group
* Country
* Authentication method
* Device posture
* Entra group, GitHub organization, Google Workspace group, Okta group

## Modify order of precedence in Gateway

By default, Cloudflare will evaluate Access infrastructure application policies after evaluating all Gateway network policies. To evaluate Access infrastructure applications before or after specific Gateway policies, create the following [Gateway network policy](https://developers.cloudflare.com/cloudflare-one/policies/gateway/network-policies/):

| Selector | Operator | Value | Action |
| - | - | - | - |
| Access Infrastructure Target | is | *Present* | Allow |

You can move this policy in the Gateway policy builder to change its [order of precedence](https://developers.cloudflare.com/cloudflare-one/policies/gateway/order-of-enforcement/#order-of-precedence).

Note

Users must pass the policies in your Access application before they are granted access. The Gateway Allow policy is strictly for routing and connectivity purposes.
