---
title: "Ansible"
description: "Comprehensive Ansible cheatsheet covering playbooks, inventories, roles, tasks, variables, handlers, ad-hoc commands, modules, and configuration options."
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/cheatsheets/0028-ansible
---

# Ansible

Ansible is a powerful automation tool for configuration management, application deployment, and orchestration. This cheatsheet provides quick reference guides for common Ansible tasks, modules, and best practices to help you get started and work efficiently with Ansible.

## Getting Started

### Installation & Setup

Install Ansible and configure basic settings

**Keywords:** install, setup, config, requirements

#### Install Ansible on Ubuntu

```bash
sudo apt update
sudo apt install -y ansible
```

#### Install Ansible via pip

```bash
pip install ansible
pip install ansible==2.10.7
```

#### Verify Ansible Installation

```bash
ansible --version
```

_exec_
```bash
ansible 2.10.7
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.10.12
```

Displays installed Ansible version and configuration details

- Version should be 2.9+
- Python 3.6+ required

### Ansible Configuration File

Main configuration file setup at ansible.cfg

**Keywords:** config, ansible.cfg, settings, options

#### Create Basic ansible.cfg

```yaml
[defaults]
inventory = ./hosts
remote_user = ubuntu
private_key_file = ~/.ssh/id_rsa
host_key_checking = False
gather_facts = True
```

#### Configure Parallel Execution

```yaml
[defaults]
forks = 10
timeout = 30
retries = 3
```

forks increases parallelism for faster execution

- Default forks value is 5
- Higher forks = more parallelism = higher memory usage

### First Playbook Run

Execute your first Ansible playbook

**Keywords:** playbook, first, hello, test, run

#### Simple Hello World Playbook

```yaml
---
- name: Hello World
  hosts: all
  tasks:
    - name: Print Hello
      debug:
        msg: "Hello from Ansible"
```

_exec_
```bash
PLAY [Hello World] *****
TASK [Print Hello] *****
ok: [localhost] => {
    "msg": "Hello from Ansible"
}
PLAY RECAP *****
localhost : ok=1 changed=0 failed=0
```

Basic playbook that prints a debug message

- Playbooks must be valid YAML
- [object Object]

### Test Host Connectivity

Verify connectivity to managed hosts

**Keywords:** ping, connectivity, test, hosts, network

#### Ping All Hosts

```bash
ansible all -i hosts -m ping
```

_exec_
```bash
webserver01 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
database01 | SUCCESS => {
    "ping": "pong"
}
```

Tests connectivity to all hosts without running tasks

- ping module requires Python on remote
- SUCCESS indicates host is reachable

## Inventory Management

### Inventory Formats

Different ways to define managed hosts

**Keywords:** inventory, hosts, ini, yaml, format

#### INI Format Inventory

```ini
[webservers]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11

[databases]
db1 ansible_host=192.168.1.20
db2 ansible_host=192.168.1.21

[all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/id_rsa
```

INI format with groups and variables

- Groups defined with [groupname]
- [all:vars] applies to all hosts

#### YAML Format Inventory

```yaml
all:
  children:
    webservers:
      hosts:
        web1:
          ansible_host: 192.168.1.10
        web2:
          ansible_host: 192.168.1.11
    databases:
      hosts:
        db1:
          ansible_host: 192.168.1.20
  vars:
    ansible_user: ubuntu
```

YAML format for complex hierarchies

- Better for nested groups
- More readable for complex inventories

### Host Patterns

Select specific hosts or groups

**Keywords:** pattern, selection, filter, group, host

#### Target Specific Groups

```bash
ansible webservers -i hosts -m ping
ansible databases -i hosts -m ping
ansible 'webservers:!web2' -i hosts -m ping
```

_exec_
```bash
web1 | SUCCESS => {"ping": "pong"}
web2 | SUCCESS => {"ping": "pong"}
```

webservers targets group, !web2 excludes host

- webservers selects entire group
- negates selection

