Kernel of Truth

Ansible CLI: Commands and Practical Examples

The Ansible command line makes it easy to run one-off tasks, inspect inventories, validate playbooks, and execute automation at scale. This page is a hands-on reference with copy-paste examples.


Prerequisites

# Ubuntu/Debian
sudo apt update
sudo apt install -y ansible

# Verify
ansible --version

Create a simple inventory you can reuse:

# hosts.ini
[web]
192.168.0.101 ansible_user=ansible
192.168.0.102 ansible_user=ansible

[db]
192.168.0.103 ansible_user=ansible

Ad-hoc commands with ansible

Run a single module against hosts without a playbook. Useful for quick checks and one-off changes.

Ping all hosts

ansible all -i hosts.ini -m ping

Run a shell command

command is safest. shell runs through a shell and is needed for pipes, redirects, and expansions.

# Using 'command' (no shell features)
ansible web -i hosts.ini -m command -a "uptime"

# Using 'shell' for pipes
ansible web -i hosts.ini -m shell -a "df -h | grep /var"

Manage packages

Use the generic package module where possible. It maps to apt, dnf, yum, etc.

ansible web -i hosts.ini -m package -a "name=apache2 state=present" --become
ansible db  -i hosts.ini -m package -a "name=mysql-server state=present" --become

Manage services

ansible web -i hosts.ini -m service -a "name=apache2 state=started enabled=true" --become

Copy files and templates

# Copy a static file
ansible web -i hosts.ini -m copy -a "src=./index.html dest=/var/www/html/index.html mode=0644" --become

# Use the template module for Jinja2 templates
ansible web -i hosts.ini -m template -a "src=./vhost.conf.j2 dest=/etc/apache2/sites-available/000-default.conf" --become

Users and authorised keys

ansible all -i hosts.ini -m user -a "name=deploy groups=sudo state=present" --become
ansible all -i hosts.ini -m authorized_key -a "user=deploy state=present key={{ lookup('file','~/.ssh/id_ed25519.pub') }}"

Common CLI flags

  • -i hosts.ini choose inventory file
  • -l web limit to group or host
  • -u ansible SSH user (or set in inventory)
  • --become use sudo on remote
  • -k ask for SSH password, -K ask for sudo password
  • -f 20 set forks for parallelism
  • -v, -vvv increase verbosity

Running playbooks with ansible-playbook

Minimal playbook

# site.yml
---
- name: Baseline setup
  hosts: all
  become: true
  tasks:
    - name: Ensure latest updates
      apt:
        update_cache: yes
        upgrade: dist

Run it:

ansible-playbook -i hosts.ini site.yml

Tags, check mode, and limit

# Only run tasks tagged 'web'
ansible-playbook -i hosts.ini site.yml --tags web

# Dry run to see changes without applying
ansible-playbook -i hosts.ini site.yml --check

# Limit to a single host
ansible-playbook -i hosts.ini site.yml -l 192.168.0.101

Syntax check and diff

ansible-playbook site.yml --syntax-check
ansible-playbook -i hosts.ini site.yml --diff

Variables and extra vars

ansible-playbook -i hosts.ini site.yml -e "env=prod app_port=8080"

Serial rolling updates

# deploy.yml
- hosts: web
  serial: 2
  tasks:
    - name: Restart app in batches of 2 hosts
      service:
        name: myapp
        state: restarted
ansible-playbook -i hosts.ini deploy.yml

Inventory inspection with ansible-inventory

# Show inventory as Ansible sees it
ansible-inventory -i hosts.ini --list

# Graph view of groups and hosts
ansible-inventory -i hosts.ini --graph

Module docs with ansible-doc

# Search for modules that manage services
ansible-doc -l | grep service

# Read the 'apt' module docs
ansible-doc apt

Configuration with ansible-config

# Show current config values and where they come from
ansible-config dump --only-changed

# View effective config file path
ansible-config view

Secrets with ansible-vault

