150+ Ansible commands for ad-hoc tasks, playbooks, inventory, modules, vault, roles, and Galaxy. Includes an Ansible Module Quick-Reference. Verified against official Ansible docs.
Everything runs in your browser. No commands or data are sent to any server.
5 essential commands to get you started. The full reference is right below.
ansible --version Confirm which Ansible version, config file, and Python interpreter are actually being used before debugging anything else.
ansible all -m ping The first command to run against any new inventory to confirm SSH connectivity and Python are working before anything else.
ansible-playbook site.yml --check Preview exactly what a playbook would change before committing to running it for real, especially on production.
ansible-doc -l Browse every module available in your current Ansible install and any collections you have installed, before writing a task from memory.
ansible-galaxy init my_role Generate the standard role directory structure (tasks, handlers, defaults, templates, and more) instead of building it by hand.
ansible --version ↓ Click command to explain
When to use this
Confirm which Ansible version, config file, and Python interpreter are actually being used before debugging anything else.
Gotcha
Ansible 2.10+ splits ansible-core from a much larger collection of community modules, so the version output also tells you whether a module you expect is bundled or needs installing separately.
ansible all -m ping ↓ Click command to explain
-m Specifies which module to run When to use this
The first command to run against any new inventory to confirm SSH connectivity and Python are working before anything else.
Gotcha
The ping module does not use ICMP at all. It just verifies Ansible can log in and execute a Python script on the remote host, which is a much more useful check.
ansible webservers -m ping ↓ Click command to explain
When to use this
Narrow a connectivity check to a specific inventory group instead of the entire fleet.
ansible-doc -l ↓ Click command to explain
-l Lists all installed modules with a one-line summary When to use this
Browse every module available in your current Ansible install and any collections you have installed, before writing a task from memory.
Gotcha
The list only includes modules from collections you actually have installed. A module documented online but missing from this list usually means the collection needs installing with ansible-galaxy collection install.
ansible-doc apache2_module ↓ Click command to explain
When to use this
Read the full parameter list, defaults, and examples for a specific module directly in the terminal, without a browser.
ansible-doc -s copy ↓ Click command to explain
-s Outputs a ready-to-use YAML task snippet with every parameter listed When to use this
Generate a starter YAML task block for a module with every available parameter commented in, then delete what you do not need.
ansible-config list ↓ Click command to explain
When to use this
See every configuration option Ansible supports, its default value, and which environment variable or ini setting controls it.
ansible-config dump ↓ Click command to explain
When to use this
See exactly what configuration Ansible is actually using right now, merged from defaults, ansible.cfg, and environment variables.
Gotcha
This is the first command to run when a setting in ansible.cfg does not seem to be taking effect, since it shows exactly which source won.
ansible-config view ↓ Click command to explain
When to use this
Print the exact ansible.cfg file currently in effect, useful when multiple config files exist across a project and a home directory.
ansible all -m command -a 'uptime' ↓ Click command to explain
-a Passes arguments to the module being run When to use this
Run a quick one-off command against the whole fleet without writing a playbook, such as checking uptime after a maintenance window.
Gotcha
command is the default module when -m is omitted, so ansible all -a 'uptime' does exactly the same thing.
ansible all -m shell -a 'df -h | grep /var' ↓ Click command to explain
When to use this
Run a command that needs shell features like pipes, redirects, or environment variable expansion, which the plain command module cannot do.
Gotcha
Reach for shell only when you actually need a shell feature. Prefer command, or better yet a dedicated module, for anything simpler since shell input is harder to make idempotent and safe.
ansible all -m setup ↓ Click command to explain
When to use this
Dump every fact Ansible can discover about a host: OS, memory, network interfaces, mounted disks, and more.
Gotcha
The full output is huge. Pipe it through a filter or use the filter= argument to narrow it down when you only care about one or two facts.
ansible all -m setup -a 'filter=ansible_distribution*' ↓ Click command to explain
filter= Restricts the fact output to keys matching a glob pattern When to use this
Check just the OS distribution and version facts across a fleet without wading through hundreds of unrelated fact keys.
ansible all -m command -a 'whoami' --become ↓ Click command to explain
--become Escalates privileges on the remote host using sudo (or another become method) When to use this
Confirm privilege escalation is configured correctly before running a task that actually needs root, such as installing a package.
Gotcha
whoami should print root when --become works. If it still prints your login user, check that your sudoers entry allows passwordless sudo or add --ask-become-pass.
ansible webservers -m ping --limit 'web1.example.com' ↓ Click command to explain
--limit Further restricts execution to a subset of the matched hosts When to use this
Test a single host inside a larger group before running the same command against the whole group.
ansible all -m ping --forks 20 ↓ Click command to explain
--forks Sets how many hosts Ansible connects to in parallel, default is 5 When to use this
Speed up a run across a large fleet by increasing how many hosts Ansible talks to simultaneously.
Gotcha
Raising forks too high can overwhelm the control node's file descriptors and CPU, or trigger rate limiting on the target infrastructure. Increase gradually and watch for connection errors.
ansible all -m ping -u deploy ↓ Click command to explain
-u Sets the remote username to connect as, overriding the inventory or config default When to use this
Connect as a non-default SSH user, such as a dedicated deploy account instead of your personal login.
ansible all -m ping --private-key ~/.ssh/id_deploy ↓ Click command to explain
--private-key Points to a specific SSH private key file for this connection When to use this
Authenticate with a dedicated deploy key instead of whatever key is loaded in your SSH agent by default.
ansible all -m ping --ask-pass ↓ Click command to explain
--ask-pass Prompts interactively for the SSH password instead of using key-based auth When to use this
Connect to hosts that only accept password authentication, such as a freshly imaged box before your key has been deployed to it.
Gotcha
This requires the sshpass package to be installed on the control node, or Ansible will error out immediately.
ansible all -a 'uptime' -o ↓ Click command to explain
-o Condenses each host's result onto a single line instead of a multi-line block When to use this
Scan results across a large fleet quickly by flattening each host's output to a single line.
ansible all --list-hosts ↓ Click command to explain
--list-hosts Prints the matched hosts without running anything against them When to use this
Sanity-check which hosts a pattern resolves to before running anything against them for real.
ansible all -m copy -a 'src=/etc/hosts dest=/tmp/hosts' ↓ Click command to explain
When to use this
Push a single file out to every matched host without writing a full playbook for a one-off task.
ansible-playbook site.yml ↓ Click command to explain
When to use this
Apply every play and task in a playbook file against the hosts it targets.
Gotcha
A minimal playbook is a YAML list of plays, each with a hosts key and a tasks list, for example: - hosts: webservers\n tasks:\n - name: Install nginx\n apt: {name: nginx, state: present}
ansible-playbook site.yml --check ↓ Click command to explain
--check Runs in dry-run mode, reporting what would change without actually changing it When to use this
Preview exactly what a playbook would change before committing to running it for real, especially on production.
Gotcha
Not every module fully supports check mode. Modules that shell out to external commands, like the command or shell module, cannot predict their own effect and are usually skipped or flagged as unsupported.
ansible-playbook site.yml --check --diff ↓ Click command to explain
--diff Shows a before/after diff for any file that template, copy, or lineinfile would change When to use this
See the exact line-by-line diff of every config file a playbook would touch, combined with --check for a full dry-run preview.
ansible-playbook site.yml --syntax-check ↓ Click command to explain
--syntax-check Parses the playbook and reports syntax errors without connecting to any hosts When to use this
Catch YAML indentation errors and structural mistakes before wasting time connecting to real infrastructure.
Gotcha
Syntax check only validates YAML structure. It does not catch a typo in a module name or an invalid parameter, those only surface once the playbook actually runs.
ansible-playbook site.yml --limit webservers ↓ Click command to explain
--limit Restricts the run to a subset of hosts matched by the playbook's hosts key When to use this
Run a playbook that targets a broad group against only one server first, to test it safely.
ansible-playbook site.yml --tags 'config,deploy' ↓ Click command to explain
--tags Runs only tasks (and their handlers) tagged with one of the listed tag names When to use this
Re-run just the deployment steps of a large playbook without re-running slow provisioning steps that already succeeded.
ansible-playbook site.yml --skip-tags 'slow' ↓ Click command to explain
--skip-tags Runs every task except those tagged with one of the listed tag names When to use this
Skip a known slow or optional section of a playbook, such as a full package cache refresh, during a quick iteration loop.
ansible-playbook site.yml -e 'env=production' ↓ Click command to explain
-e Sets extra variables, which take the highest precedence of any variable source When to use this
Override a variable at run time, such as switching a playbook between staging and production without editing any file.
Gotcha
Extra vars set with -e override every other variable source, including group_vars, host_vars, and role defaults. This is exactly why it is the right tool for a one-off override.
ansible-playbook site.yml -e '@vars.yml' ↓ Click command to explain
-e @file Loads extra variables from a YAML or JSON file, the @ prefix marks it as a file path When to use this
Pass a whole set of environment-specific variables from a file instead of listing them individually on the command line.
ansible-playbook site.yml -v ↓ Click command to explain
-v Shows the result data for each task, not just its status When to use this
See the actual result data returned by each task, useful when a task succeeds but you want to confirm exactly what it did.
ansible-playbook site.yml --list-tasks ↓ Click command to explain
--list-tasks Prints every task in the playbook, in order, without executing anything When to use this
Review the full task list of a playbook you did not write before running it, without needing to open every file.
ansible-playbook site.yml --list-hosts ↓ Click command to explain
--list-hosts Prints every host the playbook's plays would target, without executing anything When to use this
Confirm exactly which hosts a playbook resolves to across all of its plays before running it.
ansible-playbook site.yml --list-tags ↓ Click command to explain
--list-tags Prints every tag referenced anywhere in the playbook When to use this
Discover which tags a playbook actually supports before deciding what to pass to --tags or --skip-tags.
ansible-playbook site.yml --step ↓ Click command to explain
--step Prompts to confirm, skip, or continue before each task runs When to use this
Walk through a playbook one task at a time on a production host, confirming each step before it executes.
ansible-playbook site.yml --start-at-task='Install packages' ↓ Click command to explain
--start-at-task Skips every task before the one matching this name and starts there When to use this
Resume a long playbook from the task that failed last time, instead of re-running everything from the beginning.
Gotcha
The task name must match exactly, including case. Earlier tasks are still parsed for variables and roles but their actions are not executed.
ansible-playbook site.yml -i inventory/production ↓ Click command to explain
-i Points to a specific inventory file or directory instead of the configured default When to use this
Target the production inventory explicitly when a project keeps separate inventory files per environment.
ansible-playbook site.yml --become --ask-become-pass ↓ Click command to explain
--become Escalates privileges for every task in the play --ask-become-pass Prompts interactively for the sudo password instead of assuming passwordless sudo When to use this
Run a playbook that needs root access on hosts where sudo requires a password rather than being passwordless.
ansible-playbook site.yml --forks 50 ↓ Click command to explain
--forks Sets how many hosts are processed in parallel for this run When to use this
Speed up a large fleet-wide rollout by raising parallelism above the default of 5 hosts at a time.
ansible-playbook site.yml --connection=local ↓ Click command to explain
--connection=local Executes tasks directly on the control node instead of connecting over SSH When to use this
Run a playbook that configures the machine Ansible itself is running on, skipping SSH entirely.
ansible-playbook site.yml --vault-password-file ~/.vault_pass ↓ Click command to explain
--vault-password-file Reads the vault password from a file instead of prompting interactively When to use this
Run a playbook non-interactively in CI when it references vault-encrypted variable files.
Gotcha
Never commit the vault password file itself to version control. Store it as a CI secret and write it to a temp file at pipeline run time.
ansible-playbook site.yml --become-user=deploy ↓ Click command to explain
--become-user Sets which user to become, default is root When to use this
Run tasks as a dedicated service account instead of root, when the target application should not run privileged.
ansible-playbook site.yml --flush-cache ↓ Click command to explain
--flush-cache Clears any cached facts before gathering fresh ones for this run When to use this
Force fresh fact gathering when fact caching is enabled and stale cached facts are causing a playbook to behave unexpectedly.
Gotcha
Only relevant when fact caching (fact_caching in ansible.cfg) is enabled. Without it, facts are already gathered fresh on every run.
[webservers]
web1.example.com
web2.example.com ansible_host=10.0.1.5
[databases]
db1.example.com ↓ Click command to explain
When to use this
The classic static inventory format, grouping hosts under bracketed group names. Still the most common format for small, fixed environments.
Gotcha
A per-host variable like ansible_host can be set inline after the hostname, useful when the inventory name differs from the actual address to connect to.
all:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
ansible_host: 10.0.1.5
databases:
hosts:
db1.example.com: ↓ Click command to explain
When to use this
The YAML equivalent of an INI inventory, preferred in larger projects since it nests more naturally with group_vars and host_vars.
[webservers:vars]
http_port=8080
env=production ↓ Click command to explain
When to use this
Attach variables to every host in a group directly inside the INI inventory file, without a separate group_vars file.
Gotcha
This works but does not scale well. Most teams move group variables into a dedicated group_vars/<groupname>.yml file once there are more than a couple of them.
[production:children]
webservers
databases ↓ Click command to explain
When to use this
Build a parent group made up of other groups, so a single pattern like production can target every host in both webservers and databases.
ansible-inventory --list ↓ Click command to explain
--list Outputs the entire inventory, all groups and hosts, as JSON When to use this
See exactly how Ansible has parsed and merged your inventory sources into one structure, including all variables.
ansible-inventory --graph ↓ Click command to explain
--graph Prints groups and their child groups and hosts as an indented tree When to use this
Get a quick, human-readable view of how groups nest inside each other, much easier to scan than the raw JSON output.
ansible-inventory --host web1.example.com ↓ Click command to explain
--host Prints every variable resolved for a single named host When to use this
Check exactly which variables a specific host will see once group_vars, host_vars, and inventory variables are all merged together.
ansible-inventory --list --yaml ↓ Click command to explain
--yaml Formats the --list output as YAML instead of the default JSON When to use this
Read the full resolved inventory in a more readable format than raw JSON, useful for a quick manual review.
ansible all --list-hosts ↓ Click command to explain
When to use this
all is a built-in group containing every host in the inventory, useful for fleet-wide checks like connectivity or fact gathering.
ansible ungrouped --list-hosts ↓ Click command to explain
When to use this
ungrouped is a built-in group for any host defined in inventory but not assigned to a named group, useful for catching inventory hygiene mistakes.
ansible webservers:!staging --list-hosts ↓ Click command to explain
When to use this
Target every webserver except the ones also in the staging group, useful for production-only fleet-wide operations.
Gotcha
The exclude operator only removes hosts that are also matched by an earlier part of the pattern. It does not work as a standalone negative pattern on its own.
ansible webservers:&staging --list-hosts ↓ Click command to explain
When to use this
Target only the hosts that appear in both webservers and staging, a true intersection of two groups.
ansible 'web*' --list-hosts ↓ Click command to explain
When to use this
Target every host whose name matches a shell-style wildcard, useful when hosts are not all in one clean group.
ansible '~web[0-9]+\.example\.com' --list-hosts ↓ Click command to explain
When to use this
Target hosts by a full regular expression when a wildcard is not precise enough, marked with a leading tilde.
ansible-inventory -i inventory/aws_ec2.yml --graph ↓ Click command to explain
When to use this
Pull inventory live from a cloud provider's API using an inventory plugin config file instead of maintaining a static host list by hand.
Gotcha
A dynamic inventory source is still just a file, but its extension and a plugin: key inside it tell Ansible to run a plugin instead of parsing it as static INI or YAML.
# group_vars/webservers.yml
http_port: 8080
max_clients: 200 ↓ Click command to explain
When to use this
The standard way to attach variables to a group at scale: a YAML file named after the group under a group_vars directory next to the inventory.
# host_vars/web1.example.com.yml
ansible_host: 10.0.1.5
ansible_user: deploy ↓ Click command to explain
When to use this
The standard way to attach variables to a single host at scale: a YAML file named after the host under a host_vars directory next to the inventory.
ansible-playbook site.yml -e 'env=staging' ↓ Click command to explain
-e Sets an extra variable, the highest-precedence variable source in Ansible When to use this
Override any variable defined anywhere else, since extra vars sit at the very top of Ansible's variable precedence order.
Gotcha
The simplified precedence order, lowest to highest: role defaults, inventory group_vars and host_vars, play vars, role vars, task vars, then extra vars (-e) last and highest. When two definitions of the same variable conflict, the higher one always wins.
ansible-playbook site.yml -e '{"key":"value"}' ↓ Click command to explain
When to use this
Pass a nested structure of variables directly on the command line using inline JSON instead of a flat key=value pair.
ansible web1.example.com -m debug -a 'var=hostvars[inventory_hostname]' ↓ Click command to explain
When to use this
Print every variable Ansible has resolved for a specific host at run time, combining inventory, group_vars, host_vars, and facts.
ansible all -m copy -a 'src=app.conf dest=/etc/app.conf mode=0644' ↓ Click command to explain
When to use this
Push a static file from the control node to every matched host, setting its permissions in the same task.
ansible all -m template -a 'src=app.conf.j2 dest=/etc/app.conf' ↓ Click command to explain
When to use this
Render a config file from a Jinja2 template, substituting variables per host, instead of copying an identical static file everywhere.
Gotcha
The source path is always relative to a templates/ directory next to the playbook or role, not an arbitrary filesystem path.
ansible all -m file -a 'path=/opt/app state=directory mode=0755' ↓ Click command to explain
When to use this
Ensure a directory exists with specific permissions before deploying application files into it.
ansible all -m file -a 'path=/tmp/old.log state=absent' ↓ Click command to explain
When to use this
Remove a file or directory, including recursively for a directory, cleanly and idempotently.
Gotcha
state=absent on a directory removes it and everything inside it, with no confirmation prompt. Double-check the path before running this against a real fleet.
ansible all -m file -a 'src=/opt/app/current dest=/opt/app/releases/1 state=link' ↓ Click command to explain
When to use this
Point a stable path at a versioned release directory, the classic pattern for atomic, symlink-based deployments.
ansible all -m service -a 'name=nginx state=restarted' ↓ Click command to explain
When to use this
Restart a service using whichever init system the host actually runs, without hardcoding systemctl or service commands.
ansible all -m systemd -a 'name=nginx enabled=yes state=started' ↓ Click command to explain
When to use this
Ensure a service is both running now and set to start on boot, specifically on hosts using systemd.
ansible all -m systemd -a 'daemon_reload=yes' ↓ Click command to explain
When to use this
Reload systemd's configuration after deploying a new or changed .service unit file, so systemd picks up the change.
Gotcha
Forgetting daemon_reload after editing a unit file is one of the most common causes of 'I changed the service file but nothing happened' confusion.
ansible all -m package -a 'name=curl state=present' ↓ Click command to explain
When to use this
Install a package across a mixed fleet of Debian and RHEL-family hosts without branching logic, since package delegates to the right backend automatically.
ansible all -m apt -a 'update_cache=yes' ↓ Click command to explain
When to use this
Refresh apt's package index before installing packages, the equivalent of apt-get update.
ansible all -m apt -a 'name=nginx state=present' ↓ Click command to explain
When to use this
Install a package on Debian or Ubuntu hosts specifically, with access to apt-only parameters like update_cache.
ansible all -m apt -a 'upgrade=dist' ↓ Click command to explain
When to use this
Apply every available package upgrade across a fleet, equivalent to apt-get dist-upgrade.
Gotcha
A full dist upgrade can restart services or even require a reboot depending on what was updated. Run this with --check first and schedule it deliberately, never as a surprise.
ansible all -m yum -a 'name=httpd state=latest' ↓ Click command to explain
When to use this
Install or update a package on RHEL, CentOS, or Fedora hosts using yum (dnf is used automatically where yum is just an alias).
ansible all -m user -a 'name=deploy shell=/bin/bash groups=sudo append=yes' ↓ Click command to explain
When to use this
Create a deploy or service account with a specific shell and group membership as part of server bootstrapping.
Gotcha
Always pass append=yes when adding to groups, otherwise groups= replaces the user's entire group list instead of adding to it.
ansible all -m user -a 'name=olduser state=absent remove=yes' ↓ Click command to explain
When to use this
Fully deprovision a user account, including their home directory, when decommissioning access.
Gotcha
state=absent alone leaves the home directory behind. Add remove=yes to actually delete the home directory and mail spool along with the account.
ansible all -m group -a 'name=deployers state=present' ↓ Click command to explain
When to use this
Ensure a group exists before assigning users to it, useful when provisioning permissions ahead of the accounts that need them.
ansible all -m git -a 'repo=https://github.com/example/app.git dest=/opt/app version=main' ↓ Click command to explain
When to use this
Deploy application code by cloning or updating a Git repository directly to a target directory on the remote host.
ansible all -m cron -a 'name="daily backup" minute=0 hour=2 job="/opt/scripts/backup.sh"' ↓ Click command to explain
When to use this
Manage a crontab entry idempotently, identified by its name comment so re-running the task never creates duplicate entries.
Gotcha
The name parameter is not just a label. Ansible uses it as the marker comment to find and update the entry on future runs, so keep it stable once set.
ansible all -m cron -a 'name="old job" state=absent' ↓ Click command to explain
When to use this
Remove a previously managed cron entry cleanly by its name, without disturbing any other jobs in the same crontab.
ansible all -m command -a 'systemctl status nginx' ↓ Click command to explain
When to use this
Run a single command directly, without shell interpretation, which is safer and the recommended default over shell.
Gotcha
command does not process shell operators like |, >, or &&. If the command needs any of those, use shell instead.
ansible all -m shell -a 'ps aux | grep nginx' ↓ Click command to explain
When to use this
Run a command that specifically needs shell features like pipes, which the command module cannot process.
ansible all -m raw -a 'which python3' ↓ Click command to explain
When to use this
Run a bare SSH command on a host that has no Python interpreter yet, most commonly used to bootstrap Python itself on a fresh image.
Gotcha
raw is the one module that does not require Python on the target at all, since it skips Ansible's usual module machinery entirely and just runs the command over SSH.
ansible all -m debug -a 'var=ansible_facts' ↓ Click command to explain
When to use this
Print the current value of a variable or fact during troubleshooting, without modifying anything.
ansible all -m debug -a "msg='deployment starting'" ↓ Click command to explain
When to use this
Print a plain custom message during a run, often used to mark a checkpoint or explain what a following task is about to do.
ansible all -m set_fact -a 'app_version=1.2.3' ↓ Click command to explain
When to use this
Compute or set a variable during a run that later tasks in the same play can reference, without it needing to exist in inventory or group_vars.
Gotcha
A fact set with set_fact only persists for the current play by default. Add cacheable=yes with fact caching enabled if it needs to survive into a later play or run.
ansible all -m lineinfile -a "path=/etc/hosts line='127.0.0.1 app.local'" ↓ Click command to explain
When to use this
Add or update a single line in an existing config file without touching the rest of its contents.
ansible all -m lineinfile -a "path=/etc/ssh/sshd_config regexp='^PermitRootLogin' line='PermitRootLogin no'" ↓ Click command to explain
When to use this
Replace whatever an existing setting currently is, rather than blindly appending, by matching it with a regular expression first.
Gotcha
Without regexp, lineinfile only checks for an exact match of line and will append a duplicate rather than replacing a differently-formatted existing line.
ansible all -m blockinfile -a "path=/etc/motd block='Managed by Ansible'" ↓ Click command to explain
When to use this
Insert or update a multi-line block of text wrapped in marker comments, so re-running the task updates the block instead of duplicating it.
ansible all -m get_url -a 'url=https://example.com/app.tar.gz dest=/tmp/app.tar.gz mode=0644' ↓ Click command to explain
When to use this
Download a file directly on the remote host from an HTTP, HTTPS, or FTP URL, skipping the control node entirely.
ansible all -m unarchive -a 'src=/tmp/app.tar.gz dest=/opt/app remote_src=yes' ↓ Click command to explain
When to use this
Extract a tar or zip archive that already exists on the remote host, commonly chained right after get_url.
Gotcha
remote_src=yes is essential here. Without it, unarchive assumes src is a path on the control node and tries to copy it over first.
ansible all -m wait_for -a 'port=8080 delay=5 timeout=60' ↓ Click command to explain
When to use this
Pause a playbook until an application has actually started listening on its port, before running a health check task against it.
ansible all -m wait_for -a 'path=/tmp/deploy.lock state=absent' ↓ Click command to explain
When to use this
Pause until a lock file created by a deploy script is removed, coordinating Ansible with an external process.
ansible all -m uri -a 'url=http://localhost/health return_content=yes' ↓ Click command to explain
When to use this
Hit a health check or API endpoint and inspect the response, useful right after a deploy to confirm the app came up healthy.
ansible all -m stat -a 'path=/etc/app.conf' ↓ Click command to explain
When to use this
Check whether a file exists and inspect its permissions or checksum, typically registered into a variable and used in a later when condition.
ansible all -m assert -a "that='ansible_memtotal_mb > 512'" ↓ Click command to explain
When to use this
Fail a play early and loudly if a required condition is not met, such as a minimum amount of memory before installing a memory-hungry service.
ansible all -m fetch -a 'src=/var/log/app.log dest=/tmp/logs/ flat=yes' ↓ Click command to explain
When to use this
Pull a file from every matched host back to the control node, the reverse direction of copy, commonly used to collect logs.
Gotcha
Without flat=yes, fetch nests each file under a per-host directory on the control node so files from different hosts never collide.
ansible all -m synchronize -a 'src=/local/dir/ dest=/remote/dir/' ↓ Click command to explain
When to use this
Sync a whole directory tree efficiently using rsync under the hood, much faster than copy for large numbers of files.
Gotcha
synchronize requires rsync to be installed on both the control node and the target host, unlike copy which has no such dependency.
ansible all -m authorized_key -a "user=deploy key={{ lookup('file', '~/.ssh/id_rsa.pub') }}" ↓ Click command to explain
When to use this
Add a public key to a user's authorized_keys file idempotently, commonly used when bootstrapping a new deploy account.
ansible all -m reboot -a 'reboot_timeout=300' --become ↓ Click command to explain
When to use this
Reboot a host as part of a kernel or system update, and block until it has actually come back online and is reachable again.
Gotcha
Always run this with --limit against a small batch first. Rebooting an entire fleet in one pass with high forks can take down a service simultaneously across every instance.
ansible all -m package_facts ↓ Click command to explain
When to use this
Discover exactly which packages and versions are installed on a host, useful for an inventory audit or a when condition based on package presence.
ansible-vault create secrets.yml ↓ Click command to explain
When to use this
Create a brand-new file that is encrypted from the moment it is saved, opening your default editor to write its contents.
Gotcha
The editor used is whatever your EDITOR environment variable points to. If nothing happens when you run this, EDITOR is probably unset.
ansible-vault edit secrets.yml ↓ Click command to explain
When to use this
Decrypt a vault file into your editor, let you make changes, and re-encrypt it on save, without ever leaving plaintext on disk.
ansible-vault view secrets.yml ↓ Click command to explain
When to use this
Read the contents of a vault-encrypted file to your terminal without opening an editor or risking an accidental save.
ansible-vault encrypt vars/prod.yml ↓ Click command to explain
When to use this
Encrypt a file that already exists as plaintext, turning it into a vault-protected file in place.
ansible-vault encrypt vars/prod.yml vars/staging.yml ↓ Click command to explain
When to use this
Encrypt several related variable files in a single command, all with the same vault password.
ansible-vault decrypt secrets.yml ↓ Click command to explain
When to use this
Remove vault encryption from a file entirely, leaving it as plain, readable text on disk.
Gotcha
This leaves real secrets sitting in plaintext on disk. Only do this briefly and intentionally, and never commit the decrypted file to version control.
ansible-vault rekey secrets.yml ↓ Click command to explain
When to use this
Rotate the password protecting a vault file without needing to fully decrypt and re-encrypt it manually.
Gotcha
Rekeying only changes the password for that one file. Every other vault file encrypted with the old password still needs rekeying separately, or a shared vault ID setup.
ansible-vault encrypt_string 'S3cr3tP@ss' --name 'db_password' ↓ Click command to explain
--name Names the resulting encrypted variable, formatting the output ready to paste into a YAML file When to use this
Encrypt just one secret value, like a single password, so it can be pasted directly into an otherwise plaintext variables file.
echo -n 'S3cr3tP@ss' | ansible-vault encrypt_string --stdin-name 'db_password' ↓ Click command to explain
--stdin-name Reads the value to encrypt from stdin instead of a command-line argument When to use this
Encrypt a secret without it ever appearing in your shell history, which passing it directly as a command-line argument would risk.
Gotcha
echo -n is important here. A trailing newline from a plain echo becomes part of the encrypted value and can silently break comparisons or authentication.
ansible-playbook site.yml --vault-password-file ~/.vault_pass ↓ Click command to explain
--vault-password-file Reads the vault password from a file, or from a script's stdout if the file is executable When to use this
Supply the vault password non-interactively, most commonly needed for CI/CD pipelines running playbooks unattended.
ansible-playbook site.yml --ask-vault-pass ↓ Click command to explain
--ask-vault-pass Prompts interactively for the vault password at run time When to use this
Run a playbook that touches vault-encrypted files interactively, typing the password once at the start of the run.
ansible-vault encrypt secrets.yml --vault-id prod@prompt ↓ Click command to explain
--vault-id Encrypts under a named vault identity, prompting interactively for that identity's password When to use this
Encrypt a file under a labeled identity like prod, so different environments can use entirely separate vault passwords.
ansible-playbook site.yml --vault-id prod@~/.vault_pass_prod ↓ Click command to explain
When to use this
Decrypt files that were encrypted under a specific named vault identity, pairing the identity with its password file.
ansible-playbook site.yml --vault-id dev@~/.vault_dev --vault-id prod@~/.vault_prod ↓ Click command to explain
When to use this
Decrypt files encrypted under different vault identities in a single run, such as a playbook that references both dev and prod secrets.
Gotcha
Ansible tries each supplied vault-id against each encrypted file until one works, so the order does not need to match which file uses which identity.
ansible-vault create --vault-id prod@prompt secrets_prod.yml ↓ Click command to explain
When to use this
Create a brand-new secrets file that is encrypted from the start under a specific named vault identity.
ansible-galaxy init my_role ↓ Click command to explain
When to use this
Generate the standard role directory structure (tasks, handlers, defaults, templates, and more) instead of building it by hand.
Gotcha
The generated defaults/main.yml is where role variables meant to be easily overridden should live, since role defaults have the lowest variable precedence of any source.
ansible-galaxy install geerlingguy.nginx ↓ Click command to explain
When to use this
Install a community-maintained role directly from Ansible Galaxy instead of writing one from scratch.
ansible-galaxy install -r requirements.yml ↓ Click command to explain
-r Reads a list of roles (and their versions and sources) from a requirements file When to use this
Install every external role a project depends on in one command, keeping dependencies version-pinned and reproducible.
ansible-galaxy list ↓ Click command to explain
When to use this
See every role currently installed locally along with its version, useful before upgrading or auditing dependencies.
ansible-galaxy remove geerlingguy.nginx ↓ Click command to explain
When to use this
Remove a role that is no longer needed from the local roles directory.
ansible-galaxy search nginx ↓ Click command to explain
When to use this
Search the public Galaxy registry for roles matching a keyword before deciding whether to write one yourself.
ansible-galaxy info geerlingguy.nginx ↓ Click command to explain
When to use this
Check a role's available versions, dependencies, and last update date before pinning it in requirements.yml.
ansible-galaxy collection install community.general ↓ Click command to explain
When to use this
Install a collection, a bundle of modules, plugins, and roles from a single namespace, most commonly community.general for modules not in ansible-core.
Gotcha
Collections and roles are installed separately with different subcommands. A missing module usually means the collection needs installing, not just a role.
ansible-galaxy collection install -r requirements.yml ↓ Click command to explain
When to use this
Install every collection dependency a project needs in one command, version-pinned and reproducible across machines.
ansible-galaxy collection list ↓ Click command to explain
When to use this
See every collection currently installed and its version, useful for confirming a required collection is actually present.
ansible-galaxy collection verify community.general ↓ Click command to explain
When to use this
Confirm an installed collection has not been modified locally, comparing its files against the checksums published to Galaxy.
ansible-galaxy collection build ↓ Click command to explain
When to use this
Package a collection you maintain into a tarball ready to publish or install elsewhere, run from inside the collection's root directory.
ansible-galaxy collection publish my_namespace-my_collection-1.0.0.tar.gz ↓ Click command to explain
When to use this
Publish a built collection tarball to Ansible Galaxy or a private Automation Hub so others can install it.
ansible-galaxy install geerlingguy.nginx,3.1.0 ↓ Click command to explain
When to use this
Pin a role to an exact version rather than always installing latest, keeping a project's dependencies reproducible.
ansible-galaxy install geerlingguy.nginx -p ./roles ↓ Click command to explain
-p Sets the directory roles are installed into, instead of the default roles path When to use this
Install a role directly into a project-local roles directory so it can be committed and versioned alongside the playbook.
ansible-galaxy collection init my_namespace.my_collection ↓ Click command to explain
When to use this
Generate the standard collection directory structure when starting a new collection to hold custom modules, plugins, or roles.
tasks:
- name: Update nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Restart nginx
handlers:
- name: Restart nginx
service:
name: nginx
state: restarted ↓ Click command to explain
When to use this
Restart a service only when the config that feeds it actually changed, instead of restarting it unconditionally on every run.
Gotcha
A handler is matched to notify by its name, not by which task called it. Renaming a handler without updating every notify that references it silently breaks the trigger.
handlers:
- name: Restart nginx
service:
name: nginx
state: restarted
- name: Reload firewall
service:
name: firewalld
state: reloaded ↓ Click command to explain
When to use this
Handlers always run in the order they are listed under handlers, regardless of the order in which tasks notified them.
ansible-playbook site.yml --force-handlers ↓ Click command to explain
--force-handlers Runs any handlers that were already notified even if a later task in the play fails When to use this
Ensure a service still restarts to pick up a config change even if an unrelated later task in the same play fails.
Gotcha
By default, handlers only run at the very end of a successful play. A failure anywhere in the play normally skips every pending handler entirely.
- name: Install nginx on Debian family
apt:
name: nginx
state: present
when: ansible_facts['os_family'] == "Debian" ↓ Click command to explain
When to use this
Run a task only on hosts matching a condition, most commonly branching behavior based on OS family or a variable.
Gotcha
when is evaluated as a raw Jinja2 expression, so it should not be wrapped in {{ }} the way a value elsewhere in a task would be.
- name: Restart app only in production
service:
name: myapp
state: restarted
when:
- env == "production"
- deploy_enabled | bool ↓ Click command to explain
When to use this
A list of conditions under when is implicitly ANDed together, all must be true for the task to run.
- name: Create multiple users
user:
name: "{{ item }}"
state: present
loop:
- alice
- bob
- carol ↓ Click command to explain
When to use this
Run the same task once per item in a list, referencing the current item with {{ item }}, instead of writing one task per user.
- name: Install packages
apt:
name: "{{ item }}"
with_items:
- nginx
- curl
- git ↓ Click command to explain
When to use this
The older looping syntax, still common in existing playbooks and still fully supported.
Gotcha
with_items still works but loop is the modern recommended syntax, and it composes more predictably with filters and lookups than the older with_ family.
- name: Create users with groups
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
loop:
- { name: 'alice', groups: 'sudo' }
- { name: 'bob', groups: 'developers' } ↓ Click command to explain
When to use this
Loop over structured data instead of plain strings, accessing each item's fields with dot notation like item.name.
ansible localhost -m debug -a "msg={{ myvar | default('fallback') }}" ↓ Click command to explain
When to use this
Provide a fallback value for a variable that might be undefined, avoiding an undefined variable error.
ansible localhost -m debug -a "msg={{ 'hello world' | upper }}" ↓ Click command to explain
When to use this
Transform string case inside a template or task, useful for normalizing values like environment names before comparing them.
ansible localhost -m debug -a "msg={{ ['a','b','c'] | join(',') }}" ↓ Click command to explain
When to use this
Turn a list variable into a single delimited string, commonly used when rendering a config value that expects a comma or space separated list.
ansible localhost -m debug -a "msg={{ myvar | to_nice_yaml }}" ↓ Click command to explain
When to use this
Render a complex variable as readable, indented YAML inside a template or debug message, instead of a single-line dump.
ansible localhost -m debug -a "msg={{ 'foo123' | regex_replace('[0-9]+', '') }}" ↓ Click command to explain
When to use this
Strip or replace parts of a string using a regular expression, useful for cleaning up a value pulled from facts before using it elsewhere.
ansible localhost -m debug -a "msg={{ (env == 'prod') | ternary('production','staging') }}" ↓ Click command to explain
When to use this
Pick between two values based on a boolean condition in a single expression, a compact alternative to a multi-line when/set_fact pair.
ansible localhost -m debug -a "msg={{ users | selectattr('active') | list }}" ↓ Click command to explain
When to use this
Filter a list of dictionaries down to only the items matching an attribute condition, such as only active users.
ansible all -m template -a "src=sudoers.j2 dest=/etc/sudoers validate='visudo -cf %s'" ↓ Click command to explain
validate= Runs a validation command against a temp copy of the rendered file before overwriting the real destination When to use this
Validate a rendered config file with its own tool, like visudo, before it ever overwrites the live file, so a broken render never lands on disk.
Gotcha
The %s in the validate command is replaced with the path to the temporary rendered file, not the real destination, which is exactly what makes this safe.
ansible-playbook site.yml -vvv ↓ Click command to explain
-vvv Shows connection details including the actual SSH command being executed When to use this
Debug a connection failure by seeing the exact SSH command Ansible is running under the hood, including which key and user it picked.
ansible-playbook site.yml -vvvv ↓ Click command to explain
-vvvv Adds connection plugin debugging on top of -vvv, the most detailed verbosity level When to use this
Debug the deepest connection-layer problems, such as an SSH multiplexing or ControlPath issue that -vvv does not fully expose.
ansible all -m ping -vvv ↓ Click command to explain
When to use this
Combine the simplest possible module with high verbosity to isolate whether a failure is about connectivity at all, before suspecting anything else.
ansible all -m command -a 'whoami' --become -vvv ↓ Click command to explain
When to use this
Isolate whether a task failure is actually a sudo or become configuration problem, separate from the task's own logic.
ansible all -m setup -a 'filter=ansible_python_interpreter' ↓ Click command to explain
When to use this
Diagnose a module failure caused by Ansible picking an unexpected Python interpreter on a host with multiple Python versions installed.
ansible all -m ping -c paramiko ↓ Click command to explain
-c Selects a specific connection plugin instead of the default openssh-based one When to use this
Work around an issue specific to the system OpenSSH client by switching to Ansible's Python-based paramiko connection plugin.
ansible all -m ping --ssh-common-args='-o StrictHostKeyChecking=no' ↓ Click command to explain
--ssh-common-args Passes extra arguments through to every SSH invocation Ansible makes When to use this
Work around a host key checking failure or pass a jump host argument when connecting through a bastion.
Gotcha
Disabling StrictHostKeyChecking removes a real security check. Fine for short-lived lab or CI environments, but avoid it as a permanent fix for real infrastructure.
ansible all -m ping --timeout=30 ↓ Click command to explain
--timeout Sets the connection timeout in seconds, default is 10 When to use this
Give slow or high-latency hosts more time to respond before Ansible gives up on the connection.
ansible-playbook site.yml --limit @site.retry ↓ Click command to explain
--limit @file.retry Limits the run to only the hosts listed in an auto-generated .retry file from the previous failed run When to use this
Re-run a playbook against only the hosts that failed last time, instead of the entire fleet, after fixing the underlying issue.
Gotcha
Retry files are only generated when a run actually fails, and only if retry_files_enabled is not disabled in ansible.cfg.
ansible all -m ping --become --become-method=su ↓ Click command to explain
--become-method Selects which privilege escalation method to use, default is sudo When to use this
Work around a host where sudo is not configured but su is available, or another become plugin like doas or pbrun is required.
ansible-config dump --only-changed ↓ Click command to explain
--only-changed Shows only settings that differ from their built-in default value When to use this
Cut through hundreds of default settings and see only the handful your project has actually overridden.
ansible-doc --json apt ↓ Click command to explain
--json Outputs module documentation as machine-readable JSON instead of formatted text When to use this
Get a module's parameter list as structured JSON, useful for scripting or building tooling around Ansible's own module metadata.
ansible-doc -l -t module ↓ Click command to explain
-t Restricts the listing to a specific plugin type, such as module, lookup, or filter When to use this
List only modules and exclude other plugin types like lookups or filters when browsing what is available.
ansible-playbook site.yml --limit 'web*' --list-hosts ↓ Click command to explain
When to use this
Confirm a wildcard or complex limit pattern resolves to exactly the hosts you expect before actually running the playbook against them.
ansible-playbook site.yml --step --start-at-task='Restart service' ↓ Click command to explain
When to use this
Combine resuming from a specific task with interactive step confirmation, useful for carefully walking through the exact section of a playbook that failed.
ansible all -m setup --tree /tmp/facts ↓ Click command to explain
--tree Writes each host's output to its own file under the given directory instead of printing to the terminal When to use this
Capture full facts for every host into separate files for offline diffing or review, instead of scrolling through terminal output for a large fleet.
The most commonly used Ansible modules, each with a one-line description and the minimal syntax to use it inside a task. Search by module name or what it does.
copy
Copies a file from the control node to remote hosts.
copy: {src: app.conf, dest: /etc/app.conf, mode: '0644'} template
Renders a Jinja2 template file and copies the result to remote hosts.
template: {src: app.conf.j2, dest: /etc/app.conf} file
Manages file and directory properties: create, delete, permissions, symlinks.
file: {path: /opt/app, state: directory, mode: '0755'} service
Starts, stops, or restarts a system service using the host's native service manager.
service: {name: nginx, state: restarted, enabled: true} systemd
Manages services under systemd specifically, including reloading unit files after a change.
systemd: {name: nginx, state: started, enabled: true, daemon_reload: true} package
Installs or removes a package using whichever package manager the target OS actually has.
package: {name: curl, state: present} apt
Installs or removes packages on Debian and Ubuntu systems using apt.
apt: {name: nginx, state: present, update_cache: true} yum
Installs or removes packages on RHEL, CentOS, and Fedora systems using yum or dnf.
yum: {name: httpd, state: latest} user
Creates, modifies, or removes a user account on the remote host.
user: {name: deploy, shell: /bin/bash, groups: sudo, append: true} group
Creates or removes a group on the remote host.
group: {name: deployers, state: present} git
Clones or updates a Git repository on the remote host.
git: {repo: 'https://github.com/example/app.git', dest: /opt/app, version: main} cron
Manages a cron job entry in a user's crontab.
cron: {name: 'daily backup', minute: '0', hour: '2', job: /opt/scripts/backup.sh} command
Runs a command directly without a shell, so pipes, redirects, and env vars are not interpreted.
command: /usr/bin/systemctl status nginx shell
Runs a command through /bin/sh, so shell features like pipes and redirects actually work.
shell: ps aux | grep nginx debug
Prints a message or variable value during a playbook run, mainly for troubleshooting.
debug: {msg: 'Deployment starting'} set_fact
Sets a variable at runtime that is available to later tasks in the same play.
set_fact: {app_version: '1.2.3'} lineinfile
Ensures a specific line exists in a file, adding or replacing it as needed.
lineinfile: {path: /etc/hosts, line: '127.0.0.1 app.local'} blockinfile
Inserts or updates a marked, multi-line block of text in a file, safely re-runnable.
blockinfile: {path: /etc/motd, block: 'Managed by Ansible'} get_url
Downloads a file from HTTP, HTTPS, or FTP to the remote host.
get_url: {url: 'https://example.com/app.tar.gz', dest: /tmp/app.tar.gz, mode: '0644'} unarchive
Extracts a tar or zip archive on the remote host, optionally unpacking one already fetched with get_url.
unarchive: {src: /tmp/app.tar.gz, dest: /opt/app, remote_src: true} wait_for
Pauses playbook execution until a port, file, or string condition is met.
wait_for: {port: 8080, delay: 5, timeout: 60} uri
Sends an HTTP request and can validate the response, useful for health checks and API calls.
uri: {url: 'http://localhost/health', return_content: true} stat
Retrieves file or file system status information, commonly used with a when condition.
stat: {path: /etc/app.conf} assert
Fails the play with a clear message if a condition is not true, useful for pre-flight checks.
assert: {that: inventory_hostname is defined} Ansible is an agentless automation tool that configures servers over plain SSH, running small Python programs called modules on the remote host and then removing them, rather than requiring a permanently installed agent like some competing tools. A playbook describes the desired end state of a server in YAML, such as a package being installed or a service running, and Ansible figures out whether any change is actually needed before making it. This agentless design is a big part of why Ansible spread so quickly through operations teams: there is nothing to install or maintain on the managed hosts beyond Python and SSH, both of which almost every Linux server already has.
The reason ansible-playbook shows up in daily operations work so often is that server configuration drifts constantly. A manually patched package, a config file edited directly during an incident, or a cron job added by hand during a one-off fix all quietly pull a server away from its intended state. Running the same playbook repeatedly and safely, a property called idempotency, is what lets a team re-apply the source of truth on a schedule or after every incident and trust that only the actual drift gets corrected, not everything getting torn down and rebuilt from scratch.
The single most important mental model for working with Ansible is that almost every module describes a desired state, not a sequence of steps. The apt module's state: present does not mean run apt-get install, it means ensure this package ends up installed, checking first whether it already is. This is exactly why running a playbook twice in a row against an already-configured server reports no changes the second time: every module already checked the current state and found nothing left to do. Commands like ansible-playbook --check and --diff exist specifically to preview that comparison before committing to it.
Three mistakes account for most of the frustration engineers hit when learning Ansible. The first is reaching for the shell or command module for something a dedicated module already handles, which throws away idempotency and the clean check-mode diff a real module provides. The second is forgetting that handlers only fire once, at the end of a play, and only if the notifying task actually reported a change, which trips people up when they expect a handler to run immediately or every time. The third is not understanding variable precedence, so an override in group_vars gets silently beaten by a leftover -e flag from a previous command in shell history, and the wrong value wins with no error message pointing at why.