#### Wildcard and Range Patterns

```bash
ansible 'web*' -i hosts -m ping
ansible 'db[1:2]' -i hosts -m ping
ansible 'webservers[0]' -i hosts -m ping
```

Wildcards match patterns, [1:2] matches range

- * matches any characters
- [1:2] includes indexes 1 and 2

### Dynamic Inventory

Generate inventory from external sources

**Keywords:** dynamic, inventory, script, plugin, cloud

#### EC2 Dynamic Inventory

```yaml
plugin: aws_ec2
regions:
  - us-east-1
filters:
  tag:Environment: production
keyed_groups:
  - key: placement.region_name
    prefix: aws_region
```

AWS EC2 plugin pulls instances from AWS

- Requires boto3 library
- Cache results for performance

#### Custom Inventory Script

```bash
#!/bin/bash
cat << EOF
{
  "webservers": {
    "hosts": ["web1", "web2"]
  }
}
EOF
```

Custom script outputs JSON inventory format

- Script must be executable
- Output must be valid JSON

### Host Variables & Priorities

Set variables at different levels

**Keywords:** variables, host, group, priority, precedence

#### Host-Level Variables

```yaml
all:
  children:
    webservers:
      hosts:
        web1:
          ansible_host: 192.168.1.10
          http_port: 80
          server_role: primary
```

Variables specific to individual hosts

- Host variables override group variables
- Highest precedence level

#### Group Variables File

```bash
group_vars/webservers.yml
group_vars/webservers/main.yml
host_vars/web1.yml
```

Load variables from files by host/group name

- group_vars/groupname.yml for entire group
- host_vars/hostname.yml for single host

## Ad-Hoc Commands

### Basic Syntax

Run single tasks without playbook

**Keywords:** adhoc, command, module, execute, one-time

#### Run Adhoc Command

```bash
ansible all -i hosts -m shell -a "uptime"
```

_exec_
```bash
web1 | CHANGED | rc=0 >>
 10:45:23 up 5 days,  3:21,  2 users,  load average: 0.05, 0.10, 0.08
web2 | CHANGED | rc=0 >>
 10:45:24 up 3 days,  1:15,  1 user,  load average: 0.02, 0.06, 0.05
```

Execute shell command on all hosts

- -m specifies module
- -a passes arguments

#### Use copy Module

```bash
ansible webservers -i hosts -m copy -a "src=/etc/hosts dest=/tmp/hosts"
```

_exec_
```bash
web1 | CHANGED => {
    "changed": true,
    "checksum": "5d41402abc4b2a76b9719d911017c592",
    "dest": "/tmp/hosts",
    "gid": 0,
    "mode": "0644",
    "owner": "root",
    "size": 158,
    "src": "/tmp/ansible.87a8vz/hosts",
    "state": "file"
}
```

Copy file from control node to remote

- src path on control node
- dest path on remote

### Common Ad-Hoc Modules

Frequently used modules for ad-hoc tasks

**Keywords:** module, command, shell, copy, file, service

#### Package Management

```bash
ansible webservers -i hosts -m apt -a "name=nginx state=present"
```

_exec_
```bash
web1 | CHANGED => {
    "changed": true,
    "stderr": "",
    "stdout": "Reading package lists..."
}
```

Install nginx package

- apt for Debian/Ubuntu
- yum for Red Hat/CentOS

#### Service Management

```bash
ansible webservers -i hosts -m service -a "name=nginx state=started enabled=yes"
```

_exec_
```bash
web1 | CHANGED => {
    "changed": true,
    "enabled": true,
    "name": "nginx",
    "state": "started"
}
```

Start nginx service and enable on boot

- [object Object]
- enabled=yes enables service on boot

#### File Permissions

```bash
ansible all -i hosts -m file -a "path=/tmp/test.txt mode=0644 owner=root"
```

_exec_
```bash
web1 | CHANGED => {
    "changed": true,
    "mode": "0644",
    "owner": "root",
    "path": "/tmp/test.txt"
}
```

