Running an Ansible Playbook on a Remote Host (Including Kerberos kinit Auth)

Automating server configuration is one of the highest-leverage things an infrastructure team can do, and Ansible is the tool most teams reach for. The promise is simple: write your desired state once, then run an Ansible playbook against any number of remote machines. But the moment you move past a lab and into mixed environments, the connection layer gets interesting fast, especially when Kerberos and Active Directory enter the picture.

This guide walks through running an Ansible playbook on a remote host the standard way (over SSH to RHEL/Linux), then covers the Kerberos angle: how `kinit admin@REALM` fits in when your targets authenticate against AD or speak WinRM.

Key Takeaways
Ansible is agentless and connects to Linux remote hosts over SSH by default, no agent to install on the target.
• An inventory lists your hosts, a playbook defines tasks, and `ansible-playbook -i inventory site.yml` runs it.
• For Linux, SSH key authentication plus `become: yes` for privilege escalation is the standard path.
• For Kerberos/AD-integrated hosts (notably Windows over WinRM), you authenticate out of band with `kinit` first, then Ansible rides the existing ticket.
• The most common Kerberos gotcha is ticket expiry mid-run, a long playbook can outlive its TGT.

How does Ansible connect to and run on a remote host?

The foundational thing to understand is that Ansible is agentless. There is no daemon to install or maintain on your managed nodes. Instead, the control node (the machine where you run `ansible-playbook`) opens a connection to each target, pushes small modules over that connection, executes them, and collects the results.

For Linux and RHEL hosts, that connection is SSH. If you can SSH into a box, you can almost certainly manage it with Ansible. Three pieces work together:

  • Inventory — a file (INI or YAML) that lists the hosts and groups you want to manage.
  • Playbook — a YAML file describing the tasks, roles, and desired state.
  • The `ansible-playbook` command — the runner that ties an inventory to a playbook.

A minimal inventory in INI format looks like this:

“`ini [webservers] web1.example.com web2.example.com

[webservers:vars] ansible_user=deploy ansible_ssh_private_key_file=~/.ssh/id_ed25519 “`

And a minimal playbook (`site.yml`):

“`yaml


  • name: Configure web servers

hosts: webservers become: yes tasks:

  • name: Ensure nginx is installed

ansible.builtin.dnf: name: nginx state: present

  • name: Ensure nginx is running and enabled

ansible.builtin.service: name: nginx state: started enabled: yes “`

You run it with:

“`bash ansible-playbook -i inventory site.yml “`

That single command connects to every host in the `webservers` group, installs nginx, and ensures the service is enabled, idempotently.

How do you set up SSH key authentication for a Linux remote host?

Password prompts do not scale and they break automation. The standard path for a Linux remote host is SSH key authentication.

First, generate a key pair on the control node if you do not already have one:

“`bash ssh-keygen -t ed25519 -C “ansible-control” “`

Then copy the public key to each target host:

“`bash ssh-copy-id [email protected] “`

Once the key is in place, verify a passwordless login works:

“`bash ssh [email protected] “`

You can confirm Ansible reaches every host before running real tasks by using the `ping` module, which checks connectivity and the Python interpreter, not ICMP:

“`bash ansible -i inventory webservers -m ping “`

A successful run returns `pong` from each host.

Handling privilege escalation with become

Most useful work, installing packages, editing system files, restarting services, requires root. On RHEL you escalate with `sudo`, and Ansible wraps that through become.

Set it at the play level (`become: yes` as shown above), or per task. If `sudo` itself needs a password, supply it at runtime:

“`bash ansible-playbook -i inventory site.yml –ask-become-pass “`

Best practice is to grant the Ansible user passwordless `sudo` for the specific commands it needs, or `NOPASSWD` for the deploy account in controlled environments, so unattended runs do not stall on a prompt.

When do you need Kerberos instead of plain SSH keys?

SSH keys cover most Linux fleets. But many enterprises run hosts that authenticate against Active Directory or a Kerberos realm, and there the model shifts. Two scenarios are common:

  1. Windows hosts managed over WinRM. Ansible talks to Windows not over SSH but over WinRM, and the recommended transport for domain-joined machines is Kerberos.
  2. Kerberos-integrated Linux hosts. Some RHEL environments use SSSD/AD integration where SSH can authenticate via GSSAPI using a Kerberos ticket instead of (or alongside) keys.

In both cases the key idea is the same: you obtain a Kerberos ticket before running the playbook, and Ansible uses that ticket to authenticate.

The table below summarizes the common connection methods.

Target type Ansible connection Transport / auth Typical inventory vars
RHEL / Linux `ssh` (default) SSH key `ansible_user`, `ansible_ssh_private_key_file`
RHEL / Linux (AD-joined) `ssh` GSSAPI / Kerberos `ansible_user`, `ansible_ssh_common_args` with GSSAPI
Windows (domain-joined) `winrm` Kerberos `ansible_connection=winrm`, `ansible_winrm_transport=kerberos`
Windows (workgroup) `winrm` NTLM / basic `ansible_winrm_transport=ntlm`

Here is the part that trips up newcomers: with SSH keys, the credential lives in a file Ansible reads on demand for the whole run. With Kerberos, authentication happens out of band before Ansible even starts. You run `kinit [email protected]`, which contacts the KDC and stores a Ticket-Granting Ticket (TGT) in your credential cache. Ansible does not perform the Kerberos handshake itself, it simply *rides the ticket that already exists* in your cache. The consequence: a TGT has a finite lifetime (often ten hours, sometimes far less), and a long-running playbook can outlive its ticket and start failing partway through with cryptic authentication errors. The fix is to request a renewable ticket and extend or renew its lifetime before kicking off lengthy runs, rather than blaming the playbook.

