Ansible Zero to Hero: Day-02 | Passwordless Authentication, Inventory, and Ad-hoc Commands
This chapter covers the foundational setup and execution mechanics of Ansible. It details the prerequisite of passwordless authentication, the structure and management of Ansible inventories, and the execution of one-off tasks using Ansible ad-hoc commands.
1. The Core Problem: Why Passwordless Authentication is an Ansible Prerequisite
Ansible is an agentless automation tool. Unlike other configuration management systems that require a client daemon to be installed on target machines, Ansible operates over standard Secure Shell (SSH) connections.
When a DevOps engineer issues an instruction from the Control Node (the machine where Ansible is installed) to be executed on Manage Nodes (the target virtual or physical servers), the target operating systems will naturally block the incoming connection to protect their resources.
To bypass this authentication wall, the target machines require proof of identity. Traditionally, this is done in one of two ways:
- Providing an interactive password.
- Providing an SSH private key (e.g., a
.pemfile).
If Ansible has to pause and prompt the operator for a password or key path for every single target machine during execution, the automation workflow is broken. To achieve true, uninterrupted automation—where scripts can run via CI/CD pipelines (like Jenkins) or scheduled cron jobs overnight—you must establish a trusted, passwordless communication channel between the Control Node and the Manage Nodes.
2. Mental Model: The Trust Relationship
Passwordless authentication does not mean security is disabled. Rather, it means you have pre-authorized the Control Node to access the Manage Nodes.
Real-Life Analogy
Think of passwordless authentication like a pre-approved security badge at an office building. The first time you visit the building, you must present your government ID (password or private key) to the receptionist. Once verified, they issue you a badge. For all subsequent visits, you simply swipe the badge at the turnstile to enter without standing in line or talking to the receptionist again.
In technical terms, passwordless authentication is a mechanism where you configure the Manage Node (Server B) to trust the Control Node (Server A). Once established, any service, script, or human executing commands from Server A can securely log into Server B without interactive prompts.
3. Method 1: Setting Up Passwordless Authentication via SSH Keys
This is the industry-standard approach, especially when working with cloud providers like AWS, where password-based authentication is disabled by default on EC2 instances.
Step-by-Step Implementation
-
Locate or Generate SSH Keys on the Control Node: If you do not have an SSH key pair on your Control Node, generate one using:
BASHssh-keygen -t rsa -b 4096 -
Copy the Public Key to the Manage Node: Use the
ssh-copy-idutility. This command appends your Control Node's public key to the~/.ssh/authorized_keysfile on the target Manage Node.BASHssh-copy-id -i /path/to/identity_file.pem ubuntu@<MANAGE_NODE_IP>Example:
BASHssh-copy-id -i ~/Downloads/ABI-AWS-keypair.pem ubuntu@13.235.241.12 -
Verify Passwordless Access: Attempt to SSH into the target machine without specifying the identity (
-i) flag:BASHssh ubuntu@13.235.241.12If configured correctly, you will immediately drop into the shell of the Manage Node without a password prompt.
4. Method 2: Setting Up Passwordless Authentication via Password
In some enterprise environments or private data centers, SSH keys may not be distributed initially, and systems are accessed via standard passwords. To configure passwordless authentication in this scenario, you must temporarily enable password authentication on the target node, copy the key, and then establish the trust.
Step-by-Step Implementation
-
Log into the Manage Node (using your initial credentials).
-
Enable Password Authentication in SSH Daemon Configuration: Open the SSH configuration file with administrative privileges:
BASHsudo vim /etc/ssh/sshd_config(Note: On certain cloud-init systems like AWS Ubuntu, check
/etc/ssh/sshd_config.d/for overriding configuration files). -
Modify the Configuration: Locate the line
PasswordAuthenticationand set it toyes:TEXTPasswordAuthentication yesEnsure it is not commented out (remove any leading
#). -
Set a Password for the Target User:
BASHsudo passwd ubuntuEnter and confirm a secure password.
-
Restart the SSH Service: Apply the configuration changes by restarting the daemon:
BASHsudo systemctl restart ssh -
Execute
ssh-copy-idfrom the Control Node: From your Control Node, run the copy command without the-iflag. It will prompt you for the password you just created:BASHssh-copy-id ubuntu@13.201.15.99 -
Verify Access: Test the connection. It should now connect instantly without prompting for a password:
BASHssh ubuntu@13.201.15.99
5. Understanding Ansible Inventory: The Heart of Target Management
Ansible cannot execute commands in a vacuum; it must know which servers to target. The Ansible Inventory is a configuration file that defines the hosts and groups of hosts upon which Ansible commands, modules, and playbooks operate.
Inventory Formats
Ansible supports two primary inventory formats:
- INI Format (
.ini): The traditional, flat-file format. It is highly readable and remains the most popular choice in production environments. - YAML Format (
.yaml): A structured, hierarchical format aligned with Ansible Playbook syntax.
Basic INI Inventory Structure
An inventory file can be as simple as a list of IP addresses or hostnames, prefixed by their target SSH user:
ubuntu@13.235.241.12
ubuntu@13.201.15.99
Note: Specifying the user (e.g.,
ubuntu@) tells Ansible which remote user account to use when establishing the SSH connection.
6. Naive vs. Production Inventory Management
There are two ways to manage inventory files: using the default system-wide inventory or using custom project-specific inventories.
Production Best Practice
Always create a local inventory.ini file within your project repository. This ensures that changes to infrastructure can be tracked, peer-reviewed, and integrated into CI/CD pipelines.
7. Advanced Inventory Structuring: Grouping and Targeting Nodes
In real-world deployments, you rarely run commands on every server simultaneously. You have distinct tiers of infrastructure (e.g., Application Servers, Database Servers). Ansible allows you to group hosts using square brackets [...] in the INI file.
Example Structured inventory.ini
[app]
ubuntu@13.235.241.12
[db]
ubuntu@13.201.15.99
Targeting Specific Groups
By grouping your hosts, you can target specific subsets of your infrastructure during execution:
[inventory.ini]
/ \
/ \
[app] group [db] group
| |
ubuntu@13.235.241.12 ubuntu@13.201.15.99
- To target only the application servers:
BASH
ansible -i inventory.ini -m ping app - To target only the database servers:
BASH
ansible -i inventory.ini -m ping db - To target every host defined in the inventory:
BASH
ansible -i inventory.ini -m ping all
8. Introduction to Ansible Ad-hoc Commands: Syntax and Architecture
An Ad-hoc Command is a quick, single-line execution pattern used to perform a single action on one or more managed nodes. It is the command-line equivalent of writing a one-off shell script.
The Anatomy of an Ad-hoc Command
ansible -i <inventory_path> -m <module_name> -a "<arguments>" <target_pattern>
Key Flags Explained
-i: Specifies the path to the inventory file. If omitted, Ansible defaults to/etc/ansible/hosts.-m: Specifies the Ansible module to run (e.g.,ping,shell,apt,copy).-a: Passes arguments or commands to the specified module.Target Pattern: Defines which hosts in the inventory should execute the command (e.g.,all,app,13.235.241.12).
9. Ad-hoc Commands vs. Playbooks
While ad-hoc commands are powerful, they serve a different purpose than Ansible Playbooks.
10. Practical Walkthrough: Executing Common Ad-hoc Modules
1. The ping Module
The ping module is not a network utility (like ICMP ping). Instead, it is an Ansible-specific test module that verifies:
- The target host is reachable.
- Your SSH credentials/passwordless setup are working.
- The target host has a usable Python interpreter.
ansible -i inventory.ini -m ping all
Expected Output:
13.235.241.12 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
2. The shell Module
The shell module executes commands through the default shell (typically /bin/sh) on the target nodes. This gives you access to shell environment variables, pipes, and redirections.
-
Listing files in
/etcon all nodes:BASHansible -i inventory.ini -m shell -a "ls /etc" all -
Installing a package (requires root privileges via
sudo):BASHansible -i inventory.ini -m shell -a "sudo apt update && sudo apt install -y openjdk-17-jdk" app
11. Real-World Troubleshooting & Debugging Workflows
When setting up passwordless authentication and running your first ad-hoc commands, you may encounter common failure modes.
Issue 1: Host Key Verification Failed
- Symptom:
TEXT
SSH Error: data: ECDSA host key for IP has changed and you have requested strict checking. Host key verification failed. - Root Cause: The Control Node has an outdated or mismatched SSH signature for the Manage Node in its
~/.ssh/known_hostsfile (common when cloud IPs are recycled). - Resolution: Clear the old key signature from your Control Node:
BASH
ssh-keygen -f "~/.ssh/known_hosts" -R "<MANAGE_NODE_IP>"
Issue 2: Permission Denied (publickey)
- Symptom:
TEXT
13.235.241.12 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: ubuntu@13.235.241.12: Permission denied (publickey).", "unreachable": true } - Root Cause: The public key of the Control Node was not successfully appended to the target's
~/.ssh/authorized_keysfile, or the SSH daemon configuration on the target does not allow key-based authentication. - Resolution:
- Manually check the target's
~/.ssh/authorized_keysfile to ensure your public key (~/.ssh/id_rsa.pub) is present. - Ensure directory permissions on the target are secure (SSH will ignore keys if permissions are too open):
BASH
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys
- Manually check the target's
Issue 3: Host Pattern Mismatch
- Symptom:
TEXT
[WARNING]: Could not match supplied host pattern, ignoring: db - Root Cause: You targeted a group (e.g.,
db) that is either commented out, misspelled, or missing from the active inventory file. - Resolution: Verify your inventory file structure. Ensure the group header matches your command target exactly:
INI
[db] ubuntu@13.201.15.99
Summary and Key Takeaways
- Agentless Architecture: Ansible relies entirely on SSH for Linux/Unix management, making passwordless authentication a critical prerequisite for automation.
- Passwordless Authentication: This mechanism establishes a one-way trust relationship, allowing the Control Node to execute commands on Manage Nodes without interactive prompts.
- Two Authentication Paths: You can configure passwordless access using either an existing SSH Key (
ssh-copy-id -i) or by temporarily enabling password authentication on the target node. - Ansible Inventory: The inventory file (typically in
.iniformat) acts as the source of truth for all target host addresses, connection users, and logical groupings. - Project-Specific Inventories: Managing custom inventory files within your project directory is a production best practice, ensuring isolation and version control.
- Logical Grouping: Grouping hosts (e.g.,
[app],[db]) allows you to target specific tiers of your infrastructure rather than running commands globally. - Ad-hoc Commands: These are single-task CLI commands useful for quick, non-reusable operations like service restarts, quick package installations, or connectivity checks.
- The
pingModule: This module is a diagnostic tool used to verify SSH connectivity, Python availability, and credential validity on target nodes.