Set file permissions and ownership

- mode in octal format
- owner and group can be specified

### Parallelism & Forks

Control how many hosts execute simultaneously

**Keywords:** fork, parallel, limit, batch, speed

#### Limit Concurrent Execution

```bash
ansible all -i hosts -m ping -f 2
```

Execute on 2 hosts at a time instead of default

- -f or --forks sets parallelism
- Lower for safety, higher for speed

#### Serial Execution

```bash
ansible all -i hosts -m shell -a "systemctl restart app" -f 1
```

Execute one at a time (serial)

- Useful for rolling restarts
- Prevents service downtime

## Playbooks

### Playbook Structure

Create and organize playbooks

**Keywords:** playbook, structure, yaml, tasks, hosts

#### Basic Playbook Structure

```yaml
---
- name: Deploy Web Application
  hosts: webservers
  become: yes
  vars:
    app_port: 8080
    app_user: www-data
  tasks:
    - name: Install dependencies
      apt:
        name: python3-pip
        state: present
    - name: Start application
      command: /opt/app/start.sh
```

Complete playbook with all major sections

- --- indicates YAML document start
- [object Object]
- [object Object]

#### Multiple Plays in Single Playbook

```yaml
---
- name: Configure Databases
  hosts: databases
  tasks:
    - debug: msg="Setting up database"

- name: Configure Web Servers
  hosts: webservers
  tasks:
    - debug: msg="Setting up web server"
```

Multiple plays execute sequentially

- Each play is independent
- Plays execute in order

### Playbook Execution

Run playbooks with various options

**Keywords:** run, execute, syntax, check, tags, verbose

#### Run Basic Playbook

```bash
ansible-playbook playbook.yml -i hosts
```

_exec_
```bash
PLAY [Deploy Web Application] *****
TASK [Install dependencies] *****
ok: [web1]
ok: [web2]
TASK [Start application] *****
changed: [web1]
changed: [web2]
PLAY RECAP *****
web1 : ok=2 changed=1 failed=0
web2 : ok=2 changed=1 failed=0
```

Execute playbook against specified inventory

- ok = task already in desired state
- changed = task made changes

#### Check Mode (Dry Run)

```bash
ansible-playbook playbook.yml -i hosts --check
```

Preview changes without executing

- Shows what would change
- Useful before production runs

#### Run with Extra Variables

```bash
ansible-playbook playbook.yml -i hosts -e "env=production app_version=2.0"
```

Pass variables from command line

- -e or --extra-vars for variables
- Overrides defaults in playbook

#### Verbose Output

```bash
ansible-playbook playbook.yml -i hosts -vvv
```

Show detailed execution information

- -v = info, -vv = debug, -vvv = extra debug

### Conditionals

Execute tasks based on conditions

**Keywords:** when, conditional, if, condition, test

#### Simple When Condition

```yaml
- name: Install nginx if not exists
  apt:
    name: nginx
    state: present
  when: ansible_distribution == "Ubuntu"
```

_exec_
```bash
TASK [Install nginx if not exists] *****
skipped: [web1] => (item=centos)
ok: [web2] => (item=ubuntu)
```

Skip task if condition false

- Conditions use when keyword
- Access facts with ansible_variablename

#### Multiple Conditions

```yaml
- name: Restart service
  service:
    name: nginx
    state: restarted
  when:
    - ansible_os_family == "Debian"
    - ansible_distribution_version >= "20.04"
```

All conditions must be true (AND logic)

- List format uses AND logic
- [object Object]

## Tasks & Handlers

### Task Structure

Define and organize tasks

**Keywords:** task, name, register, debug, action

#### Basic Task Definition

```yaml
- name: Install web server
  apt:
    name: nginx
    state: present
  become: yes
  tags:
    - webserver
    - packages
```

Task with module, arguments, and tags

- [object Object]
- [object Object]

#### Register Task Output