How do you run an Ansible playbook against a Kerberos/AD host?

Start by getting a ticket. The `admin` principal here is whatever AD or realm account has rights on the targets:

“`bash kinit [email protected] “`

Confirm the ticket landed in your cache:

“`bash klist “`

You should see a valid TGT with an expiry timestamp. Note that expiry.

Inventory for a Windows host over WinRM

“`ini [windows] win-app01.example.com

[windows:vars] ansible_connection=winrm ansible_port=5986 ansible_winrm_transport=kerberos ansible_winrm_server_cert_validation=validate “`

With a valid TGT in your cache, run a Windows-oriented playbook:

“`yaml


  • name: Configure Windows app server

hosts: windows tasks:

  • name: Ensure a Windows feature is present

ansible.windows.win_feature: name: Web-Server state: present “`

“`bash ansible-playbook -i inventory windows.yml “`

Ansible authenticates the WinRM session using the Kerberos ticket you obtained with `kinit`, no password in the inventory, no secret on disk.

GSSAPI for Kerberos-integrated Linux

For an AD-joined RHEL host where you want SSH to use the same ticket, point Ansible’s SSH args at GSSAPI:

“`ini [linux_ad] rhel-ad01.example.com

[linux_ad:vars] ansible_user=admin ansible_ssh_common_args=-o GSSAPIAuthentication=yes -o GSSAPIDelegateCredentials=yes “`

The same `kinit`-then-`ansible-playbook` flow applies: get the ticket, then run.

What are the most common issues when running playbooks on remote hosts?

A short field guide to the failures you will actually hit:

  • SSH host key prompts. First connections may block on host-key verification. Pre-populate `known_hosts`, or set host key checking appropriately in `ansible.cfg` for trusted networks.
  • Permission denied (publickey). The key is not on the target, the wrong `ansible_user` is set, or file permissions on `~/.ssh` are too open.
  • kinit ticket expiry. As noted, long runs outlive the TGT. Request a renewable ticket (`kinit -r`) and renew before big jobs, or extend the realm’s ticket lifetime.
  • become password missing. Unattended runs stall waiting for a `sudo` password. Use `–ask-become-pass` interactively or configure `NOPASSWD` for the deploy account.
  • Connectivity and firewall. SSH needs port 22; WinRM over Kerberos typically needs 5986 (HTTPS). Confirm the path is open before debugging Ansible itself.
  • Clock skew. Kerberos is sensitive to time differences between client, KDC, and target. Keep NTP in sync, more than a few minutes of drift breaks ticket validation.

Reliable infrastructure to run and target your playbooks

Automation is only as dependable as the machines underneath it. DarazHost VPS and dedicated servers ship with full SSH root access, which makes them excellent Ansible targets and equally capable as a control node for managing the rest of your fleet. Because you get full control of the operating system, you can install Ansible, configure Kerberos clients, and tune SSH exactly the way your playbooks expect, no hosting-side restrictions getting in the way.

A reliable network matters for automation: dropped connections mid-playbook are a real source of partial failures, and our infrastructure is built to keep those long-running jobs connected from first task to last. With 24/7 support available whenever a run goes sideways, you have a team to lean on while you scale your configuration management.

Whether you are building a single control node to orchestrate a handful of servers or provisioning a fleet that your playbooks manage end to end, DarazHost gives you the predictable, fully accessible foundation that infrastructure-as-code depends on.


Frequently asked questions

Does Ansible need an agent installed on the remote host? No. Ansible is agentless. It connects over SSH (Linux) or WinRM (Windows), pushes modules, runs them, and cleans up. The only requirement on most Linux targets is SSH access and a Python interpreter.

What does `kinit admin@REALM` actually do before I run a playbook? It contacts the Kerberos KDC and obtains a Ticket-Granting Ticket stored in your credential cache. Ansible then uses that existing ticket to authenticate the WinRM or GSSAPI session. You authenticate once, out of band, rather than putting credentials in the inventory.

Why does my long playbook suddenly fail with Kerberos errors halfway through? Almost always ticket expiry. A TGT has a limited lifetime, and a long run can outlast it. Request a renewable ticket with `kinit -r` and renew it, or have your realm admin extend the ticket lifetime for automation accounts.

Can I use the same Kerberos ticket for both Windows and Linux targets? Yes, if both authenticate against the same realm. Windows uses `ansible_winrm_transport=kerberos`; AD-joined Linux uses SSH GSSAPI. Both consume the TGT from `kinit`, so one ticket can serve a mixed inventory.

How do I escalate to root on RHEL within a playbook? Use become. Set `become: yes` at the play or task level so Ansible runs the task through `sudo`. If `sudo` requires a password, pass `–ask-become-pass` or configure passwordless `sudo` for the Ansible user.

About the Author
Cristina Shank
Cristina Shank is a skilled Database Engineer with a degree from Stanford University. She specializes in optimizing and managing complex database systems, bringing a blend of technical expertise and innovative solutions to her work. Cristina is dedicated to advancing data management practices and frequently shares her insights through writing and speaking engagements.

Leave a Reply