# Nodes in Docker Containers

A node in your StrongDM network is either a gateway or a relay. You can find out more about them in the [Nodes](/admin/networking/gateways-and-relays.md) section of the documentation.

This guide describes how to do the following:

1. Create a standard gateway or relay in your Docker container.
2. Create a self-registering gateway or relay in your Docker container.

### Prerequisites

You can install your gateways or relays using either the [StrongDM Node Docker Image](#the-strongdm-relay-binary) or your existing Docker image; however, the configuration options in this guide assume you deployed, or will deploy, the StrongDM Node Docker Image.

Gateways and relays *must* be installed on "always up" Docker machines, as they form the connection to StrongDM for all users accessing the resources behind it. You may repurpose a preexisting machine (for example, bastion host), or in AWS parlance, any general purpose instance with 2 CPUs and 4 GBs memory. For example, the M3s or M4s are a good option.

{% hint style="warning" %}
When setting up Docker gateways or relays, it is recommended to run `sdm` as root to allow gateways or relays to upgrade themselves automatically. If gateways or relays do not update automatically, this may cause incompatibilities between versions, which may result in access interruptions for your end users.
{% endhint %}

### Gateway and Relay Differences

Because gateways are functionally different from relays, in that they listen for and accept incoming connections, it is important to note the following:

* If you configure a gateway, you must know the host address before you start because the relay token must be passed.
* If you create a relay token within StrongDM, you have to know the gateway address ahead of time. Once it is registered and you have the token, then you can pass the token into your Docker image.

Additionally, for self-registering gateways or relays, you must figure out which address a gateway or relay listens on. Once that is done, the gateway or relay registers itself with StrongDM, retrieves the token, and so forth.

### Standard Gateways and Relays

This section walks you through the process of setting up a gateway or relay using the StrongDM Node Docker Image.

1. Add your gateway/relay to the Admin UI and generate a token for it.
   1. Log into the Admin UI and select **Gateways** in the left navigation.
   2. Click the **Add gateway** button in the upper right, and a box will pop up.
   3. Name the gateway, set the advertised host, and set the port. The **Advertised host** should be the IP address or host that the gateway listens on. Select a **TCP port** (default **5000**) for the service to listen on.
   4. Click on **create** and the token appears onscreen.
   5. Copy the token and put it aside, being careful to capture every character. You will need it again below. See [sdm admin nodes create-gateway](/references/cli/admin/nodes/create-gateway.md) if you want to generate a token via the CLI.

{% hint style="info" %}
If you intend to create a relay instead of a gateway, click **Add relay**, fill in the name, and click **Create**.
{% endhint %}

2. Execute the Docker command `docker pull public.ecr.aws/strongdm/relay` to download the StrongDM Node Docker Image. Note that you may obtain the same link from the Admin UI's **Downloads & Install** page.
3. To activate your gateway/relay, type the following Docker command replacing \<YOUR\_TOKEN> with the actual token you created:

   ```shell
    docker run --restart=always [--net=host] --name sdm-relay -e SDM_RELAY_TOKEN=<YOUR_TOKEN> -p 5000:5000 -d public.ecr.aws/strongdm/relay
   ```

   The `net=host` option is only necessary if the destination database is known as `localhost` (if you are running sdm-relay colocated with the resource), otherwise the Docker default works. If the destination database is already in a container, we can provide a separate pattern for configuring Docker container linking.
4. Log in to the Admin UI. In that section, the gateway/relay you created appears **Online**, with a heartbeat.

### Self-Registering Gateways and Relays

This section describes how to create a self-registering gateway or relay. The process involves modifying the default StrongDM Node Docker Image to take an [admin token](/admin/principals/admin-tokens.md) that generates its own relay token with the purpose of registering itself to your StrongDM organization.

{% hint style="info" %}
Note that STDOUT logging is on by default in the StrongDM client Docker image. For more information, see `SDM_DOCKERIZED` in [Environment Variables](/admin/deployment/environment-variables.md).
{% endhint %}

#### Generate the token

You can generate an admin token that has only one function: to create relay tokens. To do this, follow these steps:

1. In the Admin UI, go to section **Principals** > **Tokens** and click **Add token**.
2. On the **Create Admin Token** page, under **Relays**, select the checkbox for **Create**.
3. Click the **Create** button at the bottom.
4. Copy the token that is generated, as you will need it later.

{% hint style="info" %}
For more detailed information on creating admin tokens, see [Admin Tokens](/admin/principals/admin-tokens.md).
{% endhint %}

#### Create the new Dockerfile

You can modify the default [StrongDM relay binary](https://gallery.ecr.aws/strongdm/relay), which is included in the StrongDM Node Docker Image, by creating and building a new Dockerfile. Use the following file to define your new Docker image. Save it as `autoreg.dock` in a directory on a system with Docker installed.

```docker
# Use the following command to build the Dockerfile.
# docker build -f autoreg.dock .
FROM public.ecr.aws/strongdm/relay:latest
ADD autoreg.sh /autoreg.sh
RUN chmod a+x /autoreg.sh
ENTRYPOINT ["/autoreg.sh"]
```

Note that this file references a shell script. Use the following file as `autoreg.sh`, which should be saved in the same directory as `autoreg.dock`.

```bash
#!/bin/bash
CMD=/sdm.linux
if [ -f /sdm/.sdmrc ]
then
	unset SDM_ADMIN_TOKEN
	# set the relay token env variable
	source /sdm/.sdmrc
else
	# necessary to suppress stdout during token create
	unset SDM_DOCKERIZED
	# generate fresh relay token (depends on inheriting SDM_ADMIN_TOKEN)
	SDM_RELAY_TOKEN=$($CMD relay create)
    export SDM_RELAY_TOKEN
	# retain the relay token
	echo "export SDM_RELAY_TOKEN=${SDM_RELAY_TOKEN}" >/sdm/.sdmrc
	# temporary auth state is created by invoking `relay create` and must be cleared out prior to relay startup
	rm /root/.sdm/*
	unset SDM_ADMIN_TOKEN
	export SDM_DOCKERIZED=true # reinstate stdout logging
fi
# --daemon arg automatically respawns child relay process during version upgrades or abnormal termination
$CMD relay --daemon
```

{% hint style="info" %}
It is important to understand why each command is in this script:

* First, unset `SDM_DOCKERIZED` to turn off STDOUT logging, so when you run `$CMD relay create` it is only outputting the token itself.
* Next, turn off admin authentication by removing the token in `SDM_ADMIN_TOKEN` and deleting the `.sdm` directory. Otherwise, when you run the relay, it attempts to authenticate with the admin token.
* Finally, turn on `SDM_DOCKERIZED` and run the relay command. The `--daemon` flag is needed to ensure the relay automatically restarts itself in case of upgrades or abnormal terminations.
  {% endhint %}

With `autoreg.dock` and `autoreg.sh` in place, run the following command to generate the Dockerfile, taking note of the output image name.

```bash
$ docker build -f autoreg.dock .
[+] Building 1.3s (8/8) FINISHED                                                                                                                                   docker:default => [internal] load build definition from autoreg.dock                                                                                                                       0.0s
=> => transferring dockerfile: 252B                                                                                                                                         0.0s
=> [internal] load metadata for public.ecr.aws/strongdm/relay:latest                                                                                                        0.6s
=> [internal] load .dockerignore                                                                                                                                            0.0s
=> => transferring context: 2B                                                                                                                                              0.0s
=> [internal] load build context                                                                                                                                            0.0s
=> => transferring context: 816B                                                                                                                                            0.0s
=> CACHED [1/3] FROM public.ecr.aws/strongdm/relay:latest@sha256:fa4604d08a6d633d13cf56721677c8157dc74ee1f90d5620da8163aa3bbed080                                           0.0s
=> [2/3] ADD autoreg.sh /autoreg.sh                                                                                                                                         0.1s
=> [3/3] RUN chmod a+x /autoreg.sh                                                                                                                                          0.4s
=> exporting to image                                                                                                                                                       0.1s
=> => exporting layers                                                                                                                                                      0.1s
=> => writing image sha256:1478948b3cd63707f1d0434b7adeb4ccabb64d7172078c39c4945ec9966a7097                                                                                 0.0s
```

#### Run the new Docker container

Similarly to creating a normal Docker node, you must invoke this Docker image with an environment variable. Replace **\<ADMIN\_TOKEN>** with the admin token you generated above, and with the ID of the Docker image you just generated.

```bash
docker run --restart=always [--net=host] --name sdm-relay -e SDM_ADMIN_TOKEN=<ADMIN_TOKEN> -d <ID>
```

{% hint style="info" %}
The `--net=host` option is only necessary if the destination database is known as localhost (running sdm-relay colocated with the DB). If you plan to use these instructions to generate arbitrary numbers of relays, be sure to account for this in the `--name` flag by removing it or generating a new name for each relay.
{% endhint %}

#### Verify your new node

Log into the Admin UI. In that section, the node you created should appear with the **online** status and a heartbeat.


---

# 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/networking/gateways-and-relays/docker-nodes.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.
