# Join Services with a Secure Token

In this guide, we will show you how to register a Teleport process running one or more services to your cluster by presenting a **join token**.

In this approach, you declare your intention to register a new Teleport process, and Teleport generates a secure token that the process uses to establish a trust relationship with the Teleport cluster.

## Prerequisites

- A running Teleport cluster. If you want to get started with Teleport, [sign up](https://goteleport.com/signup) for a free trial or [set up a demo environment](https://goteleport.com/docs/get-started/deploy-community.md).

- The `tctl` and `tsh` clients.

  Installing `tctl` and `tsh` clients

  1. Determine the version of your Teleport cluster. The `tctl` and `tsh` clients must be at most one major version behind your Teleport cluster version. Send a GET request to the Proxy Service at `/v1/webapi/find` and use a JSON query tool to obtain your cluster version. Replace teleport.example.com:443 with the web address of your Teleport Proxy Service:

     ```
     $ TELEPORT_DOMAIN=teleport.example.com:443
     $ TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.server_version')"
     ```

  2. Follow the instructions for your platform to install `tctl` and `tsh` clients:

     **Mac**

     Download the signed macOS .pkg installer for Teleport, which includes the `tctl` and `tsh` clients:

     ```
     $ curl -O https://cdn.teleport.dev/teleport-${TELEPORT_VERSION?}.pkg
     ```

     In Finder double-click the `pkg` file to begin installation.

     ---

     DANGER

     Using Homebrew to install Teleport is not supported. The Teleport package in Homebrew is not maintained by Teleport and we can't guarantee its reliability or security.

     ---

     **Windows - Powershell**

     ```
     $ curl.exe -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-windows-amd64-bin.zip
     Unzip the archive and move the `tctl` and `tsh` clients to your %PATH%
     NOTE: Do not place the `tctl` and `tsh` clients in the System32 directory, as this can cause issues when using WinSCP.
     Use %SystemRoot% (C:\Windows) or %USERPROFILE% (C:\Users\<username>) instead.
     ```

     **Linux**

     All of the Teleport binaries in Linux installations include the `tctl` and `tsh` clients. For more options (including RPM/DEB packages and downloads for i386/ARM/ARM64) see our [installation page](https://goteleport.com/docs/installation.md).

     ```
     $ curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ tar -xzf teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ cd teleport
     $ sudo ./install
     Teleport binaries have been copied to /usr/local/bin
     ```

* A Linux server that you will use to host your Teleport process, e.g., a virtual machine or Docker container with an image based on a Linux distribution.

  In this guide, we will show you how to register a Teleport SSH Service instance. This approach also applies to other Teleport services, like the Proxy Service, Kubernetes Service, Database Service, and other services for accessing resources in your infrastructure.

  Running multiple Proxy Service instances behind a load balancer

  The join token method works if a cluster includes a single Proxy Service instance as well as multiple Proxy Service instances behind a load balancer (LB) or a DNS entry with multiple values. If there are multiple Proxy Service instances, a Teleport process joining the cluster establishes a tunnel to every Proxy Service instance.

  If you are using a load balancer, it must use a round-robin or a similar balancing algorithm. Do not use sticky load balancing algorithms (i.e., "session affinity") with Teleport Proxy Service instances.

  ---

  TIP

  If you are using a Docker container, note that this guide assumes that your Linux host has `curl` and `sudo` installed.

  ---

* One of the following client tools for managing Teleport resources:

  - The `tctl` CLI, which you can install along with Teleport on your workstation ([documentation](https://goteleport.com/docs/installation.md)) on your workstation.
  - [Teleport Terraform provider](https://goteleport.com/docs/zero-trust-access/infrastructure-as-code/terraform-provider.md)
  - [Teleport Kubernetes operator](https://goteleport.com/docs/zero-trust-access/infrastructure-as-code/terraform-provider.md)

  If you're managing Teleport resources with the Teleport Kubernetes operator, this guide assumes that your resource manifests are placed together in a Helm chart.

## Step 1/3. Install Teleport

Install Teleport on your Linux host.

To install a Teleport Agent on your Linux server:

The recommended installation method is the cluster install script. It will select the correct version, edition, and installation mode for your cluster.

1. Assign teleport.example.com:443 to your Teleport cluster hostname and port, but not the scheme (https\://).

2. Run your cluster's install script:

   ```
   $ curl "https://teleport.example.com:443/scripts/install.sh" | sudo bash
   ```

## Step 2/3. Join your Teleport process to the cluster

In this section, we will join your Teleport process to your cluster by:

- Obtaining a join token
- Running your Teleport process with the join token

### Generate a token

Teleport only allows access to resources in your infrastructure via Teleport processes that have joined the cluster (i.e., **Teleport Agents**). Generate a token that the Teleport Auth Service can compare to a value that your Teleport process presents when it joins the cluster.

You can create the token with `tctl` as well as the Teleport Terraform provider or Kubernetes operator:

**tctl**

On your local machine, use the `tctl` tool to generate a new token. In the following example, a new token is created with a TTL of five minutes:

```
Generate a short-lived invite token for a new Teleport SSH Service instance:
$ tctl tokens add --ttl=5m --type=node
The invite token: abcd123-insecure-do-not-use-this
This token will expire in 5 minutes.

Run this on the new node to join the cluster:

> teleport start \
   --roles=node \
   --token=abcd123-insecure-do-not-use-this \
   --ca-pin=sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678 \
   --auth-server=192.0.2.0:3025

Please note:

  - This invitation token will expire in 5 minutes
  - 192.0.2.0:3025 must be reachable from the new node
```

In this command, we assigned the token the `node` type, indicating that it will belong to an SSH Service instance.

Copy the token so you can use it later in this guide. You can ignore the rest of the `tctl tokens add` output.

Supported token types

Here are all the values we support for `--type` flag when creating a join token:

| Role             | Teleport Service                |
| ---------------- | ------------------------------- |
| `app`            | Application Service             |
| `auth`           | Auth Service                    |
| `bot`            | Machine & Workload Identity Bot |
| `db`             | Database Service                |
| `discovery`      | Discovery Service               |
| `kube`           | Kubernetes Service              |
| `node`           | SSH Service                     |
| `proxy`          | Proxy Service                   |
| `windowsdesktop` | Windows Desktop Service         |

Administrators can generate tokens as they are needed. A Teleport process can use a token multiple times until its time to live (TTL) expires, with the exception of tokens with the `bot` type, which are used by Machine & Workload Identity.

To list all of the tokens you have generated, run the following command:

```
$ tctl tokens ls
Token                            Type Labels Expiry Time (UTC)
-------------------------------- ---- ------ --------------------------
abcd123-insecure-do-not-use-this Node        30 Mar 23 18:15 UTC (2m8s)
```

**Terraform**

Add the following resource to your Terraform configuration, replacing values as indicated:

In this example, we declare a `random_string` resource in addition to the `teleport_provision_token` resource in order to generate a cryptographically secure value for the token:

```
resource "random_string" "token" {
  length           = 32
  override_special = "-.+"
}

resource "teleport_provision_token" "agent" {
  version = "v2"
  // use the minimal set of roles required (e.g. Node, Proxy, App, Kube, DB, WindowsDesktop)
  spec = {
    roles = ["Node"]
  }
  metadata = {
    name    = random_string.token.result
    expires = timeadd(timestamp(), "1h")
  }
}

```

**Kubernetes**

Add the following Kubernetes resource manifest, replacing values as indicated:

In this example, which assumes that you have placed the manifest in a Helm chart, we use the `randBytes` function to generate a cryptographically random token value and the `now` and `dateModify` functions to set a time to live:

```
apiVersion: "resources.teleport.dev/v2"
kind: TeleportProvisionToken
metadata:
  name: {{ randBytes 32 }}
  expires: {{ now | dateModify "+1h" }}
spec:
  # use the minimal set of roles required (e.g. Node, Proxy, App, Kube, DB, WindowsDesktop)
  roles: [Node]

```

An insecure alternative: static tokens

---

DANGER

Use short-lived tokens instead of long-lived static tokens. Static tokens are easier to steal, guess, and leak.

---

Static tokens are defined ahead of time by an administrator and stored in the Auth Service's config file:

```
# Config section in `/etc/teleport.yaml` file for the Auth Service
auth_service:
  enabled: true
  tokens:
    # This static token allows new hosts to join the cluster as "proxy" or "node"
    - 'proxy,node:secret-token-value'
    # A token can also be stored in a file. In this example the token for adding
    # new Auth Service instances are stored in /path/to/tokenfile
    - 'auth:/path/to/tokenfile'

```

### Start your Teleport process with the invite token

Execute the following command on the host running your new Teleport process to add it to a cluster. Assign join-token to the token you generated earlier and proxy-address to the host and web port of your Teleport Proxy Service or Teleport Enterprise Cloud tenant (e.g., `teleport.example.com:443`):

```
$ sudo teleport configure \
   --roles=node \
   --token=join-token \
   --proxy=proxy-address \
   -o file
```

---

TIP

For SSH Service instances, you can also run `teleport node configure` instead of `teleport configure`. This way, you can exclude the `--roles=node` flag from the command.

---

Connecting directly to the Auth Service

So far, this guide has assumed that you are joining your new Teleport process to your cluster by connecting it to the Proxy Service. (This is the only possibility in Teleport Enterprise Cloud.) Depending on the design of your infrastructure, you may need to connect your new Teleport process directly to the Auth Service.

---

WARNING

Only connect Teleport processes directly to the Auth Service if no other join methods are suitable, as we recommend exposing the Auth Service to as few sources of ingress traffic as possible.

---

The Teleport process joining the cluster must also establish trust with the Auth Service in order to prevent an attacker from hijacking the address of your Auth Service host.

To do this, you supply your new Teleport process with a secure hash value generated by the Auth Service's certificate authority, called a **CA pin**. This way, an attacker cannot easily forge a private key to trick your Teleport process into communicating with a malicious service.

### Obtain a CA pin

On you local machine, retrieve the CA pin of the Auth Service:

```
$ tctl status
Cluster      teleport.example.com
Version      12.1.1
host CA      never updated
user CA      never updated
db CA        never updated
openssh CA   never updated
jwt CA       never updated
saml_idp CA  never updated
CA pin       sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678
```

Copy the CA pin and assign it to the value of ca-pin.

---

WARNING

The CA pin becomes invalid if a Teleport administrator performs the CA rotation by executing [`tctl auth rotate`](https://goteleport.com/docs/reference/cli/tctl.md#tctl-auth-rotate).

---

### Configure your Teleport process with the join token and CA pin

Run the following command to configure your Teleport process instead of the `teleport configure` command we showed you earlier. Assign auth-service to the host and gRPC port of your Auth Service host, e.g., `teleport.example.com:3025`.

```
$ sudo teleport configure \
   --roles=node \
   --token=join-token \
   --auth-server=auth-service \
   -o file
```

Next, edit the Teleport configuration file, `/etc/teleport.yaml`, assigning the CA pin (the `teleport.ca_pin` field) to the one you copied earlier:

```
$ sudo sed -i 's|  ca_pin: ""|  ca_pin: "ca-pin"|' /etc/teleport.yaml
```

Configure your Teleport instance to start automatically when the host boots up by creating a systemd service for it. The instructions depend on how you installed your Teleport instance.

**Package Manager**

On the host where you will run your Teleport instance, enable and start Teleport:

```
$ sudo systemctl enable teleport
$ sudo systemctl start teleport
```

**TAR Archive**

On the host where you will run your Teleport instance, create a systemd service configuration for Teleport, enable the Teleport service, and start Teleport:

```
$ sudo teleport install systemd -o /etc/systemd/system/teleport.service
$ sudo systemctl enable teleport
$ sudo systemctl start teleport
```

You can check the status of your Teleport instance with `systemctl status teleport` and view its logs with `journalctl -fu teleport`.

Using a local Docker container?

If you followed this guide with a local Docker container, execute the following command within your container to run your new Teleport process in the foreground:

```
$ teleport start
```

As new services come online, they start sending heartbeat requests every few seconds to the Auth Service. This allows users to explore cluster membership and size.

Run the following command on your local machine to see all of the Teleport SSH Service instances in your cluster:

```
$ tctl nodes ls
Host          UUID                  Public Address Labels                 Version
------------- --------------------- -------------- ---------------------- -------
1f58429134c4  6805dda3-779e-493b...                hostname=1f58429134c4  18.7.3
```

## Step 3/3. Revoke an invitation

You can revoke a join token to prevent a Teleport process from using it.

Run the following command on your local machine to create a token for a new Proxy Service:

```
$ tctl nodes add --ttl=5m --roles=proxy
The invite token: abcd123-insecure-do-not-use-this.
This token will expire in 5 minutes.

Run this on the new node to join the cluster:

> teleport start \
--roles=proxy \
--token=abcd123-insecure-do-not-use-this \
--ca-pin=sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678 \
--auth-server=123.123.123.123:443

Please note:

- This invitation token will expire in 5 minutes
- 123.123.123.123 must be reachable from the new node
```

Next, run the following command to see a list of outstanding tokens:

```
$ tctl tokens ls
Token                            Type  Labels Expiry Time (UTC)
-------------------------------- ----- ------ ---------------------------
abcd123-insecure-do-not-use-this Node         30 Mar 23 18:20 UTC (36s)
efgh456-insecure-do-not-use-this Proxy        30 Mar 23 18:24 UTC (4m39s)
```

---

SIGNUP TOKENS

The output of `tctl tokens ls` includes tokens used for adding users alongside tokens used for adding Teleport processes to your cluster.

---

You generated the token with the `Node` role earlier in this guide to invite a new Teleport process to this cluster. The second token is the one you generated for a Proxy Service instance.

Tokens created via `tctl` can be deleted (revoked) via the `tctl tokens rm` command. Copy the second token from the output above and run the following command to delete it, assigning the token to token-to-delete.

```
$ tctl tokens rm token-to-delete
Token abcd123-insecure-do-not-use-this has been deleted
```

## Next steps

- If you have workloads split across different networks or clouds, we recommend setting up trusted clusters. Read how to get started in [Configure Trusted Clusters](https://goteleport.com/docs/zero-trust-access/deploy-a-cluster/trustedclusters.md).
