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

# How to connect to a tunnel

To connect a service to a tunnel, configure and run a tunnel agent. You'll need the tunnel ID in the agent configuration.

## Prerequisites

1. [Install and configure](/cli/install) the Nebius AI Cloud CLI.

2. [Get the project ID](/iam/manage-projects#cli-3) and the [tenant ID](/iam/get-tenants#cli), and save them to environment variables:

   ```bash theme={null}
   export PROJECT_ID=<project_ID>
   ```

   ```bash theme={null}
   export TENANT_ID=<tenant_ID>
   ```

3. Get the tunnel ID by listing tunnels in your project:

   ```bash theme={null}
   nebius tunnel list
   ```

   The command uses the project ID from your CLI profile configuration. Copy the ID of the tunnel that you want to connect to and save it to an environment variable:

   ```bash theme={null}
   export TUNNEL_ID=<tunnel_ID>
   ```

## Connecting a service

<Tabs>
  <Tab title="Docker">
    1. Install [Docker Engine](https://docs.docker.com/engine/install/).

    2. Create a service account and save its ID:

       ```bash theme={null}
       export SA_ID=$(nebius iam service-account create \
         --name "tunnel-agent" \
         --parent-id "$PROJECT_ID" \
         --format jsonpath='{.metadata.id}')
       ```

           <Note>
             To grant wider access instead of creating a dedicated group with the `applicationtunnel.agent` role, you can [add the service account to the `editors` group](/iam/service-accounts/manage#granting-editor-access-to-the-service-account).
           </Note>

    3. Create a group for Nebius Tunnels service accounts and save its ID:

       ```bash theme={null}
       export GROUP_ID=$(nebius iam group create \
         --name "tunnel-agents" \
         --parent-id "$TENANT_ID" \
         --format jsonpath='{.metadata.id}')
       ```

    4. Grant the group the `applicationtunnel.agent` role for the tunnel:

       ```bash theme={null}
       nebius iam access-permit create \
         --parent-id "$GROUP_ID" \
         --resource-id "$TUNNEL_ID" \
         --role applicationtunnel.agent
       ```

           <Note>
             To grant access to more tunnels, create the permit on a broader resource: a project or a tenant. A permit on a project applies to all tunnels in that project. A permit on a tenant applies to all tunnels in all projects in the tenant.
           </Note>

    5. Add the service account to the group:

       ```bash theme={null}
       nebius iam group-membership create \
         --parent-id "$GROUP_ID" \
         --member-id "$SA_ID"
       ```

    6. Create a key pair:

       ```bash theme={null}
       openssl genrsa -out ./private_key.pem 4096
       openssl rsa -in ./private_key.pem -pubout -out ./public_key.pem
       ```

    7. Upload the public key and save its ID:

       ```bash theme={null}
       export PUBLIC_KEY_ID=$(nebius iam auth-public-key create \
         --account-service-account-id "$SA_ID" \
         --data "$(cat ./public_key.pem)" \
         --format jsonpath='{.metadata.id}')
       ```

    8. Create `config.yaml` for the agent:

       ```bash theme={null}
       cat > config.yaml <<EOF
       tunnel_id: $TUNNEL_ID

       iam:
         service_account:
           service_account_id: $SA_ID
           public_key_id: $PUBLIC_KEY_ID
           private_key_path: "./private_key.pem"

       services:
         - name: web
           target: localhost:8080
           type: http
       EOF
       ```

       In the agent configuration, `services.name` can contain up to 20 characters and must use only lowercase Latin letters and digits (`[a-z0-9]`). Don't use dashes or dots.

       For multiple services, configure the `services` section like this:

       ```yaml theme={null}
       services:
         - name: api
           target: localhost:8080
           type: http
         - name: grpc
           target: localhost:9090
           type: http
           protocol: h2
         - name: db
           target: localhost:5432
           type: tcp
       ```

    9. Run the agent using a cross-platform Docker image:

       ```bash theme={null}
       docker run -v $PWD:/home/nonroot \
         cr.eu-north1.nebius.cloud/marketplace/docker/nebius-tunnel-agent:latest \
         -config ./config.yaml
       ```

       When the agent connects, it returns the public endpoint for each service. The endpoint format is:

       ```text theme={null}
       <service_name>-<tunnel_masked_ID>.tunnel.applications.<region>.nebius.cloud:443
       ```

       Where:

       * `service_name` is the `services.name` value from the agent configuration.
       * `tunnel_masked_ID` is the mask of the tunnel ID without the `applicationtunnel-` prefix and regional routing code. For example, for `applicationtunnel-<routing_code>abcdef1234`, the tunnel ID mask is `abcdef1234`.
       * `region` is the [region](/overview/regions) of the project where the tunnel was created, for example `eu-north1`.
  </Tab>

  <Tab title="Helm">
    1. [Install Helm](https://helm.sh/docs/intro/install/).

    2. Create a service account and save its ID:

       ```bash theme={null}
       export SA_ID=$(nebius iam service-account create \
         --name "tunnel-agent" \
         --parent-id "$PROJECT_ID" \
         --format jsonpath='{.metadata.id}')
       ```

           <Note>
             To grant wider access instead of creating a dedicated group with the `applicationtunnel.agent` role, you can [add the service account to the `editors` group](/iam/service-accounts/manage#granting-editor-access-to-the-service-account).
           </Note>

    3. Create a group for Nebius Tunnels service accounts and save its ID:

       ```bash theme={null}
       export GROUP_ID=$(nebius iam group create \
         --name "tunnel-agents" \
         --parent-id "$TENANT_ID" \
         --format jsonpath='{.metadata.id}')
       ```

    4. Grant the group the `applicationtunnel.agent` role for the tunnel:

       ```bash theme={null}
       nebius iam access-permit create \
         --parent-id "$GROUP_ID" \
         --resource-id "$TUNNEL_ID" \
         --role applicationtunnel.agent
       ```

           <Note>
             To grant access to more tunnels, create the permit on a broader resource: a project or a tenant. A permit on a project applies to all tunnels in that project. A permit on a tenant applies to all tunnels in all projects in the tenant.
           </Note>

    5. Add the service account to the group:

       ```bash theme={null}
       nebius iam group-membership create \
         --parent-id "$GROUP_ID" \
         --member-id "$SA_ID"
       ```

    6. Create a key pair:

       ```bash theme={null}
       openssl genrsa -out ./private_key.pem 4096
       openssl rsa -in ./private_key.pem -pubout -out ./public_key.pem
       ```

    7. Upload the public key and save its ID:

       ```bash theme={null}
       export PUBLIC_KEY_ID=$(nebius iam auth-public-key create \
         --account-service-account-id "$SA_ID" \
         --data "$(cat ./public_key.pem)" \
         --format jsonpath='{.metadata.id}')
       ```

    8. Create `custom.values.yaml` with the service account credentials and agent config:

       ```yaml theme={null}
       secret:
         data:
           private_key.pem: |
             -----BEGIN PRIVATE KEY-----
             ...
             -----END PRIVATE KEY-----
         items:
           - key: private_key.pem
             path: sa/private_key.pem

       config:
         tunnel_id: <tunnel_ID>
         iam:
           service_account:
             service_account_id: <service_account_ID>
             public_key_id: <authorized_key_ID>
             private_key_path: sa/private_key.pem
         services:
           - name: web
             target: localhost:8080
             type: http
       ```

       In the file, replace `<tunnel_ID>` with the value of `$TUNNEL_ID`, `<service_account_ID>` with the value of `$SA_ID`, `<authorized_key_ID>` with the value of `$PUBLIC_KEY_ID` and the private key placeholder with the contents of `private_key.pem`.

       In the agent configuration, `services.name` can contain up to 20 characters and must use only lowercase Latin letters and digits (`[a-z0-9]`). Don't use dashes or dots.

       For multiple services, add them to the `config.services` section:

       ```yaml theme={null}
       config:
         services:
           - name: api
             target: localhost:8080
             type: http
           - name: grpc
             target: localhost:9090
             type: http
             protocol: h2
           - name: db
             target: localhost:5432
             type: tcp
       ```

    9. Install the agent in your Kubernetes cluster:

       ```bash theme={null}
       helm install nebius-tunnel-agent \
         oci://cr.eu-north1.nebius.cloud/marketplace/chart/nebius-tunnel-agent \
         -f custom.values.yaml
       ```

       When the agent connects, it returns the public endpoint for each service. The endpoint format is:

       ```text theme={null}
       <service_name>-<tunnel_masked_ID>.tunnel.applications.<region>.nebius.cloud:443
       ```

       Where:

       * `service_name` is the `services.name` value from the agent configuration.
       * `tunnel_masked_ID` is the mask of the tunnel ID without the `applicationtunnel-` prefix and regional routing code. For example, for `applicationtunnel-<routing_code>abcdef1234`, the tunnel ID mask is `abcdef1234`.
       * `region` is the [region](/overview/regions) of the project where the tunnel was created, for example `eu-north1`.
  </Tab>

  <Tab title="VM">
    1. Download and extract the `nebius-tunnel-agent` binary for your virtual machine's OS and architecture:

       * [macOS ARM64](https://storage.eu-north1.nebius.cloud/products/releases/nebius-tunnel-agent/latest/nebius-tunnel-agent-darwin-arm64.tar.gz)
       * [macOS x86\_64](https://storage.eu-north1.nebius.cloud/products/releases/nebius-tunnel-agent/latest/nebius-tunnel-agent-darwin-x86_64.tar.gz)
       * [Linux ARM64](https://storage.eu-north1.nebius.cloud/products/releases/nebius-tunnel-agent/latest/nebius-tunnel-agent-linux-aarch64.tar.gz)
       * [Linux x86\_64](https://storage.eu-north1.nebius.cloud/products/releases/nebius-tunnel-agent/latest/nebius-tunnel-agent-linux-x86_64.tar.gz)
       * [Windows ARM64](https://storage.eu-north1.nebius.cloud/products/releases/nebius-tunnel-agent/latest/nebius-tunnel-agent-windows-arm64.tar.gz)
       * [Windows x86\_64](https://storage.eu-north1.nebius.cloud/products/releases/nebius-tunnel-agent/latest/nebius-tunnel-agent-windows-x86_64.tar.gz)

       For example, to download and extract the Linux x86\_64 archive:

       ```bash theme={null}
       curl -LO https://storage.eu-north1.nebius.cloud/products/releases/nebius-tunnel-agent/latest/nebius-tunnel-agent-linux-x86_64.tar.gz
       tar -xzf nebius-tunnel-agent-linux-x86_64.tar.gz
       ```

    2. Create a service account and save its ID:

       ```bash theme={null}
       export SA_ID=$(nebius iam service-account create \
         --name "tunnel-agent" \
         --parent-id "$PROJECT_ID" \
         --format jsonpath='{.metadata.id}')
       ```

           <Note>
             To grant wider access instead of creating a dedicated group with the `applicationtunnel.agent` role, you can [add the service account to the `editors` group](/iam/service-accounts/manage#granting-editor-access-to-the-service-account).
           </Note>

    3. Create a group for Nebius Tunnels service accounts and save its ID:

       ```bash theme={null}
       export GROUP_ID=$(nebius iam group create \
         --name "tunnel-agents" \
         --parent-id "$TENANT_ID" \
         --format jsonpath='{.metadata.id}')
       ```

    4. Grant the group the `applicationtunnel.agent` role for the tunnel:

       ```bash theme={null}
       nebius iam access-permit create \
         --parent-id "$GROUP_ID" \
         --resource-id "$TUNNEL_ID" \
         --role applicationtunnel.agent
       ```

           <Note>
             To grant access to more tunnels, create the permit on a broader resource: a project or a tenant. A permit on a project applies to all tunnels in that project. A permit on a tenant applies to all tunnels in all projects in the tenant.
           </Note>

    5. Add the service account to the group:

       ```bash theme={null}
       nebius iam group-membership create \
         --parent-id "$GROUP_ID" \
         --member-id "$SA_ID"
       ```

    6. Create a key pair:

       ```bash theme={null}
       openssl genrsa -out ./private_key.pem 4096
       openssl rsa -in ./private_key.pem -pubout -out ./public_key.pem
       ```

    7. Upload the public key and save its ID:

       ```bash theme={null}
       export PUBLIC_KEY_ID=$(nebius iam auth-public-key create \
         --account-service-account-id "$SA_ID" \
         --data "$(cat ./public_key.pem)" \
         --format jsonpath='{.metadata.id}')
       ```

    8. Create `config.yaml` for the agent:

       ```bash theme={null}
       cat > config.yaml <<EOF
       tunnel_id: <tunnel_ID>

       iam:
         service_account:
           service_account_id: <service_account_ID>
           public_key_id: <authorized_key_ID>
           private_key_path: ./private_key.pem

       services:
         - name: web
           target: localhost:8080
           type: http
       EOF
       ```

       In the file, replace `<tunnel_ID>` with the value of `$TUNNEL_ID`, `<service_account_ID>` with the value of `$SA_ID` and `<authorized_key_ID>` with the value of `$PUBLIC_KEY_ID`.

       In the agent configuration, `services.name` can contain up to 20 characters and must use only lowercase Latin letters and digits (`[a-z0-9]`). Don't use dashes or dots.

       For multiple services, configure the `services` section like this:

       ```yaml theme={null}
       services:
         - name: api
           target: localhost:8080
           type: http
         - name: grpc
           target: localhost:9090
           type: http
           protocol: h2
         - name: db
           target: localhost:5432
           type: tcp
       ```

    9. Run the agent:

       ```bash theme={null}
       ./nebius-tunnel-agent -config ./config.yaml
       ```

       When the agent connects, it returns the public endpoint for each service. The endpoint format is:

       ```text theme={null}
       <service_name>-<tunnel_masked_ID>.tunnel.applications.<region>.nebius.cloud:443
       ```

       Where:

       * `service_name` is the `services.name` value from the agent configuration.
       * `tunnel_masked_ID` is the mask of the tunnel ID without the `applicationtunnel-` prefix and regional routing code. For example, for `applicationtunnel-<routing_code>abcdef1234`, the tunnel ID mask is `abcdef1234`.
       * `region` is the [region](/overview/regions) of the project where the tunnel was created, for example `eu-north1`.
  </Tab>
</Tabs>