```yaml
- name: Get service status
  command: systemctl status nginx
  register: nginx_status
  changed_when: false

- name: Display status
  debug:
    msg: "{{ nginx_status.stdout }}"
```

Save task output in variable for later use

- register stores full result
- Access with variable name

### Handlers

Run tasks on change events

**Keywords:** handler, notify, changed, event, restart

#### Basic Handler

```yaml
- name: Deploy application
  hosts: webservers
  tasks:
    - name: Copy app config
      copy:
        src: app.conf
        dest: /etc/app/app.conf
      notify: restart app
  handlers:
    - name: restart app
      service:
        name: app
        state: restarted
```

Handler executes if task notifies it

- Handlers only run if task changed
- Run at end of play by default

#### Multiple Handlers

```yaml
tasks:
  - name: Update config
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify:
      - reload nginx
      - log config change
handlers:
  - name: reload nginx
    service:
      name: nginx
      state: reloaded
  - name: log config change
    command: logger "nginx config updated"
```

Single task can notify multiple handlers

- Handlers run in defined order
- Duplicate handler calls only run once

### Loops

Repeat tasks with different variables

**Keywords:** loop, with_items, iterate, repeat, foreach

#### Loop Over List

```yaml
- name: Install multiple packages
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - php-fpm
    - mysql-client
```

_exec_
```bash
TASK [Install multiple packages] *****
ok: [web1] => (item=nginx)
ok: [web1] => (item=php-fpm)
ok: [web1] => (item=mysql-client)
```

Item variable changes per loop iteration

- [object Object]
- item is implicit variable name

#### Loop Over Dict

```yaml
- name: Create users
  user:
    name: "{{ item.name }}"
    uid: "{{ item.uid }}"
    state: present
  loop:
    - { name: 'alice', uid: 1001 }
    - { name: 'bob', uid: 1002 }
```

Loop over dictionary structures

- Access dict items with dot notation
- Useful for complex configurations

## Variables & Facts

### Variable Definition

Define and use variables

**Keywords:** variable, var, define, set, value

#### Play-Level Variables

```yaml
- name: My playbook
  hosts: all
  vars:
    db_host: localhost
    db_port: 3306
    db_name: myapp
    env: production
  tasks:
    - name: Connect to database
      debug:
        msg: "Connecting to {{ db_host }}:{{ db_port }}"
```

Define variables at play scope

- Accessible in all tasks
- {{ }} for variable substitution

#### Task-Level Variables

```yaml
- name: Configure service
  service:
    name: nginx
    state: started
  vars:
    nginx_user: www-data
    nginx_workers: 4
```

Variables local to specific task

- Only available in this task's context

### Gathering Facts

Collect system information from hosts

**Keywords:** facts, gather, discovery, system, info

#### Auto-Gather Facts

```yaml
- name: Display fact
  hosts: all
  tasks:
    - name: Show OS
      debug:
        msg: "OS: {{ ansible_os_family }}, Memory: {{ ansible_memtotal_mb }}"
```

_exec_
```bash
TASK [Show OS] *****
ok: [web1] => {
    "msg": "OS: Debian, Memory: 4096"
}
```

Facts gathered by default unless disabled

- ansible_* variables are facts
- [object Object]

#### Custom Facts

```bash
/etc/ansible/facts.d/custom.fact
{
  "app_version": "2.1.0",
  "deployment_date": "2026-01-15"
}
```

Define custom facts in JSON files

- Store in /etc/ansible/facts.d/
- Extension must be .fact

### Variable Precedence

Order of variable resolution

**Keywords:** precedence, priority, override, order

#### Precedence Levels

```yaml
# Lowest to highest precedence:
# 1. defaults/main.yml in role
# 2. group_vars/all
# 3. group_vars/groupname
# 4. host_vars/hostname
# 5. vars in playbook
# 6. vars_files
# 7. task vars
# 8. -e extra vars (highest)
```

Variables override based on source location

