Skip to main content

Ansible

Report an Issue

Ansible uses the OpenSSH client by default. Teleport supports SSH protocol and works as SSH jumphost.

In this guide, you will configure OpenSSH client to work with Teleport Proxy and run a sample ansible playbook.

How it works

In the setup we describe in this guide, you generate an OpenSSH configuration that uses a Teleport-issued SSH certificate to connect to Teleport-protected servers. You then provide this OpenSSH configuration to your Ansible host, along with an inventory of Teleport-protected servers. Ansible then uses the OpenSSH configuration to present the Teleport-issued credentials in order to manage your servers.

Prerequisites

  • A running Teleport cluster accessible at a hostname with a valid TLS certificate. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.

  • 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:

      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.

    Connecting with TLS routing disabled

    This guide's commands assume your Teleport cluster uses TLS routing (proxy_listener_mode: multiplex), where the tctl and tsh clients reach every Teleport service through the Proxy Service's web address on port 443. If you're not sure whether this applies to your cluster, check with whoever manages it.

    If your cluster uses separate listener ports instead, adjust ports as follows:

    • tsh commands (e.g., tsh login --proxy=...): continue using the Proxy Service web address on port 3080 (or 443 if behind a load balancer). Do not change these to port 3025.

    • Direct tctl or Auth Service API commands: use port 3025 for the Auth Service gRPC listener:

      tctl status --auth-server=teleport.example.com:3025
  • ssh openssh tool
  • ansible >= 2.9.6
  • Optional tool jq to process JSON output.
Headless and automated environments

This guide uses interactive tsh login. For headless environments, CI/CD pipelines, or automation, use Machine ID (tbot) to issue short-lived credentials without interactive authentication.

Step 1/3. Login and configure SSH

Log into Teleport with tsh:

tsh login --proxy=teleport.example.com

Generate openssh configuration using tsh config shortcut:

tsh config > ssh.cfg
tip

You can edit matching patterns used in ssh.cfg if something is not working out of the box.

Step 2/3. Configure Ansible

Create a folder ansible where we will collect all generated files:

mkdir -p ansible

Copy the openssh configuration from the previous step to the ansible dir

cp ssh.cfg ansible/
cd ansible

Create a file ansible.cfg:

[defaults]
host_key_checking = True
inventory=./hosts
remote_tmp=/tmp

[ssh_connection]
scp_if_ssh = True
ssh_args = -F ./ssh.cfg

You can create an inventory file hosts manually or use a script below to generate it from your environment. Set your cluster name (e.g. teleport.example.com or in the form mytenant.teleport.sh for Teleport Enterprise Cloud) and this script will generate the host names to match the openssh configuration:

tsh ls --format=json | jq '.[].spec.hostname + ".teleport.example.com"' > hosts

Step 3/3. Run a playbook

Finally, let's create a simple ansible playbook playbook.yaml.

The playbook below runs hostname on all hosts. Make sure to set the remote_user parameter to a valid SSH username that works with the target host and is allowed by Teleport:

- hosts: all
  remote_user: ubuntu
  tasks:
    - name: "hostname"
      command: "hostname"

From the folder ansible, run the ansible playbook:

ansible-playbook playbook.yaml

PLAY [all] *****************************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************************

ok: [terminal]

TASK [hostname] ************************************************************************************************************************************

changed: [terminal]

PLAY RECAP *****************************************************************************************************************************************

terminal : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

You are all set. You are now using short-lived SSH certificates and Teleport can now record all ansible commands in the audit log.

Troubleshooting

In cases where Ansible cannot connect, you may see an error like this:

example.host | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname example.host: Name or service not known",
    "unreachable": true
}

You can examine and tweak patterns matching the inventory hosts in ssh.cfg.

Try the SSH connection using ssh.cfg with verbose mode to inspect the error:

ssh -vvv -F ./ssh.cfg root@example.host

If ssh works, try running the playbook with verbose mode on:

ansible-playbook -vvvv playbook.yaml

If your hostnames contain uppercase characters (like MYHOSTNAME), please note that Teleport's internal hostname matching is case sensitive by default, which can also lead to seeing this error.

If this is the case, you can work around this by requesting that your Teleport administrator enable case-insensitive routing at the cluster level. For admins, it is possible to enable case-insensitive routing using the following instructions:

Edit your /etc/teleport.yaml config file on all servers running the Teleport auth_service, then restart Teleport on each.

auth_service:
  case_insensitive_routing: true