Encrypt sensitive variables and files.

# Create an encrypted vars file
ansible-vault create group_vars/all/vault.yml

# Edit later
ansible-vault edit group_vars/all/vault.yml

# Run a playbook using a password prompt
ansible-playbook -i hosts.ini site.yml --ask-vault-pass

Example usage inside a playbook:

vars_files:
  - group_vars/all/vault.yml

Roles and collections with ansible-galaxy

# Install a role
ansible-galaxy role install geerlingguy.apache

# Install a collection
ansible-galaxy collection install community.mysql

Use them in a playbook:

- hosts: web
  become: true
  roles:
    - geerlingguy.apache

Practical examples

1) Baseline hardening snippet

# harden.yml
- hosts: all
  become: true
  tasks:
    - name: Ensure unattended upgrades
      package:
        name: unattended-upgrades
        state: present
    - name: Disable root SSH login
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^PermitRootLogin'
        line: 'PermitRootLogin no'
        create: yes
      notify: Restart ssh
  handlers:
    - name: Restart ssh
      service:
        name: ssh
        state: restarted
ansible-playbook -i hosts.ini harden.yml

2) LAMP stack quick playbook

# lamp.yml
- hosts: web
  become: true
  vars:
    php_packages:
      - php
      - php-mysql
      - libapache2-mod-php
  tasks:
    - package: { name: apache2, state: present }
    - package: { name: mysql-server, state: present }
    - package:
        name: "{{ php_packages }}"
        state: present
    - service: { name: apache2, state: started, enabled: true }
    - service: { name: mysql,   state: started, enabled: true }
    - copy:
        dest: /var/www/html/info.php
        content: "<?php phpinfo(); ?>"
ansible-playbook -i hosts.ini lamp.yml

3) Fact gathering and conditional tasks

# facts.yml
- hosts: all
  gather_facts: yes
  tasks:
    - name: Print OS details
      debug:
        msg: "{{ ansible_distribution }} {{ ansible_distribution_version }}"
    - name: Run only on Ubuntu 22.04
      debug:
        msg: "Hello Jammy"
      when: ansible_distribution == "Ubuntu" and ansible_distribution_major_version == "22"

SSH and performance tips

  • Create ~/.ssh/config entries for hosts and set ControlPersist to reuse connections.
# ~/.ssh/config
Host web1
  HostName 192.168.0.101
  User ansible
  ControlMaster auto
  ControlPath ~/.ssh/cm-%r@%h:%p
  ControlPersist 60s
  • Increase forks for large runs: ansible-playbook -f 20 ...
  • Use -l to limit blast radius during testing.

Troubleshooting

SSH permission denied
Check key distribution and user in inventory. Try -u ansible -k if using passwords.

Python not found on target
Install Python on minimal hosts. For Debian/Ubuntu: sudo apt install -y python3.

Module not found
Install the required collection or role. Use ansible-doc to confirm module name.

Playbook logic errors
Use --check, --diff, and -vvv for verbose output. Break changes into tagged tasks.


CLI cheatsheet

Task Command
Ping all ansible all -i hosts.ini -m ping
Run playbook ansible-playbook -i hosts.ini site.yml
Dry run ansible-playbook site.yml --check
Limit hosts ansible-playbook site.yml -l web
Syntax check ansible-playbook site.yml --syntax-check
Inventory graph ansible-inventory -i hosts.ini --graph
Module docs ansible-doc apt
Vault edit ansible-vault edit group_vars/all/vault.yml
Install role ansible-galaxy role install geerlingguy.apache

Summary

The Ansible CLI gives you fast checks with ad-hoc commands, reliable deployments with playbooks, and strong guard rails with check mode and tags. Keep inventories tidy, use roles and collections for reuse, protect secrets with Vault, and validate changes with syntax checks and diffs before you run.


🛡️Latest Security Alerts 🛡️

NCSC Latest
(The National Cyber Security Centre UK)