- Command line (-e) always wins
- Host vars override group vars

#### Override with Extra Vars

```bash
ansible-playbook playbook.yml -e "db_host=newhost db_port=5432"
```

Extra vars override all others

- -e highest precedence
- Useful for overriding defaults

### Variable Templating

Template and manipulate variable values

**Keywords:** template, jinja2, filter, transform, format

#### Jinja2 Filters

```yaml
- name: Use filters
  debug:
    msg: |
      Uppercase: {{ service_name | upper }}
      Lowercase: {{ domain | lower }}
      Default: {{ undefined_var | default('localhost') }}
      List join: {{ servers | join(',') }}
```

_exec_
```bash
TASK [Use filters] *****
ok: [localhost] => {
    "msg": "Uppercase: NGINX\nLowercase: example.com\nDefault: localhost\nList join: web1,web2,web3"
}
```

Transform variables with filters

- | for multiline strings
- | filters modify variable values

## Roles

### Role Structure

Organize code with roles

**Keywords:** role, structure, directory, reusable, organize

#### Role Directory Structure

```bash
roles/webserver/
├── tasks/
│   └── main.yml
├── handlers/
│   └── main.yml
├── vars/
│   └── main.yml
├── defaults/
│   └── main.yml
├── files/
├── templates/
└── meta/
    └── main.yml
```

Standard role directory structure

- tasks/ contains main task execution
- defaults/ provides variable defaults

#### Role Definition

```yaml
# roles/webserver/tasks/main.yml
---
- name: Install web server
  apt:
    name: nginx
    state: present
  become: yes

- name: Copy config
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: restart nginx
```

Define tasks in role

- Include handler definitions
- Keep role single-purpose

### Role Options & Includes

Include and configure roles

**Keywords:** include, import, role, vars, config

#### Include Role in Playbook

```yaml
- name: Deploy web application
  hosts: webservers
  roles:
    - webserver
    - php
    - mysql
```

Include multiple roles

- Roles execute in order
- Most common role usage

#### Role with Variables

```yaml
- name: Deploy web application
  hosts: webservers
  roles:
    - role: webserver
      vars:
        nginx_port: 8080
        nginx_workers: 8
    - role: php
      when: "'php' in group_names"
```

Pass variables to roles

- Vars override role defaults
- when can conditionally include roles

### Role Dependencies

Manage role dependencies

**Keywords:** dependency, depend, require, meta, include

#### Declare Dependencies

```yaml
# roles/php/meta/main.yml
---
dependencies:
  - role: webserver
  - role: database
    vars:
      db_type: mysql
```

Specify required roles

- Dependencies execute first
- Can pass variables to dependencies

## Modules

### System Modules

System administration modules

**Keywords:** system, package, service, file, user, group

#### User Management

```yaml
- name: Create user
  user:
    name: appuser
    uid: 2000
    home: /opt/app
    shell: /bin/bash
    state: present
```

_exec_
```bash
ok: [web1] => {
    "changed": false,
    "comment": "",
    "home": "/opt/app",
    "name": "appuser",
    "shell": "/bin/bash",
    "uid": 2000
}
```

Create system user with specified properties

- [object Object]
- uid specifies numeric user id

#### File Management

```yaml
- name: Create directory
  file:
    path: /opt/app/data
    state: directory
    mode: '0755'
    owner: appuser
    recurse: yes
```

_exec_
```bash
changed: [web1] => {
    "changed": true,
    "mode": "0755",
    "owner": "appuser",
    "path": "/opt/app/data",
    "state": "directory"
}
```

Create directory with permissions

- [object Object]
- [object Object]

### Package Management

Install and manage packages

**Keywords:** package, apt, yum, pip, install

#### APT Package Manager

```yaml
- name: Install packages
  apt:
    name:
      - curl
      - wget
      - git
    state: present
    update_cache: yes
```

Install multiple packages with cache update

- update_cache updates apt database
- [object Object]

#### PIP Package Manager

