Gravitiational Teleport is a pretty neat and lightweight open-source software that works great as a bastion host. However, some parts the documentation can be a bit vague for a first-time user so this blog entry serves as a reference material for myself, and hopefully it is also helpful to you.


Teleport is a great way to control access into a network of restricted systems. It can be used as a single-point-of-entry, or commonly known as a “bastion host”.


The same Teleport software is installed on every system, i.e. the server and the client installs the same package/binary. The software package contains the following components:


Authentication service to authenticate Clients and Nodes, and is also the Certificate Authority (CA) for the Teleport Cluster
3025 (Restricted access from Nodes only)

Web UI for public users (Clients). Tunnels SSH from Clients to Nodes. Also allows Nodes to create a reverse SSH tunnel through it for Client connections.
443 (HTTPS, can be public to Clients, should also be reachable by Nodes)

3023 (SSH Proxy, can be public to Clients)

3024 (SSH Reverse Proxy, restricted access from Nodes only)

Provides SSH access to the system.
3022 (SSH, restricted access from Proxy only)

A Teleport “Server” only requires two components – Proxy and Auth, although a Node usually runs on the Server as well.

The Nodes (“Protected Resource”) would only need to run the Node component.

Server setup

In the example below, I am using an Amazon Linux 2 instance. You can refer to the installation docs for other distros.


  1. Set up an instance with a public IP address
  2. Set up a DNS hostname that resolves to the public IP address correctly (this is required for LetsEncrypt)
  3. Ensure the following TCP ports are open/allowed
    1. Inbound, TCP 443, from public (required for LetsEncrypt)
    2. Inbound, TCP 3023, from Clients
    3. Inbound, TCP 3024, from Nodes
    4. Inbound, TCP 3025, from Nodes (you can omit if you use reverse tunnel for Nodes behind firewall)
    5. Outbound, TCP 3022, to Nodes

Install Teleport:

sudo yum-config-manager --add-repo
sudo yum install teleport

Configure Teleport; replace your email and DNS hostname:

sudo teleport configure \
  --acme --acme-email=<> \
  --cluster-name=<> \
  -o file

At this point, you should realise that the configuration file is /etc/teleport.yaml. This file controls how and what component Teleport runs.

Start Teleport in foreground to test/debug first:

sudo teleport start

If all goes well, you should be able to reach the web interface at HTTPS port 443. Hit CTRL+C to stop, then start it as a service:

sudo systemctl start teleport
sudo systemctl enable teleport

User management

When Teleport first starts, there are no user accounts provisioned. Add the first user:

sudo tctl users add --roles=access,editor --logins=root <username>

(This is your first interaction with the tctl command. The tctl command is the CLI admin tool for the Auth service. Type tctl to see other commands available.)

In the example above, the user is given the access and editor roles to Teleport, and can login as the Linux root user to Nodes.

To see what roles are available:

sudo tctl get roles

Once the user is added, a sign up URL is provided. Send it to the user to set up his/her Teleport account, including registering an OTP. OTP is mandatory.

Note that Teleport does not create the logins on the Nodes. If the login does not exist, an attempt by the user to access the Node will simply fail.

Node setup

In the example below, I am using an Ubuntu instance. You can refer to the installation docs for other distros.


  • Ensure the following TCP ports are open/allowed
    • Inbound, TCP 3022, from Proxy
    • Outbound, TCP 443 and 3024, to Proxy

Install Teleport:

curl | sudo apt-key add -
sudo add-apt-repository 'deb stable main'
sudo apt-get update && apt-get install teleport

From the bastion host (Server), generate a temporary token used to join a node:

sudo tctl tokens add --type=node --ttl=5m
sudo tctl tokens ls # View tokens and expiry

The --ttl=5m option sets a short 5 minute expiry for the token. Tokens are one-time-use only, so after a server has used the token, it should either expire or we should remove it.

Copy the output from the tctl tokens add command and run it on the Node to join:

sudo teleport start \
  --roles=node \
  --token=xxxx \
  --ca-pin=sha256:xxxx \

Note: If you change auth-server from the default port 3025 to port 443, the Node will join via reverse tunnel.

The above command starts Teleport in the foreground for debug/testing. If Teleport registers successfully, you should see it appear on the Web UI. Hit CTRL+C to shut down Teleport on the Node.

Create a file /etc/teleport.yaml on the node; replace nodename and ca_pin:

  nodename: <your node name here; does not need to be a fqdn>
  ca_pin: "sha256:xxxx"

  enabled: true
  enabled: false
  enabled: false

Fix permissions to ensure that only root can access /etc/teleport.yaml:

sudo chown root:root /etc/teleport.yaml
sudo chmod 0600 /etc/teleport.yaml

Now, start the Teleport service and test if you are able to reach via Server’s Web UI:

sudo systemctl start teleport
sudo systemctl enable teleport

Access control

Control of access privileges is dependent upon the individual Node’s provision of the login user.

For example, if I had the following users on my Nodes:

Linux LoginNode ANode BNode C
engineerCan sudoCan sudoCan sudo
developerCan only view logsCan sudo(No account)

… and I provision the following users, the resultant access would be:

Teleport UserCan login asResult of access
user1engineerCan login to all Nodes and run sudo
user2developerCan view logs on Node A
Can sudo on Node B
Can’t login to Node C

Note that the provisioned user on the Node does not need to have a password or SSH key, but must have a valid shell.