# SSH (Customer Managed Key)

This guide describes how to set up an SSH server with your own key. An SSH server resource in StrongDM is defined by a specific destination (host and port) and credentials used to access it.

### Authentication

When using the SSH (Customer Managed Key) server type:

* You supply your private key (or the path/reference to it) into StrongDM.
* You ensure that the public key that corresponds to your private key is installed on the target host in the `~/.ssh/authorized_keys` file for the user account configured in StrongDM.
* A StrongDM node uses the supplied private key to authenticate to the target host.
* The host verifies the public key and, if valid, grants the connection.

### Prerequisites

Before you begin, ensure that the following requirements are met:

* A StrongDM node (gateway, relay, or proxy worker) is deployed and can reach the target SSH host (hostname/IP and port).
* You have Admin access in StrongDM to create and manage resources.
* You have already generated or hold an SSH key pair (private and public). The public key must be compatible with your host’s SSH daemon (PEM or OpenSSH format).
* On the target host, you have a user account configured for SSH access and permissions to edit `~/.ssh/authorized_keys`.
* (Recommended) The host’s `.ssh` directory and `authorized_keys` file have proper ownership/permissions (for example, `.ssh` owned by login user, `authorized_keys` only writable by that user).
* (Recommended) The host’s system clock is synchronized (via NTP) to avoid unexpected issues.

{% hint style="info" %}
To verify that the server you are attempting to add is accessible from your StrongDM node, go to the gateway or relay server and from a command prompt, type `ping <YOUR_HOSTNAME>`. If your gateway or relay can connect to this hostname, you can continue.