```yaml
- name: Install Python packages
  pip:
    name:
      - django==3.2
      - requests>=2.25
    virtualenv: /opt/app/venv
```

Install Python packages in virtualenv

- virtualenv creates/uses virtualenv
- Version pinning with == or >=

### Command Execution

Execute commands on remote hosts

**Keywords:** command, shell, script, raw

#### Command Module (Preferred)

```yaml
- name: Get nginx version
  command: nginx -v
  register: nginx_version
  changed_when: false
```

_exec_
```bash
ok: [web1] => {
    "cmd": ["nginx", "-v"],
    "rc": 0,
    "stderr": "nginx version: nginx/1.18.0",
    "stdout": ""
}
```

Execute command without shell processing

- No shell expansion (*, |, &)
- More predictable

#### Shell Module

```yaml
- name: Check if file exists
  shell: |
    if [ -f /opt/app/config.yml ]; then
      echo "exists"
    else
      echo "missing"
    fi
  register: config_check
```

Execute with shell processing

- Supports pipes, redirects
- Less secure, use with care

### Web & Net Modules

HTTP and network operations

**Keywords:** uri, get_url, url, download, http

#### HTTP Request

```yaml
- name: Health check
  uri:
    url: http://localhost:8080/health
    method: GET
    status_code: 200
  register: health_check
```

_exec_
```bash
ok: [web1] => {
    "changed": false,
    "content": "{\"status\":\"ok\"}",
    "status": 200
}
```

Make HTTP request and validate response

- status_code validates response
- body can parse JSON response

## Advanced Features

### Blocks & Error Handling

Group tasks and handle errors

**Keywords:** block, rescue, always, error, exception

#### Block with Error Handling

```yaml
- name: Database operations
  block:
    - name: Connect to database
      debug: msg="Connecting"
    - name: Run migrations
      command: /opt/app/migrations.sh
  rescue:
    - name: Rollback on error
      command: /opt/app/rollback.sh
  always:
    - name: Cleanup
      file:
        path: /tmp/app.lock
        state: absent
```

Block groups tasks with error handling

- [object Object]
- [object Object]
- [object Object]

#### Validate Task Results

```yaml
- name: Run test
  shell: npm test
  failed_when: "npm_test.rc != 0"
  changed_when: false
  register: npm_test
```

Control when task is marked failed/changed

- failed_when override failure detection
- changed_when override change detection

### Asynchronous Execution

Run long-running tasks in background

**Keywords:** async, poll, background, long-running, wait

#### Async with Polling

```yaml
- name: Long running task
  shell: /opt/app/long-job.sh
  async: 3600
  poll: 10
  register: long_job
```

_exec_
```bash
ASYNC OK on web1 (job_id=123456789.12345)
```

Run 1-hour task, check every 10 seconds

- [object Object]
- [object Object]

#### Fire and Forget

```yaml
- name: Start background service
  shell: /opt/app/service.sh
  async: 0
  poll: 0
```

Start task and don't wait for completion

- async: 0 and poll: 0 for fire-and-forget

### Advanced Variable Usage

Complex variable patterns

**Keywords:** variable, complex, nested, dict, list, hostvars

#### Access Host Variables

```yaml
- name: Reference another host
  debug:
    msg: "Database host: {{ hostvars['db1']['ansible_default_ipv4']['address'] }}"
```

Access variables from other hosts

- hostvars dict contains all host info
- Useful in multi-host plays

#### Nested Variable Access

```yaml
vars:
  services:
    web:
      port: 8080
      workers: 4
    db:
      port: 5432
      replicas: 3
tasks:
  - debug: msg="Web port {{ services.web.port }}"
```

Access deeply nested structures

- Dot notation for nested access
- Bracket notation also works

### Plugins & Extensions

Extend Ansible functionality

**Keywords:** plugin, filter, lookup, connection, callback

#### Custom Filters

