---
title: "Ansible"
description: "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/ansible
---

# Ansible

Ansible is an automation tool for configuration management, application deployment, and orchestration. This cheatsheet is a quick reference for common Ansible tasks, modules, and best practices.

## 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 overrides failure detection
- changed_when overrides 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
- Keeps secrets isolated between environments

**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:**

- **Forgetting the vault password prevents decryption.**: Keep a backup in a password manager
- **Committing .vault_pass exposes all secrets.**: Check .gitignore
- **Mixing encrypted and plain text in the same file fails.**: Use separate vault files
- **Skipping --check before a production run.**: Always check first