\
For more information see [gateways-and-relays](https://docs.strongdm.com/admin/networking/gateways-and-relays "mention").
{% endhint %}

## Generate the Key

If you have not already done so, generate your key. Use PEM or OpenSSH formatting to generate your key.

{% hint style="info" %}
Note that if you use the AWS Secret Key Generator in Wizard mode to generate your key, this can cause issues due to the line breaks it inserts. We recommend that if you use this generator, you do so in plaintext.
{% endhint %}

## Add the Resource in StrongDM

Next, add the resource in StrongDM. This section provides instructions for adding the resource in either the StrongDM Admin UI, CLI, Terraform provider, or SDKs.

{% tabs %}
{% tab title="Admin UI" %}
**Set up and Manage With the Admin UI**

If using the Admin UI to add the resource to StrongDM, use the following steps.

* Log in to the Admin UI and select **Managed Resources**.
* Click the **Add Resource** button.
* On the **Add Resource** dialog, select **SSH (Customer Managed Key)** as the **Resource Type** and set other [resource properties](#resource-properties) to configure how the StrongDM relay connects to the server via SSH.

  ![](https://4180056444-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FF7eka9SH5TT8nJm2ZfWj%2Fuploads%2Fgit-blob-e5d653c0e7336dd198a243a43dd6a879c6b53676%2Fadd-resource-ssh-customermanagedkey.png?alt=media)
* Click **create** to save the resource.
  {% endtab %}

{% tab title="CLI" %}
**Set up and Manage With the CLI**

This section provides general steps on how to configure and manage the resource using the StrongDM CLI. For more information and examples, please see the [CLI Reference](https://docs.strongdm.com/references/cli) documentation.

1. In your terminal or Command Prompt, log in to StrongDM:

   ```sh
   sdm login
   ```
2. Run `sdm admin servers add ssh-customer-key --help` to view the help text for the command, which shows you how to use the command and what options (properties) are available. Note which [properties](#resource-properties) are required and collect the values for them.

   ```sh
   NAME:
      sdm admin servers add ssh-customer-key - create SSH (Customer Managed Key) server

   USAGE:
      sdm admin servers add ssh-customer-key [command options] <name>

   OPTIONS:
      --allow-deprecated-key-exchanges             sdm must use TLS to connect
      --bind-interface value                       bind interface (default: "127.0.0.1")
      --egress-filter value                        apply filter to select egress nodes e.g. 'field:name tag:key=value ...'
      --hostname value                             (required)
      --identity-alias-healthcheck-username value  (conditional)
      --identity-set-id value                      
      --identity-set-name value                    set the identity set by name
      --port value                                 (required) (default: 22)
      --port-forwarding                            
      --port-override value                        port profile override (default: -1)
      --proxy-cluster-id value                     proxy cluster id
      --private-key value                          The file path of the private key used to authenticate with the server. (required, secret)
      --proxy-cluster-id value                     proxy cluster id
      --secret-store-id value                      secret store id
      --subdomain value, --bind-subdomain value                            DNS subdomain through which this resource may be accessed on clients (e.g. "app-prod" allows the resource to be accessed as "app-prod.<your-org-name>.<sdm-proxy-domain>"). Only applicable to HTTP-based resources or resources using virtual networking mode.
      --tags value                                 tags e.g. 'key=value,...'
      --template, -t                               display a JSON template
      --timeout value                              set time limit for command
      --username value                             (conditional, secret)

   ```
3. Run `sdm admin servers add ssh-customer-key <RESOURCE_NAME>` to add the resource in StrongDM. Set all required properties with their values. For example:

   ```sh
   sdm admin servers add ssh-customer-key "linux-ssh-cmk-prod-01"
     --hostname "ssh01.acme.internal"
     --port 22
     --username "ubuntu"
     --private-key "/path/to/private_key.pem"
     --bind-interface "default"
     --port-override -1
     --egress-filter 'field:name tag:env=prod tag:region=us-west'
     --proxy-cluster-id "plc_0123456789abcdef"
     --secret-store-id "ss_abcdef0123456789"
     --port-forwarding
     --subdomain "ssh-prod01"
     --tags "env=prod,role=linux,team=infra"
     --timeout 30
   ```
4. Check that the resource has been added. The output of the following command should show the resource's name:

   ```sh
   sdm admin resources list
   ```

{% endtab %}

{% tab title="Terraform" %}
**Set up and Manage With Terraform**

This section provides an example of how to configure and manage the resource using the Terraform provider. For more information and examples, please see the [Terraform provider](https://github.com/strongdm/terraform-provider-sdm) documentation.

```
# Install StrongDM provider
terraform {
  required_providers {
    sdm = {
      source  = "strongdm/sdm"
      version = "16.5.0"
    }
  }
}

# Configure StrongDM provider
provider "sdm" {
  # Add API access key and secret key from the Admin UI
  api_access_key = "njjSn...5hM"
  api_secret_key = "ziG...="
}

# Create SSH (Customer Managed Key) server
resource "sdm_resource" "linux_ssh_cmk_prod_01" {
  ssh_customer_key {
    # Required
    name     = "linux-ssh-cmk-prod-01"           # <name>
    hostname = "ssh01.acme.internal"             # --hostname
    port     = 22                                 # --port (default 22)
    username = "ubuntu"                           # --username
    private_key = file("path/to/private_key.pem") # --private-key (path or content)

    # Common networking options
    bind_interface = "default"                    # --bind-interface ("default" | "loopback" | "vnm")
    port_override  = -1                           # --port-override (-1 = auto-allocate)
    egress_filter  = "field:name tag:env=prod tag:region=us-west"  # --egress-filter
    subdomain      = "ssh-prod01"                 # --subdomain (VN/HTTP-only applicability noted in CLI)

    # Connection behavior
    allow_deprecated_key_exchanges = false        # --allow-deprecated-key-exchanges
    port_forwarding                = true         # --port-forwarding

    # Optional integrations
    proxy_cluster_id = "plc_0123456789abcdef"     # --proxy-cluster-id
    secret_store_id  = "ss_abcdef0123456789"      # --secret-store-id

    # Tags
    tags = {                                      # --tags
      env  = "prod"
      role = "linux"
      team = "infra"
    }
  }
}
```

{% endtab %}

{% tab title="SDKs" %}
**Set up and Manage With SDKs**

In addition to the Admin UI, CLI, and Terraform, you may configure and manage your resource with any of the following SDK options: Go, Java, Python, and Ruby. Please see the following references for more information and examples.

| Go            | ​[pkg.go.dev](https://pkg.go.dev/github.com/strongdm/strongdm-sdk-go/v16)​ | ​[strongdm-sdk-go](https://github.com/strongdm/strongdm-sdk-go)​         | ​[Go SDK Examples](https://github.com/strongdm/strongdm-sdk-go-examples)​         |
| ------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
| Java          | ​[javadoc](https://strongdm.github.io/strongdm-sdk-java-docs/)​            | ​[strongdm-sdk-java](https://github.com/strongdm/strongdm-sdk-java)​     | ​[Java SDK Examples](https://github.com/strongdm/strongdm-sdk-java-examples)​     |
| Python        | ​[pdocs](https://strongdm.github.io/strongdm-sdk-python-docs/)​            | ​[strongdm-sdk-python](https://github.com/strongdm/strongdm-sdk-python)​ | ​[Python SDK Examples](https://github.com/strongdm/strongdm-sdk-python-examples)​ |
| Ruby          | ​[RubyDoc](https://www.rubydoc.info/gems/strongdm)​                        | ​[strongdm-sdk-ruby](https://github.com/strongdm/strongdm-sdk-ruby)​     | ​[Ruby SDK Examples](https://github.com/strongdm/strongdm-sdk-ruby-examples)​     |
| {% endtab %}  |                                                                            |                                                                          |                                                                                   |
| {% endtabs %} |                                                                            |                                                                          |                                                                                   |

## Resource properties

Configuration properties are visible when you add a **Resource Type** or when you click to view the server's settings. The following table describes the settings available for your SSH (Customer Managed Key) server.

<table><thead><tr><th width="200.20379638671875">Property</th><th width="130.4183349609375">Requirement</th><th>Description</th></tr></thead><tbody><tr><td><strong>Display Name</strong></td><td>Required</td><td>Meaningful name to display the resource throughout StrongDM; exclude special characters like quotes (") or angle brackets (&#x3C; or >)</td></tr><tr><td><strong>Server Type</strong></td><td>Required</td><td><strong>SSH (Customer Managed Key)</strong></td></tr><tr><td><strong>Proxy Cluster</strong></td><td>Required</td><td>Defaults to "None (use gateways)"; if using <a href="../../networking/proxy-clusters">proxy clusters</a>, select the appropriate cluster to proxy traffic to this resource</td></tr><tr><td><strong>Hostname</strong></td><td>Required</td><td>Hostname or IP address to which you are connecting, such as <code>testserver-01.example.org</code>; relay server should be able to <a href="#prerequisites">connect to your target server</a> or hostname</td></tr><tr><td><strong>Port</strong></td><td>Required</td><td>Port to connect to the resource; default port value <strong>22</strong></td></tr><tr><td><strong>Connectivity Mode</strong></td><td>Required</td><td>Select either <strong>Virtual Networking Mode</strong>, which lets users connect to the resource with a software-defined, IP-based network; or <strong>Loopback Mode</strong>, which allows users to connect to the resource using the local loopback adapter in their operating system; this field is shown if <a href="../../clients/client-networking/virtual-networking-mode">Virtual Networking Mode</a> enabled for your organization</td></tr><tr><td><strong>IP Address</strong></td><td>Optional</td><td>If <strong>Virtual Networking Mode</strong> is the selected connectivity mode, an IP address value in the configured Virtual Networking Mode subnet in the organization network settings; if <strong>Loopback Mode</strong> is the selected connectivity mode, an IP address value in the configured Loopback IP range in the organization network settings (by default, <code>127.0.0.1</code>); if not specified, an available IP address in the configured IP address space for the selected connectivity mode will be automatically assigned; this field is shown if <a href="../../clients/client-networking/virtual-networking-mode">Virtual Networking Mode</a> and/or <a href="../../clients/client-networking/loopback-ip-ranges">multi-loopback mode</a> is enabled for your organization</td></tr><tr><td><strong>Port Override</strong></td><td>Optional</td><td>If <strong>Virtual Networking Mode</strong> is the selected connectivity mode, a port value between 1 and 65535 that is not already in use by another resource with the same IP address; if <strong>Loopback Mode</strong> is the selected connectivity mode, a port value between 1024 to 64999 that is not already in use by another resource with the same IP address; when left empty with Virtual Networking Mode, the system assigns the default port to this resource; when left empty for Loopback Mode, an available port that is not already in use by another resource is assigned; preferred port also can be modified later from the <a href="../port-overrides">Port Overrides settings</a></td></tr><tr><td><strong>DNS</strong></td><td>Optional</td><td>If Virtual Networking Mode is the selected connectivity mode, a unique hostname alias for this resource; when set, causes the desktop app to display this resource's human-readable DNS name (for example, <code>k8s.my-organization-name</code>) instead of the bind address that includes IP address and port (for example, <code>100.64.100.100:5432</code>)</td></tr><tr><td><strong>Secret Store</strong></td><td>Optional</td><td>Credential store location; defaults to none (credentials are stored in StrongDM resource configuration); to learn more, see <a href="#secret-store-options">Secret Store options</a></td></tr><tr><td><strong>Authentication</strong></td><td>Required</td><td>Select <strong>Leased Credentials</strong> (default) or <strong>Identity Aliases</strong></td></tr><tr><td><strong>Username</strong></td><td>Required</td><td>Displays if <strong>Authentication</strong> is set to <strong>Leased Credentials</strong> and using StrongDM Secret Store; enter the username the relay should utilize to connect to the server via SSH (for example, <code>bob.belcher</code>)</td></tr><tr><td><strong>Username (path)</strong></td><td>Required</td><td>Displays if <strong>Authentication</strong> is set to <strong>Leased Credentials</strong> and using a non-StrongDM Secret Store; path to the secret in your Secret Store location (for example, <code>path/to/credential?key=optionalKeyName</code> where key argument is optional)</td></tr><tr><td><strong>Identity Set</strong></td><td>Required</td><td>Displays if <strong>Authentication</strong> is set to <strong>Identity Aliases</strong>; select an Identity Set name from the list</td></tr><tr><td><strong>Healthcheck Username</strong></td><td>Required</td><td>Displays if <strong>Authentication</strong> is set to <strong>Identity Alias</strong>; enter the username that will be utilized to verify StrongDM's connection to the server; username must exist on the target server</td></tr><tr><td><strong>Private Key</strong></td><td>Required</td><td>The key in either plaintext or Base64 encoding; paste the key or import the key</td></tr><tr><td><strong>Allow Port Forwarding</strong></td><td>Optional</td><td>When enabled, allows SSH connections proxied by StrongDM for this server to accept local forwarding requests; this checkbox is shown when the <strong>Allow port forwarding through SSH?</strong> option is turned on in the Admin UI security settings; see <a href="port-forwarding">Port Forwarding</a> for more information</td></tr><tr><td><strong>Resource Lock Required</strong></td><td>Required</td><td>Enables a resource lock, which can lock access the resource to ensure it can only be used by one user at a time; defaults to disabled</td></tr><tr><td><strong>Resource Tags</strong></td><td>Optional</td><td>Resource <a data-mention href="https://app.gitbook.com/s/4XOJmXFslCMVCzIG2rKp/cli/tags">Tags</a> consisting of key-value pairs <code>&#x3C;KEY>=&#x3C;VALUE></code> (for example, <code>env=dev</code>)</td></tr></tbody></table>

### Secret Store options

By default, server credentials are stored in StrongDM. However, these credentials can also be saved in a secrets management tool.

Non-StrongDM options appear in the **Secret Store** dropdown if they are created under **Settings** > **Secrets Management**. When you select another Secret Store type, its unique properties display. For more details, see [Configure Secret Store Integrations](https://docs.strongdm.com/admin/access/secret-stores).

**Identity Aliases and third-party Secret Stores**

When you use Identity Aliases in combination with a third-party Secret Store, it is possible to provide different keys for different Identity Aliases. During server configuration, the **Private Key (path)** field, which specifies the path to the SSH private key in the Secret Store, can optionally include the variable `$SDM_USERNAME`. This variable is substituted with the user's Identity Alias when connecting to the resource. This allows a different SSH key to be used for different Identity Aliases connecting to the same resource.

For example, you could set **Private Key (path)** to `path/to/credential/for/$SDM_USERNAME?key=ssh-key` and store the keys for different users in the Secret Store under paths matching that pattern (`path/to/credential/for/user1`, `path/to/credential/for/user2`, ...`path/to/credential/for/userN`). This is optional. If the path you provide does not include the variable, the same SSH key is used for each user. This is only supported for secret stores.

## Add Your Key to Your Hosts

If you have not already done so, add your public key to the targeted host.

1. Open a command prompt on the server you are adding and edit the authorized keys file for the user specified during server setup.

   ```bash
    sudo vi ~/.ssh/authorized_keys
   ```
2. Append the generated public key to the end of the file, save, and exit.
3. Back in the Admin UI, go to the **Servers** section and click the server's name to view status, diagnostic information, and setting details.
4. In the server settings, click the **Update** button.

The Admin UI displays that resource as unhealthy while the configuration is being applied. When the resource is ready, the **Health** icon indicates a positive, green status.

## Test the Connection

1. In the Admin UI, locate your new resource and observe that its Health status eventually turns green when StrongDM successfully connects.
2. From a user machine (via StrongDM Desktop or the CLI), attempt to connect to the resource. The connection uses the private key you provided behind the scenes and authenticates as the specified user.
3. On the host, run `whoami`, `hostname`, or inspect `/var/log/auth.log` (or the equivalent) for evidence of the SSH login event.
4. If the resource remains Unhealthy, check the following:
   * The public key installed in the host’s `authorized_keys` exactly matches the key derived from your private key.
   * The username configured in StrongDM matches the login user.
   * The StrongDM node can reach the host (test connectivity).
   * SSH daemon logs show no errors regarding key format or permissions.
   * The `.ssh` directory and `authorized_keys` file have correct ownership & permissions.

If you encounter issues, please consult the [StrongDM Help Center](https://help.strongdm.com/hc/en-us).


---

# 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.strongdm.com/admin/resources/servers/ssh-customer-key.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.
