# Ansible > Agentless automation — push-based configuration management over SSH. ## Core Concepts | Concept | Description | |-------------|--------------------------------------------------| | Inventory | Hosts and groups to manage | | Playbook | YAML file defining tasks to run on hosts | | Role | Reusable unit of tasks, vars, templates, handlers| | Task | Single action (install pkg, copy file, etc.) | | Module | Built-in unit of work (`apt`, `copy`, `template`)| | Handler | Task triggered by `notify`, runs once at end | | Facts | Auto-gathered host info (`ansible_os_family`) | | Vault | Encrypted secrets storage | ## Common Commands ```bash # Run ad-hoc command on all hosts ansible all -m ping ansible all -m shell -a "uptime" # Run playbook ansible-playbook site.yml ansible-playbook site.yml -l webservers # limit to group ansible-playbook site.yml --tags deploy # run tagged tasks only ansible-playbook site.yml --skip-tags debug # skip tagged tasks ansible-playbook site.yml -e "version=2.1" # extra vars (highest precedence) # Dry run / check mode ansible-playbook site.yml --check --diff # List hosts that would be affected ansible-playbook site.yml --list-hosts ansible-playbook site.yml --list-tasks ansible-playbook site.yml --list-tags # Vault ansible-vault create secrets.yml ansible-vault edit secrets.yml ansible-vault encrypt existing.yml ansible-vault decrypt existing.yml ansible-playbook site.yml --ask-vault-pass ansible-playbook site.yml --vault-password-file ~/.vault_pass # Galaxy (roles/collections) ansible-galaxy role install geerlingguy.docker ansible-galaxy role init my_role ansible-galaxy collection install community.general # Debug / info ansible --version ansible-config dump --only-changed ansible-inventory --graph ansible-inventory --host ``` ## ansible.cfg Config is loaded from the **first file found** in this order: 1. `$ANSIBLE_CONFIG` (env variable) 2. `./ansible.cfg` (current directory) 3. `~/.ansible.cfg` (home directory) 4. `/etc/ansible/ansible.cfg` (system-wide) ### Practical ansible.cfg ```ini [defaults] inventory = ./inventory/ roles_path = ./roles/ collections_path = ./collections/ remote_user = deploy private_key_file = ~/.ssh/id_ed25519 host_key_checking = False retry_files_enabled = False stdout_callback = yaml callback_enabled = timer, profile_tasks forks = 20 timeout = 30 gathering = smart fact_caching = jsonfile fact_caching_connection = /tmp/ansible_facts fact_caching_timeout = 3600 vault_password_file = ~/.vault_pass interpreter_python = auto_silent log_path = ./ansible.log [privilege_escalation] become = True become_method = sudo become_user = root become_ask_pass = False [ssh_connection] pipelining = True ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no control_path_dir = /tmp/.ansible-cp ``` ### Key Settings Explained | Setting | Effect | |------------------------|-------------------------------------------------| | `forks` | Parallel host connections (default: 5) | | `pipelining` | Reduces SSH operations, major speed gain | | `gathering = smart` | Cache facts, skip re-gathering | | `stdout_callback=yaml` | Human-readable output instead of JSON | | `fact_caching` | Persist facts between runs | | `retry_files_enabled` | Disable `.retry` file clutter | ## Gotchas - Config in current dir (`./ansible.cfg`) is ignored if the directory is world-writable - `become: true` in `ansible.cfg` applies globally — prefer setting it per play - `host_key_checking = False` is fine for labs, not for production - `forks` above ~50 can exhaust file descriptors on the control node - `pipelining` requires `requiretty` disabled in sudoers on targets ## See Also - `ansible-inventory` — inventory structure and dynamic inventories - `ansible-variables` — variable precedence and inheritance - `ansible-roles` — role structure and best practices