Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/gravitational/teleport/llms.txt

Use this file to discover all available pages before exploring further.

Teleport Machine Identity lets machines and CI/CD pipelines authenticate to your infrastructure without storing long-lived credentials. This guide walks through the complete setup: creating a bot user, writing a join token, configuring tbot, and using the issued certificates to access a Linux server or Kubernetes cluster from a GitHub Actions workflow. Even if your target platform is different from GitHub Actions, this guide covers the foundational setup that all Machine Identity deployments share. Once you have completed it, the deployment guides explain how to adapt the same pattern to other CI/CD systems and hosting environments.
This guide is intended for learning and development. For a production-ready deployment of tbot, see the tbot reference and the Teleport configuration reference.

Prerequisites

  • A running Teleport cluster (cloud or self-hosted). If you do not have one, follow the cloud quickstart or self-hosted quickstart.
  • tctl installed and authenticated as a cluster administrator.
  • A GitHub repository where you have permission to create GitHub Actions workflows.
  • At least one enrolled resource — either a Linux server or a Kubernetes cluster. If you haven’t enrolled one yet, see the server access guide or the Kubernetes access guide.

Steps

1

Choose your target resource and create a role

Before creating the bot, decide which resource it needs to access, then create (or identify) a Teleport role that grants that access.First, find the labels on your target resource:
tctl nodes ls --format=text
# Host    UUID        Public Address  Labels                  Version
# target1 8a50c8aa…                  env=mwi-demo            18.x
Note the label key/value you will use to target the resource — in the examples below we use env=mwi-demo.Now create a role file. Save one of the following as role.yaml:
kind: role
version: v7
metadata:
  name: github-bot
spec:
  allow:
    node_labels:
      env: mwi-demo
    logins:
      - ubuntu
Replace env: mwi-demo with the label that matches your resource, and ubuntu (or system:masters) with the appropriate user or group.Apply the role:
tctl create -f role.yaml
2

Create a bot user

A bot is a non-human Teleport identity. Like regular users, bots are assigned roles that control their access. Create a file called bot.yaml:
kind: bot
version: v1
metadata:
  name: github-bot
spec:
  roles:
    - github-bot
Make sure spec.roles references the role you created in the previous step. Apply it:
tctl create -f bot.yaml
You can verify the bot was created with:
tctl bots ls
3

Create a join token

Bots authenticate using join tokens rather than passwords. A join token specifies which bot user it grants access to and what cryptographic proof the bot must present. Because we are using GitHub Actions, we will use the github join method, which relies on the OIDC token that GitHub issues to every workflow run.Create a file called join_token.yaml:
kind: token
version: v2
metadata:
  name: github-bot
spec:
  join_method: github
  roles:
    - Bot
  bot_name: github-bot
  github:
    allow:
      - repository: "your-github-username/my-repo"
    # enterprise_server_host: github.my-company.com  # for self-hosted GitHub Enterprise
    # enterprise_slug: my-company                    # for GitHub Enterprise Cloud
Replace your-github-username/my-repo with the full name of your GitHub repository. Only workflows running from that repository will be allowed to join.Apply the join token:
tctl create -f join_token.yaml
The github join method requires no shared secret. Teleport validates the OIDC JWT that GitHub provides to every workflow run — meaning your repository never needs to store a Teleport credential.
4

Configure tbot.yaml

tbot is driven by a configuration file that specifies how it authenticates, where it stores its internal state, and what credentials it should write out. Create tbot.yaml at the root of your GitHub repository:
version: v2
proxy_server: example.teleport.sh:443
onboarding:
  join_method: github
  token: github-bot
credential_ttl: 5m
storage:
  type: memory
services:
  - type: identity
    destination:
      type: directory
      path: ./ssh_out
Replace:
  • example.teleport.sh:443 — your Teleport Proxy address
  • github-bot — the token name from the previous step
  • my-kubernetes-cluster — the name of your cluster as registered in Teleport
The credential_ttl: 5m value means credentials expire after 5 minutes. Tune this to match the expected duration of your job.Commit and push tbot.yaml to your repository.
5

Run tbot and use the certificate

Now create the GitHub Actions workflow file. Add .github/workflows/teleport.yaml to your repository:
on:
  workflow_dispatch:

jobs:
  check_resource_usage:
    permissions:
      id-token: write   # required for Machine Identity
      contents: read
    name: Check resource usage on server
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Fetch Teleport binaries
        uses: teleport-actions/setup@v1
        with:
          proxy: example.teleport.sh:443
          version: auto

      - name: Authenticate and issue SSH credentials
        run: tbot start --oneshot -c ./tbot.yaml

      - name: Run command via SSH
        run: |
          ssh -F ./ssh_out/ssh_config ubuntu@myinstance.example.teleport.sh mpstat
Replace example.teleport.sh:443 and (for the SSH workflow) myinstance.example.teleport.sh and ubuntu with values matching your environment.The --oneshot flag makes tbot issue credentials once and exit, which is the right behavior for a CI job. When tbot runs as a long-running daemon, it instead renews credentials automatically before they expire.Commit and push the workflow file. Then trigger it from the Actions tab in GitHub, or using the GitHub CLI:
gh workflow run teleport.yaml --ref main
After the workflow completes successfully, you will see the output of mpstat or kubectl get pods in the workflow logs — issued using a short-lived certificate that was never stored anywhere.

What happens under the hood

When the GitHub Actions workflow runs, the following sequence occurs:
  1. GitHub issues an OIDC JWT to the workflow run. This token encodes the repository, branch, and other workflow metadata.
  2. tbot start --oneshot presents this JWT to the Teleport Auth Service along with the join token name.
  3. The Auth Service validates the JWT against GitHub’s OIDC endpoint and checks that the repository matches the allow-list in your join token.
  4. If the checks pass, the Auth Service issues a short-lived x.509 certificate for the github-bot bot user.
  5. tbot writes SSH credentials or a kubeconfig to the configured output directory.
  6. The subsequent workflow step uses those credentials to connect through the Teleport Proxy to the target resource.
  7. The credentials expire after 5 minutes (or whatever credential_ttl is set to).
At no point is a Teleport credential stored in the GitHub repository or in GitHub’s secrets vault.

Next steps

tbot Reference

Learn about all tbot configuration options, output types, and daemon vs one-shot modes.

Workload Identity

Issue SPIFFE-compatible SVIDs for service-to-service authentication and cloud API access.

RBAC

Learn how to write fine-grained roles to control exactly what your bots can access.

Audit Events

See how bot activity, certificate issuance, and resource access are recorded in audit logs.

Build docs developers (and LLMs) love