```yaml
- name: Use custom filter
  debug:
    msg: "{{ 'hello' | custom_uppercase }}"
```

Apply custom filter plugins

- Place filters in filter_plugins/
- Extend Jinja2 capabilities

#### Lookup Plugins

```yaml
- name: Read file content
  set_fact:
    file_content: "{{ lookup('file', '/etc/config.yml') }}"

- name: Get environment variable
  debug:
    msg: "{{ lookup('env', 'HOME') }}"
```

Use lookup plugins for dynamic data

- file, env, pipe lookups common
- Results available mid-playbook

## Vault & Security

### Vault Basics

Encrypt sensitive data

**Keywords:** vault, encrypt, secret, password, security

#### Create Vault File

```bash
ansible-vault create secrets.yml
# Enter password, then edit:
# db_password: "secret123"
# api_key: "abc123xyz"
```

_exec_
```bash
New Vault password:
Confirm New Vault password:
```

Create encrypted YAML file

- Creates .yml with encrypted content
- Prompts for password

#### View Vault Content

```bash
ansible-vault view secrets.yml
# Password prompt
```

Decrypt and display vault file

- Requires vault password
- Doesn't save decrypted content

#### Edit Vault File

```bash
ansible-vault edit secrets.yml
```

Edit encrypted vault file safely

- Opens in editor
- Re-encrypts on save

### Using Vault in Playbooks

Reference vault variables in playbooks

**Keywords:** vault, include, vars, play, task

#### Include Vault Variables

```yaml
- name: Deploy app
  hosts: webservers
  vars_files:
    - secrets.yml
  tasks:
    - name: Configure database
      template:
        src: db.conf.j2
        dest: /etc/app/db.conf
      vars:
        db_password: "{{ vault_db_password }}"
```

Load vault variables in playbook

- [object Object]
- Automatic decryption on run

#### Run Playbook with Vault

```bash
ansible-playbook playbook.yml -i hosts --ask-vault-pass
```

_exec_
```bash
Vault password:
PLAY [Deploy app] *****
TASK [Configure database] *****
ok: [web1]
```

Run playbook requiring vault password

- --ask-vault-pass prompts for password
- --vault-password-file for automation

### Encrypt Individual Files

Encrypt specific files or variables

**Keywords:** encrypt, string, file, inline, protect

#### Encrypt Single Variable

```bash
ansible-vault encrypt_string --ask-vault-pass 'mypassword'
```

_exec_
```bash
Reading plaintext input from stdin.
New Vault password:
Confirm New Vault password:
!vault |
  $ANSIBLE_VAULT;1.1;AES256
  66386...
```

Encrypt individual secret for playbook

- Generates encrypted string
- Paste into playbook vars

#### Encrypt Specific Files

```bash
ansible-vault encrypt host_vars/prod.yml
```

Encrypt individual variable files

- Encrypts existing file in place

### Vault Best Practices

Security practices with vault

**Keywords:** vault, security, practice, password, protect

#### Password File Not in Repo

```bash
.gitignore:
.vault_pass

Run playbook:
ansible-playbook playbook.yml --vault-password-file ~/.vault_pass
```

Store vault password file locally, not in git

- Keep .vault_pass outside repository
- Use --vault-password-file for automation

#### Different Vaults for Environments

```bash
group_vars/prod/secrets.yml (encrypted)
group_vars/dev/secrets.yml (encrypted)
group_vars/staging/secrets.yml (encrypted)
```

Separate encrypted files per environment

- Different passwords per environment
- Enhanced security isolation

**Best practices:**

- Rotate vault passwords regularly
- Never commit .vault_pass or passwords to git
- Use --check before running production playbooks
- Implement version control for playbooks
- Document role dependencies
- Use meaningful task names
- Avoid hardcoding values
- Test in development environment first
- Use vault for all sensitive data
- Limit who can decrypt vault files

**Common errors:**

- **undefined**: undefined
- **undefined**: undefined
- **undefined**: undefined
- **undefined**: undefined
