# Gateway on Azure Container Instance

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2F3hNhzO4f6z3br5b82j8p%2FAzure%20Container%20App%20Install.jpg?alt=media&#x26;token=d46785a2-e623-4168-87b0-4ec89d537886" alt=""><figcaption></figcaption></figure>

## Overview <a href="#overview" id="overview"></a>

This document contains information on how to install, configure, and update your Keeper Gateway on an Azure Container Instance. The Keeper Gateway container is built upon the base image of Rocky Linux 9 and it is hosted in [DockerHub](https://hub.docker.com/r/keeper/gateway).

## Prerequisites

#### Azure Environment Requirements

* **Resource Group:** A dedicated resource group.
* **Virtual Network (VNet):** A VNet with a dedicated subnet for the gateway.
* **Subnet Delegation:** The designated subnet must be delegated to `Microsoft.ContainerInstance/containerGroups` .
* **Subscription Permissions:** Contributor access to create Container Instances and Network resources.

#### Docker Hub Authentication

To avoid anonymous pull rate limits in Azure (which often result in `429 Too Many Requests` or `Manifest Unknown` errors), you must have:

* **Docker Hub Account:** A registered account at [hub.docker.com](https://hub.docker.com).
* **Personal Access Token:** A Token generated via **Account Settings > Security** with `Read Only` permissions

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FzFod26aaYPanbWaiQqzH%2FDocker%20PAT.png?alt=media&#x26;token=b550a109-cdd4-48ca-9dab-9e0bf95aaca1" alt=""><figcaption></figcaption></figure>

***

## Create a Gateway&#x20;

A new Gateway deployment can be created by clicking on **Create New** > **Gateway** from the Web Vault or Desktop App.

You can also create a Gateway and configuration file from the Commander CLI:

```
pam gateway new -n "<Gateway Name>" -a <Application Name or UID> -c b64
```

The Application names and UIDs can be found with `secrets-manager app list`

### Deployment Manifest

A Docker Compose file is provided through the Vault UI. This file can be used to build a Deployment Manifest file. Save this file as `keeper-gateway.yml` . An example of a Deployment Manifest is below:

```
apiVersion: 2024-05-01-preview
location: <AZURE_REGION> # Example: westeurope
name: <GATEWAY_INSTANCE_NAME>
type: Microsoft.ContainerInstance/containerGroups
properties:
  osType: Linux
  restartPolicy: Always
  sku: Standard
  imageRegistryCredentials:
  - server: index.docker.io
    username: <DOCKER_HUB_USERNAME>
    password: <DOCKER_HUB_PAT_TOKEN>
  containers:
  - name: keeper-gateway
    properties:
      image: keeper/gateway:latest
      resources:
        requests:
          cpu: 2.0
          memoryInGB: 8.0
      ports:
      - port: 443
        protocol: TCP
      environmentVariables:
      - name: ACCEPT_EULA
        value: Y
      - name: GATEWAY_CONFIG
        secureValue: <YOUR_BASE64_CONFIG_STRING>
      volumeMounts:
      - name: devshm
        mountPath: /dev/shm
  ipAddress:
    type: Private
    ports:
    - port: 443
      protocol: TCP
  subnetIds:
  - id: /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RG_NAME>/providers/Microsoft.Network/virtualNetworks/<VNET_NAME>/subnets/<SUBNET_NAME>
  volumes:
  - name: devshm
    emptyDir: {}
```

#### Required Parameters

| **Parameter**                 | **Description**                                                                    |
| ----------------------------- | ---------------------------------------------------------------------------------- |
| `<AZURE_REGION>`              | The Azure region where your VNet and Target VMs reside.                            |
| `<GATEWAY_INSTANCE_NAME>`     | A unique name for this container group in Azure.                                   |
| `<DOCKER_HUB_USERNAME>`       | Your Docker Hub ID (required for production pull limits).                          |
| `<DOCKER_HUB_PAT_TOKEN>`      | The Personal Access Token generated in Docker Hub.                                 |
| `<YOUR_BASE64_CONFIG_STRING>` | The configuration string generated from the Keeper Vault when generating a Gateway |
| `<SUBSCRIPTION_ID>`           | Your 36-character Azure Subscription ID.                                           |
| `<SUBNET_NAME>`               | The name of the subnet delegated to `Microsoft.ContainerInstance`.                 |
| `<VNET_NAME>`                 | The name of the Virtual Network where the subnet resides                           |

We use `emptyDir` for `/dev/shm` to meet shared memory requirements without managing external storage. This storage is ephemeral. If you delete or update the ACI deployment, this data is wiped. This is acceptable for the Gateway because it syncs its state and recordings to the Keeper Cloud.

In Azure Container Instances (ACI), seccomp and AppArmor are not used because ACI uses Hyper-V isolation by default.

***

## Deployment

Once the YAML file is prepared, upload the file and execute the following commands via the Azure CLI to start the service.

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2Fa7JK0iu8N3mmiZoJz6EG%2Fyaml%20upload.png?alt=media&#x26;token=313782a7-2335-4aa4-8771-89539ddf1380" alt=""><figcaption></figcaption></figure>

**Create the Container Group**

```
az container create --resource-group <RESOURCE_GROUP_NAME> --file keeper-gateway.yml
```

**Verify the Service**

{% code overflow="wrap" %}

```
az container show --resource-group <RESOURCE_GROUP_NAME> --name <GATEWAY_INSTANCE_NAME> --query instanceView.state
```

{% endcode %}

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FOWEaKoDhgyhV5NjwsR4A%2Fverification.png?alt=media&#x26;token=4b0992a4-4ad1-4e3f-aea4-17ec0410cfd7" alt=""><figcaption></figcaption></figure>

**Logging**

```
az container logs --resource-group <RESOURCE_GROUP_NAME> --name <GATEWAY_INSTANCE_NAME>
```

***

## Gateway Service Management

In an Azure Container Instance (ACI) environment, management is performed via the Azure CLI or the Azure Portal.

#### Service Control

**Starting the Service** Deploying the manifest automatically starts the service. If the container is stopped:

```
az container start --resource-group <RG_NAME> --name <GATEWAY_NAME>
```

**Stopping the Service** To temporarily halt the Gateway:

```
az container stop --resource-group <RG_NAME> --name <GATEWAY_NAME>
```

**Restarting the Service** Required after making configuration changes to the YAML manifest:

```
az container restart --resource-group <RG_NAME> --name <GATEWAY_NAME>
```

#### Connecting to the Gateway Container&#x20;

For debugging network connectivity or verifying internal environment variables, you can establish an interactive bash session:

{% code overflow="wrap" %}

```
az container exec --resource-group <RG_NAME> --name <GATEWAY_NAME> --exec-command "/bin/bash"
```

{% endcode %}

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FtgsHxknLM0wAx2A5x3qo%2Fconnection.png?alt=media&#x26;token=3c056ff2-bc2e-4c18-9598-71899a47ee4d" alt=""><figcaption></figcaption></figure>

#### Updating the Gateway

To update your production instance to the latest version:

**Pull and Restart**: ACI will automatically pull the `:latest` image tag upon restart if the image policy allows, but the most reliable method is to re-run the creation command:

```
az container create --resource-group <RG_NAME> --file keeper-gateway.yml
```

## Debugging & Health Checks

#### Verbose Logging

If you need to enable debug logs for troubleshooting rotation failures or tunnel issues, add the following to the `environmentVariables` section of your YAML:

```
environmentVariables:
      - name: KEEPER_GATEWAY_LOG_LEVEL
        value: "debug"
      - name: LOG_LEVEL
        value: "debug"
```

#### Health Checks

To monitor the operational status of the Gateway for load balancing or automated failover, you can configure Liveness Probes. This ensures Azure automatically restarts the container if the Gateway service becomes unresponsive.

```
properties:
      livenessProbe:
        httpGet:
          path: /health
          port: 443
        initialDelaySeconds: 30
        periodSeconds: 10
```

***

## Scaling and High Availability

Before deploying additional containers, you must configure the Gateway for scaling and high availability.

After logging into Keeper Commander, get a list of gateways from this command:

```
pam gateway list
```

Run the following command for the gateway being configured for scaling:

```
pam gateway set-max-instances -g <GATEWAY_UID> -m <MAX_INSTANCES>
```

* `<GATEWAY_UID>` is the UID of the Gateway you are scaling.
* `<MAX_INSTANCES>` is the maximum number of Gateway instances you want to allow.

**Example:** The following example allows up to 5 Gateway instances to run concurrently:

```
pam gateway set-max-instances -g Dmg5bh63p3Yj7ov738BTAw -m 5
```

For further information on gateway scaling and high availability

* [Scaling and High Availability](#scaling-and-high-availability)

In Azure ACI, scaling is horizontal. You deploy multiple independent container groups using the exact same `GATEWAY_CONFIG`

To add a second instance, duplicate your YAML file and rename the container group and the YAML file.&#x20;

```
apiVersion: 2024-05-01-preview
location: <AZURE_REGION> # Example: westeurope
name: <GATEWAY_INSTANCE_NAME> <- rename
type: Microsoft.ContainerInstance/containerGroups
properties:
```

Upload your new YAML file and run the deployment command

```
az container create --resource-group <RESOURCE_GROUP_NAME> --file keeper-gateway-2.yml
```

Each instance will automatically join the existing pool.

***

## Network Configuration

The Keeper Gateway establishes outbound-only connections and does not require any inbound firewall rules. The following outbound connections must be allowed:

<table><thead><tr><th width="310.1015625">Destination Endpoint</th><th>Ports Needed</th><th>More Info</th></tr></thead><tbody><tr><td><p><strong>Keeper Cloud</strong><br><code>keepersecurity.[x]</code></p><p></p><p>Endpoints:</p><p>US: <code>.com</code></p><p>EU: <code>.eu</code>   </p><p>AU: <code>.com.au</code></p><p>JP: <code>.jp</code></p><p>CA: <code>.ca</code></p><p>US_GOV: <code>.us</code></p></td><td>TLS Port 443</td><td>Communicates with Keeper Cloud to access target infrastructure via native protocols (e.g., SSH, RDP)</td></tr><tr><td><p><strong>Keeper Router</strong><br><code>connect.keepersecurity.[x]</code></p><p></p><p>Endpoints:</p><p>US: <code>.com</code></p><p>EU: <code>.eu</code>   </p><p>AU: <code>.com.au</code></p><p>JP: <code>.jp</code></p><p>CA: <code>.ca</code></p><p>US_GOV: <code>.us</code></p></td><td>TLS Port 443</td><td>Communicates with Keeper Router to establish secure, real-time WebSocket connections </td></tr><tr><td><p><strong>Keeper Stun/Turn Service</strong></p><p><code>krelay.keepersecurity.[x]</code> </p><p></p><p>Endpoints:</p><p>US: <code>.com</code></p><p>EU: <code>.eu</code>   </p><p>AU: <code>.com.au</code></p><p>JP: <code>.jp</code></p><p>CA: <code>.ca</code></p><p>US_GOV: <code>.us</code></p></td><td>TCP and UDP opened on Port 3478<br><br>Outbound access to TCP and UDP ports 49152 through 65535<br></td><td>Facilitates secure and encrypted WebRTC  connections between end-user's vault and target systems via the Gateway</td></tr></tbody></table>

The Gateway preserves zero knowledge by performing all encryption and decryption of data locally. Keeper Secrets Manager APIs are used to communicate with the Keeper cloud.
