> For the complete documentation index, see [llms.txt](https://docs.devolutions.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.devolutions.net/gateway/getting-started/devolutions-gateway-configuration-in-docker.md).

# Devolutions Gateway configuration in Docker

Run Devolutions Gateway in Docker with the official image, configure it with environment variables and TLS, and link it to Devolutions Server or Cloud.

Devolutions Gateway is available as an official Linux container image on Docker Hub: [devolutions/devolutions-gateway](https://hub.docker.com/r/devolutions/devolutions-gateway). The container is configured entirely with environment variables. At each start, its entry point script writes the `gateway.json` configuration file from these variables and then launches Devolutions Gateway.

{% hint style="warning" %}
Devolutions Server or Devolutions Cloud is required to broker sessions through Devolutions Gateway, as well as a Devolutions Gateway license. The container can also run the standalone web application without Devolutions Server or Devolutions Cloud.
{% endhint %}

### About the image

* **Image name**: `devolutions/devolutions-gateway`
* **Tags**: `latest`, and one tag per release version. Use a version tag in production so that upgrades are deliberate.
* **Architectures**: `linux/amd64` and `linux/arm64`. Docker automatically pulls the variant that matches the host.
* **Base image**: Debian 12 (`bookworm-slim`), with PowerShell 7 and the [Devolutions Gateway PowerShell module](https://www.powershellgallery.com/packages/DevolutionsGateway) preinstalled. The entry point script uses this module to write the configuration.
* **Exposed ports**: `7171` (HTTP or HTTPS listener) and `8181` (TCP listener).
* **Configuration folder inside the container**: `/tmp/devolutions-gateway` (set by the `DGATEWAY_CONFIG_PATH` environment variable). This folder holds `gateway.json`, the provisioner key, the TLS certificate, and, unless `RECORDING_PATH` is set, the `recordings` folder.
* **Health check endpoint**: `/jet/health`.

The images are signed with [Cosign](https://github.com/sigstore/cosign).

### Prerequisites

* A Linux host with Docker Engine (or any OCI-compatible runtime) and, optionally, Docker Compose.
* Ports `7171` and `8181` (or the ports of your choice) open in the host firewall.
* A DNS name for Devolutions Gateway that clients can resolve, for example `gateway.contoso.com`.
* For production, a TLS certificate and its private key in **PEM** format for that DNS name. The certificate must meet the same requirements as on other platforms (Subject Alternative Name and Server Authentication EKU). See [Devolutions Gateway configuration on Linux](/gateway/getting-started/devolutions-gateway-configuration-on-linux.md#configure-certificates).
* The provisioner public key of your Devolutions Server or Devolutions Cloud instance (the **gateway\_public\_key.pem** or **provisioner.pem** file downloaded from ***Administration*** – ***Devolutions Gateway*** – ***More*** – ***Download public key***).
* Devolutions Gateway must be able to resolve and reach the hosts it connects to from inside the container.

### Pull the image

```shell
docker pull devolutions/devolutions-gateway:latest
```

To pull a specific version, replace `latest` with the version number, for example `devolutions/devolutions-gateway:<version>`.

### Run a minimal container

The environment variables that hold keys and certificates expect the **Base64-encoded content** of the PEM file. On Linux, encode a file with `base64 -w0`:

```shell
export PROVISIONER_PUBLIC_KEY_B64=$(base64 -w0 provisioner.pem)
```

{% hint style="info" %}
On Windows, use PowerShell instead: `[Convert]::ToBase64String([IO.File]::ReadAllBytes("provisioner.pem"))`.
{% endhint %}

The following command starts Devolutions Gateway with an HTTPS listener on port `7171`, a TCP listener on port `8181`, and the provisioner public key of your Devolutions Server or Devolutions Cloud. Because no certificate is provided, the container generates a self-signed certificate for the value of `HOSTNAME` (see [Configure TLS](#configure-tls)).

```shell
docker run -d \
  --name devolutions-gateway \
  --restart unless-stopped \
  -p 7171:7171 \
  -p 8181:8181 \
  -e HOSTNAME=gateway.contoso.com \
  -e WEB_SCHEME=https \
  -e PROVISIONER_PUBLIC_KEY_B64="$PROVISIONER_PUBLIC_KEY_B64" \
  -v devolutions-gateway-data:/tmp/devolutions-gateway \
  devolutions/devolutions-gateway:latest
```

{% hint style="warning" %}
Always set `HOSTNAME` explicitly. Docker automatically sets the `HOSTNAME` variable inside every container to the container's own host name (by default, the container ID). If you do not override it, Devolutions Gateway uses that value as its host name, and the self-signed certificate is generated for it.
{% endhint %}

Check that Devolutions Gateway is running:

```shell
docker logs devolutions-gateway
curl -k https://localhost:7171/jet/health
```

### Use Docker Compose

The following `compose.yaml` file runs Devolutions Gateway with an HTTPS listener, a certificate, the provisioner public key, and a named volume for persistent data. The Base64 values are read from a `.env` file placed next to `compose.yaml`.

```yaml
services:
  devolutions-gateway:
    image: devolutions/devolutions-gateway:latest
    container_name: devolutions-gateway
    restart: unless-stopped
    ports:
      - "7171:7171"
      - "8181:8181"
    environment:
      HOSTNAME: gateway.contoso.com
      WEB_SCHEME: https
      PROVISIONER_PUBLIC_KEY_B64: ${PROVISIONER_PUBLIC_KEY_B64}
      TLS_CERTIFICATE_B64: ${TLS_CERTIFICATE_B64}
      TLS_PRIVATE_KEY_B64: ${TLS_PRIVATE_KEY_B64}
    volumes:
      - devolutions-gateway-data:/tmp/devolutions-gateway
    healthcheck:
      test: ["CMD", "curl", "-fsk", "https://localhost:7171/jet/health"]
      interval: 30s
      timeout: 5s
      retries: 3

volumes:
  devolutions-gateway-data:
```

To create the `.env` file on Linux:

```shell
cat > .env <<EOF
PROVISIONER_PUBLIC_KEY_B64=$(base64 -w0 provisioner.pem)
TLS_CERTIFICATE_B64=$(base64 -w0 fullchain.pem)
TLS_PRIVATE_KEY_B64=$(base64 -w0 privkey.pem)
EOF
chmod 600 .env
```

Then start the container with `docker compose up -d`.

### Environment variables

#### Web listener

| VARIABLE              | DESCRIPTION                                                                                                           | DEFAULT                               |
| --------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `HOSTNAME`            | Host name of Devolutions Gateway. Also used as the subject of the self-signed certificate.                            | Set by Docker (see the warning above) |
| `WEB_SCHEME`          | Scheme of the web listener inside the container: `http` or `https`.                                                   | `http`                                |
| `WEB_PORT` or `PORT`  | Port of the web listener inside the container. `PORT` takes precedence over `WEB_PORT`.                               | `7171`                                |
| `EXTERNAL_WEB_SCHEME` | Scheme that clients use to reach the web listener, for example `https` behind a reverse proxy that terminates TLS.    | Value of `WEB_SCHEME`                 |
| `EXTERNAL_WEB_PORT`   | Port that clients use to reach the web listener. Set it when the published host port differs from the container port. | Value of `WEB_PORT`                   |

#### TCP listener

| VARIABLE            | DESCRIPTION                                           | DEFAULT                                             |
| ------------------- | ----------------------------------------------------- | --------------------------------------------------- |
| `TCP_ENABLED`       | Enables the TCP listener (`true` or `false`).         | `true`, or `false` when `WEB_APP_ENABLED` is `true` |
| `TCP_PORT`          | Port of the TCP listener inside the container.        | `8181`                                              |
| `EXTERNAL_TCP_PORT` | Port that clients use to reach the TCP listener.      | Value of `TCP_PORT`                                 |
| `TCP_HOSTNAME`      | Host name that clients use to reach the TCP listener. | `*`                                                 |

#### Keys and certificates

| VARIABLE                      | DESCRIPTION                                                                                              |
| ----------------------------- | -------------------------------------------------------------------------------------------------------- |
| `PROVISIONER_PUBLIC_KEY_B64`  | Base64-encoded provisioner public key (PEM) of Devolutions Server or Devolutions Cloud.                  |
| `PROVISIONER_PRIVATE_KEY_B64` | Base64-encoded provisioner private key (PEM). Only needed if you generate your own provisioner key pair. |
| `TLS_CERTIFICATE_B64`         | Base64-encoded TLS certificate (PEM). It can contain the full certificate chain.                         |
| `TLS_PRIVATE_KEY_B64`         | Base64-encoded private key (PEM) of the TLS certificate.                                                 |
| `TLS_CERTIFICATE_PASSWORD`    | Password of the private key, if it is encrypted.                                                         |

#### Standalone web application, recordings, and logs

| VARIABLE                 | DESCRIPTION                                                                        | DEFAULT                                                                         |
| ------------------------ | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `WEB_APP_ENABLED`        | Enables the standalone web application of Devolutions Gateway (`true` or `false`). | `false`                                                                         |
| `WEB_APP_AUTHENTICATION` | Authentication mode of the standalone web application: `None` or `Custom`.         | `None`, or `Custom` when both `WEB_APP_USERNAME` and `WEB_APP_PASSWORD` are set |
| `WEB_APP_USERNAME`       | User name for `Custom` authentication.                                             | Not set                                                                         |
| `WEB_APP_PASSWORD`       | Password for `Custom` authentication.                                              | Not set                                                                         |
| `RECORDING_PATH`         | Folder inside the container where session recordings are saved.                    | `/tmp/devolutions-gateway/recordings`                                           |
| `VERBOSITY_PROFILE`      | Log verbosity: `Default`, `Debug`, `Tls`, `All`, or `Quiet`.                       | Not set                                                                         |

{% hint style="info" %}
When the container runs as an Azure Web App for Containers, the host name is read from `WEBSITE_HOSTNAME`, and the external scheme and port are forced to `https` and `443`.
{% endhint %}

### Persistent data

Everything Devolutions Gateway writes (configuration, keys, certificate, and recordings) is stored in `/tmp/devolutions-gateway` inside the container. Without a volume, this data is lost when the container is removed or recreated, for example during an upgrade. Mount a named volume or a host folder on `/tmp/devolutions-gateway`, as shown in the examples above. If `RECORDING_PATH` points to another folder, mount a volume on that folder too.

Keep the following behavior in mind when you use a persistent volume:

* **The listeners, the host name, and the standalone web application settings are rewritten at each start** from the environment variables. Changes made to these values directly in `gateway.json` are overwritten.
* **Other values in an existing `gateway.json` are kept.** You can add settings that have no environment variable directly in the `gateway.json` file of the volume, then restart the container. See the [Devolutions Gateway configuration reference on GitHub](https://github.com/Devolutions/devolutions-gateway#configuration) for the available settings.
* **The provisioner key pair is regenerated at each start when `PROVISIONER_PUBLIC_KEY_B64` is not set.** Always pass the provisioner public key of your Devolutions Server or Devolutions Cloud in the environment, otherwise the link with Devolutions Server or Devolutions Cloud breaks after a restart.
* **The TLS certificate is imported again at each start** when `TLS_CERTIFICATE_B64` and `TLS_PRIVATE_KEY_B64` are set. A self-signed certificate is only generated when `WEB_SCHEME` is `https` and no certificate is configured.

### Configure TLS

There are three ways to secure the web listener:

* **Provide your own certificate (recommended)**: set `WEB_SCHEME=https` and pass the certificate and private key in `TLS_CERTIFICATE_B64` and `TLS_PRIVATE_KEY_B64`. To renew the certificate, update the values and recreate the container.
* **Use a self-signed certificate**: set `WEB_SCHEME=https` without providing a certificate. The container generates a self-signed certificate valid for five years, with the value of `HOSTNAME` as its common name. Clients and Devolutions Server must trust this certificate. See [Devolutions Gateway configuration on Linux](/gateway/getting-started/devolutions-gateway-configuration-on-linux.md#trust-the-self-signed-certificate-on-windows). Use this option for testing only.
* **Terminate TLS on a reverse proxy**: keep `WEB_SCHEME=http`, set `EXTERNAL_WEB_SCHEME=https` (and `EXTERNAL_WEB_PORT` if needed), and let the reverse proxy handle the certificate. See [Reverse proxying](/gateway/knowledge-base/how-to-articles/reverse-proxying.md).

{% hint style="warning" %}
WebSockets used by the web-based sessions require a certificate that the browser trusts. Do not expose the HTTP listener directly to clients in production.
{% endhint %}

### Connect Devolutions Gateway to Devolutions Server or Devolutions Cloud

1. In the Devolutions Server or Devolutions Cloud web interface, go to ***Administration*** – ***Devolutions Gateway***.
2. Click ***More*** – ***Download public key***.
3. Pass the Base64-encoded content of this file to the container in `PROVISIONER_PUBLIC_KEY_B64`, then start or recreate the container.
4. Back in ***Administration*** – ***Devolutions Gateway***, click the ***Add*** (***+***) button and select ***Gateway***.
5. Enter the ***Devolutions Gateway URL***, for example `https://gateway.contoso.com:7171`, and the ***TCP hostname***, for example `gateway.contoso.com`. Use the external host name and ports that clients use, not the internal ports of the container.
6. Click ***Test Connection***, then save.

For the details of each setting, see:

* [Devolutions Gateway configuration with Devolutions Server](/gateway/getting-started/devolutions-server/devolutions-gateway-configuration-with-devolutions-server.md)
* [Devolutions Gateway configuration with Devolutions Cloud](/gateway/getting-started/devolutions-cloud/devolutions-gateway-configuration-with-devolutions-cloud.md)
* [Devolutions Gateway configuration in Remote Desktop Manager](/gateway/getting-started/devolutions-server/devolutions-gateway-configuration-in-remote-desktop-manager.md)

### Run the standalone web application

To use Devolutions Gateway without Devolutions Server or Devolutions Cloud, enable its standalone web application:

```shell
docker run -d \
  --name devolutions-gateway \
  -p 7171:7171 \
  -e HOSTNAME=gateway.contoso.com \
  -e WEB_SCHEME=https \
  -e WEB_APP_ENABLED=true \
  -e WEB_APP_USERNAME=gatewayadmin \
  -e WEB_APP_PASSWORD='<password>' \
  -v devolutions-gateway-data:/tmp/devolutions-gateway \
  devolutions/devolutions-gateway:latest
```

Then open `https://gateway.contoso.com:7171` in a browser. In this mode, the TCP listener is turned off unless `TCP_ENABLED=true` is set.

{% hint style="danger" %}
With `WEB_APP_AUTHENTICATION=None` (the default when no user name and password are set), anyone who can reach the web listener can use the web application. Always set `WEB_APP_USERNAME` and `WEB_APP_PASSWORD` when the container is reachable from other machines.
{% endhint %}

### Upgrade Devolutions Gateway

To upgrade, pull the new image and recreate the container. The configuration is kept if it is stored in a volume, and the keys and certificate are imported again from the environment variables.

With Docker Compose, change the version tag in `compose.yaml` if needed, then run:

```shell
docker compose pull
docker compose up -d
```

With `docker run`, pull the new image, remove the container, and run it again with the same parameters:

```shell
docker pull devolutions/devolutions-gateway:latest
docker stop devolutions-gateway
docker rm devolutions-gateway
# Run the same docker run command as before
```

{% hint style="info" %}
The update methods described for Windows (bulk update from Devolutions Server through Devolutions Agent, or the auto-updater PowerShell script) do not apply to containers. Upgrade the container image instead.
{% endhint %}

### Limitations

* Only Linux container images are published. There is no Windows container image, so features that depend on Windows, such as the [Windows certificate store](/gateway/knowledge-base/how-to-articles/use-windows-certificate-store-for-devolutions-gateway.md), are not available.
* The TLS certificate and keys must be provided in PEM format through environment variables. PFX files are not supported by these variables.
* Devolutions Gateway must resolve target host names from inside the container. Configure the container DNS (for example with the `--dns` option of `docker run`) if the targets are only resolvable by an internal DNS server.

### See also

* [Devolutions Gateway configuration on Linux](/gateway/getting-started/devolutions-gateway-configuration-on-linux.md)
* [Devolutions Gateway troubleshooting](/gateway/knowledge-base/troubleshooting-articles/devolutions-gateway-troubleshooting.md)
* [devolutions/devolutions-gateway on Docker Hub](https://hub.docker.com/r/devolutions/devolutions-gateway)
* [Devolutions Gateway container entry point on GitHub](https://github.com/Devolutions/devolutions-gateway/tree/master/package/Linux)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.devolutions.net/gateway/getting-started/devolutions-gateway-configuration-in-docker.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
