Ansible OEL 8 DevOps · OEL 8 · Beginner

AnsibleYAML Primer

The 20% of YAML that covers 90% of Ansible — indentation rules, scalars, lists and maps, multi-line strings, and the seven gotchas that bite every beginner exactly once.

YAML — short for YAML Ain't Markup Language — is a human-friendly data serialisation format. Ansible playbooks are YAML files because YAML is easier to read and write by hand than JSON or XML, and because indentation-based structure forces readable layout.

💡 Tip: Every YAML file is also valid JSON when fully expanded. Ansible parses your .yml file into a Python dict — exactly what JSON would produce — then walks that dict to execute tasks.
  1. Indentation — uses spaces only (never tabs), and indentation level must be consistent within a block.
  2. Type of value — scalar (string, int, bool), list, or map.
  3. The starting marker--- at the top is optional but conventional. It says "a new YAML document begins here."
YAML — scalar types
# strings — quotes optional, but required if the value contains: # : { } [ ] , & * ! |
name: deploy            # no quotes
greeting: "Hello world" # double-quoted: \n, \t escape sequences active
literal: 'C:\\path'      # single-quoted: NO escape sequences (literal backslash)

# numbers — recognised as int / float by default
port:    3306
ratio:   0.75
big:     1_000_000      # underscores allowed for readability

# booleans — many spellings, all valid
enabled: true
debug:   yes            # also: True, On
silent:  false          # also: False, no, off

# null
unset:   null           # also: ~ or just empty
⚠ Warning: Norway problem: the country code NO in YAML 1.1 evaluates to false. Always quote two-letter country codes and version strings: country: "NO", version: "3.10" (otherwise 3.10 becomes the float 3.1).
YAML — lists and maps
# A list (sequence) — each item starts with a hyphen and a space
fruits:
  - apple
  - banana
  - cherry

# Same list, inline (flow) form
fruits: [apple, banana, cherry]

# A map (dictionary) — key: value pairs
user:
  name: deploy
  uid:  1000
  shell: /bin/bash

# Same map, inline form
user: {name: deploy, uid: 1000, shell: /bin/bash}

# A list of maps — the shape Ansible tasks use
tasks:
  - name: Install nginx
    ansible.builtin.dnf:
      name: nginx
      state: present

  - name: Start nginx
    ansible.builtin.systemd:
      name: nginx
      state: started
YAML — multi-line strings
# Literal block scalar (|) — preserves newlines exactly as written
welcome: |
  Welcome to db1.
  Authorised users only.
  All activity is logged.
# value is: "Welcome to db1.\nAuthorised users only.\nAll activity is logged.\n"

# Folded block scalar (>) — replaces single newlines with spaces
prose: >
  This is one long sentence
  written across multiple lines
  for readability.
# value is: "This is one long sentence written across multiple lines for readability.\n"

# Strip-trailing-newline variant (|-)
script: |-
  #!/usr/bin/env bash
  echo "hello"
# value ends without a trailing \n

An Ansible playbook is a list of plays. Each play is a map. Each play has a key called tasks whose value is a list of maps. Once you see it that way, the structure clicks:

YAML — playbook structure annotated
---                                # optional doc start
- name: Configure database servers   # a play (a map)
  hosts: databases                   # play-level key
  become: true
  vars:
    mysql_root_password: secret
  tasks:                             # list of tasks
    - name: Install MySQL            # one task (a map)
      ansible.builtin.dnf:           # module name
        name: mysql-server           # module args (also a map)
        state: present
    - name: Start MySQL
      ansible.builtin.systemd:
        name: mysqld
        state: started
        enabled: true

- name: Configure web servers        # second play in same file
  hosts: webservers
  tasks:
    - name: Install nginx
      ansible.builtin.dnf:
        name: nginx
        state: present
GotchaSymptomFix
Tabs instead of spacesYAML parser errorSet editor to "spaces, 2-wide" for .yml
Inconsistent indent within a blockdid not find expected keyPick 2 spaces and stay consistent
Unquoted version 3.10Becomes 3.1 (float)Quote it: "3.10"
Unquoted NO / YES / ONBecomes a booleanQuote two-letter codes: "NO"
Colon in unquoted stringmapping values are not allowedQuote: msg: "Hello: world"
Forgetting - for list itemsItem parses as a keyAdd hyphen + space at start of each item
Mixing flow (Ellipsis) and blockSubtle parse errorsPick one style per file
✅ Tip: Lint your YAML before running playbooks: pip install yamllint, then yamllint -d default *.yml. It catches every gotcha above in under a second.
BASH — syntax-check a playbook without running it
ansible-playbook --syntax-check site.yml
# parses YAML, resolves imports, validates every task name and module
# does NOT connect to any host and does NOT run any task

# even better: ansible-lint checks for best-practice violations
pip install ansible-lint
ansible-lint site.yml