# Docker Compose Install

![](/files/Kj5nzxwZqntLs1AmlaIA)

## Overview

This section describes how to install Keeper Connection Manager using Docker by building a customized docker-compose orchestration file.

### Step 1: Install Docker

**Windows**

Install Docker Desktop following Docker's [official instructions](https://docs.docker.com/desktop/install/windows-install/).

**Linux**

Install Docker on Linux, using this [guide](/en/keeperpam/privileged-access-manager/references/installing-docker-on-linux.md) as reference for your specific Linux distribution.

### Step 2: Create Docker Compose File <a href="#id-.deployingusingdockerv2.x-usingdocker-compose" id="id-.deployingusingdockerv2.x-usingdocker-compose"></a>

Now that you have Docker running on your instance, you need to generate a `docker-compose.yml` file that must be transferred to a working directory on your machine.

An example `docker-compose.yml` file for a deployment of Keeper Connection Manager which uses Let's Encrypt for its SSL certificate and an automatically-initialized database for authentication is provided below with a MySQL and PostgreSQL option.

{% hint style="warning" %}
Modify the parameters in this file as [described below](#parameters)
{% endhint %}

{% tabs %}
{% tab title="Using MySQL" %}

```yaml
version: "3"
services:

    guacd:
        image: keeper/guacd:2
        restart: unless-stopped
        shm_size: 1001500k
#        security_opt:
#            - "seccomp:guacd-docker-seccomp.json"
#            - "apparmor:guacd-apparmor-profile"
        environment:
            ACCEPT_EULA: "Y"
        volumes:
            - "common-storage:/var/lib/guacamole:rw"

    db:
        image: keeper/guacamole-db-mysql:2
        restart: unless-stopped
        environment:
            ACCEPT_EULA: "Y"
            MYSQL_RANDOM_ROOT_PASSWORD: "yes"
            GUACAMOLE_DATABASE: "guacamole_db"
            GUACAMOLE_USERNAME: "guacamole_user"
            GUACAMOLE_PASSWORD: "db_strong_password"
            GUACAMOLE_ADMIN_PASSWORD: "admin_strong_password"

    guacamole:
        image: keeper/guacamole:2
        restart: unless-stopped
        environment:
            ACCEPT_EULA: "Y"
            GUACD_HOSTNAME: "guacd"
            MYSQL_HOSTNAME: "db"
            MYSQL_DATABASE: "guacamole_db"
            MYSQL_USERNAME: "guacamole_user"
            MYSQL_PASSWORD: "db_strong_password"
            KCM_LICENSE: "XXXXXXXXXXXXXXXXXXXXXXXXXX"
        volumes:
            - "common-storage:/var/lib/guacamole:rw"

    ssl:
        image: keeper/guacamole-ssl-nginx:2
        restart: unless-stopped
        ports:
            - "80:80"
            - "443:443"
        environment:
            ACCEPT_EULA: "Y"
            GUACAMOLE_HOSTNAME: guacamole
            SSL_HOSTNAME: keeper.mycompany.com
            LETSENCRYPT_ACCEPT_TOS: "Y"
            LETSENCRYPT_EMAIL: you@company.com

volumes:
    common-storage:
```

#### Parameters

Copy this file to your target KCM instance.  Please note that you'll need to modify a few of the fields immediately:

* **KCM\_LICENSE** is the Base64 Licence Key for KCM. You can find it on your Keeper Admin Console, in Connection Manager → On-prem Licence Key.
* **shm\_size** should be roughly half of available physical memory on the instance. If this setting is too low, you won't be able to start new sessions. RBI uses a lot of memory due to launching Chromium instances on every request.
* **security\_opt** refers to the path of the [seccomp security profile ](#create-the-seccomp-security-profile)and must be included for remote browser isolation (see [below](#remote-browser-isolation-configuration)). It is commented out in the example above as KCM could run without it.
* **GUACAMOLE\_PASSWORD** and **MYSQL\_PASSWORD** need to match, and should be a randomly generated strong password. We recommend using your Keeper vault for generating a password. Avoid using special characters like backslashes, dollar signs and forward slashes.
* **GUACAMOLE\_ADMIN\_PASSWORD** is the password for the default "guacadmin" user login. This should be a strong and randomly generated password. We recommend using your Keeper vault for generating a password. Avoid using special characters like backslashes, dollar signs and forward slashes.
* **SSL\_HOSTNAME** needs to be the FQDN you set up to point to this server.  Make sure that the DNS is routable to the IP from the outside world, and ports 80/443 are open so that Let's Encrypt can register the certificate.
  {% endtab %}

{% tab title="Using PostgreSQL" %}

<pre class="language-yaml"><code class="lang-yaml">version: "3"
services:

    guacd:
        image: keeper/guacd:2
        restart: unless-stopped
        shm_size: 1001500k
<strong>#        security_opt:
</strong>#            - "seccomp:guacd-docker-seccomp.json"
#            - "apparmor:guacd-apparmor-profile"
        environment:
            ACCEPT_EULA: "Y"
        volumes:
            - "common-storage:/var/lib/guacamole:rw"

    db:
        image: keeper/guacamole-db-postgres:2
        restart: unless-stopped
        environment:
            ACCEPT_EULA: "Y"
            GUACAMOLE_DATABASE: "guacamole_db"
            GUACAMOLE_USERNAME: "guacamole_user"
            POSTGRES_PASSWORD: "db_strong_password"
            GUACAMOLE_PASSWORD: "db_strong_password"
            GUACAMOLE_ADMIN_PASSWORD: "admin_strong_password"

    guacamole:
        image: keeper/guacamole:2
        restart: unless-stopped
        environment:
            ACCEPT_EULA: "Y"
            GUACD_HOSTNAME: "guacd"
            POSTGRES_HOSTNAME: "db"
            POSTGRES_DATABASE: "guacamole_db"
            POSTGRES_USERNAME: "guacamole_user"
            POSTGRES_PASSWORD: "db_strong_password"
            KCM_LICENSE: "XXXXXXXXXXXXXXXXXXXXXXXXXX"
        volumes:
            - "common-storage:/var/lib/guacamole:rw"

    ssl:
        image: keeper/guacamole-ssl-nginx:2
        restart: unless-stopped
        ports:
            - "80:80"
            - "443:443"
        environment:
            ACCEPT_EULA: "Y"
            GUACAMOLE_HOSTNAME: guacamole
            SSL_HOSTNAME: keeper.mycompany.com
            LETSENCRYPT_ACCEPT_TOS: "Y"
            LETSENCRYPT_EMAIL: you@company.com

volumes:
    common-storage:
</code></pre>

Copy this file to your target KCM instance.  Please note that you'll need to modify a few of the fields immediately:

* **KCM\_LICENSE** is the Base64 Licence Key for KCM. You can find it on your Keeper Admin Console, in Connection Manager → On-prem Licence Key.
* **shm\_size** should be roughly half of available physical memory on the instance. If this setting is too low, you won't be able to start new sessions. RBI uses a lot of memory due to launching Chromium instances on every request.
* **security\_opt** refers to the path of the [seccomp security profile ](#create-the-seccomp-security-profile)and must be included for remote browser isolation (see [below](#remote-browser-isolation-configuration)). It is commented out in the example above as KCM could run without it.
* **GUACAMOLE\_PASSWORD** and **POSTGRES\_PASSWORD** need to match, and should be a randomly generated strong password. We recommend using your Keeper vault for generating a password. Avoid using special characters like backslashes, dollar signs and forward slashes.
* **GUACAMOLE\_ADMIN\_PASSWORD** is the password for the default "guacadmin" user login. This should be a strong and randomly generated password. We recommend using your Keeper vault for generating a password. Avoid using special characters like backslashes, dollar signs and forward slashes.
* **SSL\_HOSTNAME** needs to be the FQDN you set up to point to this server.  Make sure that the DNS is routable to the IP from the outside world, and ports 80/443 are open so that Let's Encrypt can register the certificate.
  {% endtab %}
  {% endtabs %}

### Using a Custom SSL Certificate

If you plan to use a custom SSL certificate instead of Let's Encrypt, replace the "ssl" section  of the Docker Compose file with a section that looks like this:

```yaml
    ssl:
        image: keeper/guacamole-ssl-nginx:latest
        restart: unless-stopped
        ports:
            - "80:80"
            - "443:443"
        environment:
            SELF_SIGNED: "N"
            ACCEPT_EULA: "Y"
            GUACAMOLE_HOSTNAME: "guacamole"
            SSL_HOSTNAME: "keeper.mycompany.com"
            CERTIFICATE_FILE: "/var/lib/guacamole/your_certificate.pem"
            PRIVATE_KEY_FILE: "/var/lib/guacamole/your_private_key.key"
        volumes:
            - "C:\Users\Path\To\Cert:/var/lib/guacamole:ro"

```

In this case, `CERTIFICATE_FILE` is the PEM-encoded certificate including the intermediate certificate chain.  The `PRIVATE_KEY_FILE` is the private key file.&#x20;

Also, note that in the above snippet, there is a volume mount that assigns the local filesystem to the target container. You should only modify the `C:\Users\Path\To\Cert` portion of the string.  On linux environments it will be `/path/to/cert`.

### Step 3: Start the Docker Containers

On Windows, open a Command Prompt. On Linux, open the terminal shell. Navigate to the location of the `docker-compose.yml` file that was saved in step 2.

To start up the environment, simply type the below command:

```
docker compose up -d
```

Note: Older Docker versions require a hyphen in the "docker-compose" command.

That's it.  If everything is successful, you can open the Keeper Connection Manager login screen on the specified FQDN.

![Keeper Connection Manager Login Screen](/files/ZdyV3rMMT8ylZq5sK9X1)

### Important Notes

* If you have not set up a proper domain name routing to the server, you can temporarily host-hack the local system in order to at least access the user interface and start testing.
* If you're using your own SSL certificate, we don't recommend using a wildcard cert. A certificate that has been explicitly created for the Keeper Connection Manager endpoint is the best practice since you'll be storing the SSL private key on the device.
* If you're using Windows, you will need to modify your Windows Defender Firewall to open up ports 443 to the Docker service.
* Running `docker compose down` will **delete all data** in the container including users, connections and history. To simply stop the containers, use `docker compose stop`.

### Remote Browser Isolation Configuration

#### Security Profile

If you plan to use remote browser isolation, you'll need to create a `seccomp` security profile for the guacd container.  For a new installation of Keeper Connection Manager, the `kcm-setup.run` script automatically handles this for you and places the file called `guacd-docker-seccomp.json` in the folder  `/etc/kcm-setup/` on the instance.

If this file is not automatically created, or you are upgrading an instance to use remote browser isolation, you may need to create the file manually.

You can obtain a copy of the file directly from the `guacd` Docker image once your docker containers are updated and running. The following will create a `guacd-docker-seccomp.json` file on your active directory:

{% code overflow="wrap" %}

```
docker run --rm --entrypoint=/bin/cat keeper/guacd:2 /opt/keeper/share/guacd/docker-seccomp.json > guacd-docker-seccomp.json
```

{% endcode %}

Once you have a valid security profile file on your directory, you can set it in the `security_opt` object of your `docker-compose.yml`:

{% code overflow="wrap" %}

```yaml
        security_opt:
            - "seccomp:/path/to/guacd-docker-seccomp.json"
```

{% endcode %}

#### Apparmor Profile

Since [KCM 2.20](/en/release-notes/enterprise/keeper-connection-manager/kcm-version-2.20.0.md), an apparmor profile should be configured for use of RBI in your KCM client. This AppArmor profile must be loaded for RBI to function on any platform using AppArmor, such as Ubuntu.

You can extract the apparmor profile from the guacd image, much like how it was done above for the security profile. The following will create a `guacd-apparmor-profile` file on the active directory.

{% code overflow="wrap" %}

```
sudo docker run --rm --entrypoint=/bin/cat keeper/guacd /opt/keeper/share/guacd/guacd-apparmor-profile > guacd-apparmor-profile
```

{% endcode %}

The profile should then be copied beneath `/etc/apparmor.d` so that it is automatically loaded on boot:

```
sudo cp guacd-apparmor-profile /etc/apparmor.d/
```

The new profile can then be loaded either by rebooting or by manually running `apparmor_parser`:

```
sudo apparmor_parser -r /etc/apparmor.d/guacd-apparmor-profile
```

You can then set it in the `security_opt` object of your `docker-compose.yml`:

{% code overflow="wrap" %}

```yaml
        security_opt:
            - "seccomp:/path/to/guacd-docker-seccomp.json"
            - "apparmor:/path/to/guacd-apparmor-profile"
```

{% endcode %}

If your KCM client was running already, you can restart it to enact the changes:

```
docker compose up -d
```

### Images

Below is a description of each of the images.

<table><thead><tr><th width="274.3333333333333">Image name</th><th>Base image</th><th>Description</th></tr></thead><tbody><tr><td><a href="/pages/PrGlvnEjhFxQkUuBMC4I"><code>keeper/guacamole</code></a></td><td><a href="https://hub.docker.com/_/centos"><code>centos:7</code></a></td><td>The Apache Guacamole web application, deployed under Apache Tomcat.</td></tr><tr><td><a href="/pages/hmfHGZvU3ZXXhD7fRWRP"><code>keeper/guacd</code></a></td><td><a href="https://hub.docker.com/_/centos"><code>centos:7</code></a></td><td>The Apache Guacamole proxy daemon, guacd, with support for native protocols such as RDP and SSH.</td></tr><tr><td><a href="/pages/FUGlIM7D5ZI0PmccUy2v"><code>keeper/guacamole-db-mysql</code></a></td><td><a href="https://hub.docker.com/_/mysql"><code>mysql:5</code></a></td><td>An instance of MySQL, automatically initialized with the Apache Guacamole database schema.</td></tr><tr><td><a href="/pages/P7RtZ2zsWj858OWlEWyU"><code>keeper/guacamole-db-postgres</code></a></td><td><a href="https://hub.docker.com/_/postgres"><code>postgres:11</code></a></td><td>An instance of PostgreSQL, automatically initialized with the Apache Guacamole database schema.</td></tr><tr><td><a href="/pages/OVgN11MhGSdeszJPGKQo"><code>keeper/guacamole-ssl-nginx</code></a></td><td><a href="https://hub.docker.com/_/nginx"><code>nginx:stable</code></a></td><td>An instance of NGINX which automatically provides SSL termination for Keeper Connection Manager.<br></td></tr></tbody></table>

### :tada: Installation Complete!

Now that your Keeper Connection Manager instance is running, you can login as guacadmin and start setting up some connections.  Follow the Using Keeper Connection Manager documentation for next steps.

{% content-ref url="/pages/3JzAlEHz7PsS6daC3ATV" %}
[How to Use KCM](/en/keeper-connection-manager/using-keeper-connection-manager.md)
{% endcontent-ref %}

The next several sections of this installation guide provide detailed information about each specific Docker image, if you plan to customize or modify the environment.


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/en/keeper-connection-manager/installation/docker-compose-install.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
