YAML Multiline Strings in Ansible: Literal, Folded & Block Scalars
By Luca Berton · Published 2024-01-01 · Category: installation
Complete guide to YAML multiline strings in Ansible playbooks. Understand literal block (|), folded block (>), strip, keep, and indent indicators.
Multiline strings in YAML are controlled by block scalars — the pipe (|) and greater-than (>) characters. Getting them right is essential for shell commands, configuration templates, and clean Ansible playbooks.
Quick Reference
| Syntax | Name | Newlines | Trailing | Example Use |
|--------|------|----------|----------|-------------|
| | | Literal | Preserved | One \n | Shell scripts, configs |
| |+ | Literal Keep | Preserved | All trailing | Scripts needing blank lines at end |
| |- | Literal Strip | Preserved | None | Strings that must not end with \n |
| > | Folded | Joined to spaces | One \n | Long sentences, descriptions |
| >+ | Folded Keep | Joined to spaces | All trailing | Paragraphs |
| >- | Folded Strip | Joined to spaces | None | Clean single-line output |
See also: Ansible Playbook Structure: Anatomy, Best Practices & Examples (2026)
Literal Block Scalar ( | )
Preserves newlines exactly as written. Each line break in YAML becomes a \n in the string.
- name: Run multi-line shell script
ansible.builtin.shell: |
#!/bin/bash
echo "Starting deployment"
cd /opt/app
git pull origin main
npm install
npm run build
systemctl restart app
The resulting string:
#!/bin/bash\necho "Starting deployment"\ncd /opt/app\n...
Common Use Cases for |
# Shell scripts
- name: Configure firewall
ansible.builtin.shell: |
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --reload
# Configuration file content
- name: Write nginx config
ansible.builtin.copy:
content: |
server {
listen 80;
server_name {{ domain }};
root /var/www/html;
location / {
try_files $uri $uri/ =404;
}
}
dest: /etc/nginx/conf.d/{{ domain }}.conf
# SSH keys, certificates
- name: Deploy SSL certificate
ansible.builtin.copy:
content: |
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiUMA...
-----END CERTIFICATE-----
dest: /etc/ssl/certs/app.crt
Folded Block Scalar ( > )
Joins lines with spaces — newlines become spaces, creating a single long line. Empty lines create actual line breaks.
- name: Show message
ansible.builtin.debug:
msg: >
This is a very long message
that spans multiple lines
in the YAML file but will
be joined into one line.
Result: This is a very long message that spans multiple lines in the YAML file but will be joined into one line.\n
Paragraphs with >
Empty lines in folded blocks create real line breaks:
vars:
description: >
This is the first paragraph
which gets folded into one line.
This is the second paragraph.
It also gets folded.
And a third paragraph.
Result:
This is the first paragraph which gets folded into one line.\n\nThis is the second paragraph. It also gets folded.\n\nAnd a third paragraph.\n
Common Use Cases for >
# Long descriptions
- name: Deploy application
ansible.builtin.debug:
msg: >
Deploying version {{ app_version }}
to {{ ansible_hostname }}
in the {{ env }} environment.
# Long command with arguments
- name: Run complex command
ansible.builtin.command: >
/usr/bin/myapp
--config /etc/myapp/config.yml
--log-level {{ log_level }}
--workers {{ workers }}
--bind 0.0.0.0:{{ port }}
# Long when conditions (with >-)
- name: Conditional task
ansible.builtin.debug:
msg: "Conditions met"
when: >-
ansible_os_family == 'RedHat'
and ansible_distribution_major_version | int >= 8
and enable_feature | default(false)
See also: Ansible Non-Compliant Variable Names: Fix Invalid Variables
Chomping Indicators: Strip (-) and Keep (+)
Control trailing newlines:
Default (clip) — One trailing newline
example: |
Hello
World
# Result: "Hello\nWorld\n"
Strip (-) — No trailing newlines
example: |-
Hello
World
# Result: "Hello\nWorld"
Keep (+) — All trailing newlines preserved
example: |+
Hello
World
# Result: "Hello\nWorld\n\n\n"
Practical Ansible Examples
Shell Scripts (use |)
- name: Setup application
ansible.builtin.shell: |
set -euo pipefail
cd /opt/app
if [ ! -d "venv" ]; then
python3 -m venv venv
fi
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
python manage.py collectstatic --noinput
args:
executable: /bin/bash
Jinja2 Templates (use |)
- name: Generate config from inline template
ansible.builtin.copy:
content: |
# Auto-generated by Ansible
[database]
host = {{ db_host }}
port = {{ db_port }}
name = {{ db_name }}
{% if db_ssl %}
ssl = true
ssl_ca = /etc/ssl/certs/ca.pem
{% endif %}
dest: /etc/app/database.conf
Long Variable Values (use >-)
vars:
# Won't have trailing newline
api_url: >-
https://api.example.com/v2
/organizations/{{ org_id }}
/projects/{{ project_id }}
/deployments
Result: https://api.example.com/v2 /organizations/123/projects/456/deployments
> ⚠️ Note: Folded blocks add a space where each line break was. For URLs, you typically want the lines to join without spaces. Use plain string concatenation with Jinja2 instead:
vars:
api_url: "https://api.example.com/v2/organizations/{{ org_id }}/projects/{{ project_id }}/deployments"
when Conditions (use >- or >)
- name: Complex conditional
ansible.builtin.debug:
msg: "All conditions met"
when: >-
(ansible_os_family == 'RedHat' and
ansible_distribution_major_version | int >= 8)
or
(ansible_os_family == 'Debian' and
ansible_distribution_major_version | int >= 11)
Multiline Variables
vars:
motd_banner: |
╔══════════════════════════════════════╗
║ {{ inventory_hostname | center(36) }} ║
║ Environment: {{ env | center(22) }} ║
║ Managed by Ansible ║
╚══════════════════════════════════════╝
email_body: >
Hello {{ user_name }},
Your deployment to {{ env }} has completed.
Version {{ version }} is now live on
{{ groups['webservers'] | length }} servers.
Regards,
Automation Team
See also: Ansible Async: Run Long-Running Tasks in Background (Complete Guide)
Common Mistakes
Using > When You Need |
# ❌ Wrong — folded joins lines, breaking the script
- name: Run script
ansible.builtin.shell: >
echo "line 1"
echo "line 2"
# Becomes: echo "line 1" echo "line 2" (one line!)
# ✅ Correct
- name: Run script
ansible.builtin.shell: |
echo "line 1"
echo "line 2"
Forgetting Indentation
# ❌ Wrong — content must be indented more than the key
- name: Bad indent
ansible.builtin.copy:
content: |
server {
listen 80;
}
# ✅ Correct
- name: Good indent
ansible.builtin.copy:
content: |
server {
listen 80;
}
FAQ
What is the difference between | and > in YAML?
| (literal) preserves all newlines — each line break in YAML becomes a \n in the string. > (folded) joins consecutive lines with spaces, turning multiple lines into one long line. Use | for scripts and configs; use > for long sentences.
How do I remove the trailing newline from a YAML block?
Add the strip indicator: |- or >-. This removes all trailing newlines from the block scalar value. Without it, YAML adds one trailing \n by default.
Which should I use for Ansible shell commands?
Use | (literal block) for multi-line shell scripts so each command stays on its own line. Use > (folded) for single commands with many arguments that you want on one line.
How does indentation work in YAML block scalars?
Content must be indented more than the block indicator line. The first content line sets the indentation level — all subsequent lines must match. Extra indentation within the block is preserved relative to the first line.
Can I use Jinja2 variables inside YAML multiline strings?
Yes, Jinja2 templates work inside both | and > blocks in Ansible. Variables like {{ var }} and control structures like {% if %} are processed normally.
Conclusion
•| (literal) — Use for shell scripts, configs, certificates (preserves newlines)
• > (folded) — Use for long descriptions, single commands with many args (joins lines)
• - (strip) — Remove trailing newlines when they'd cause issues
• + (keep) — Preserve all trailing newlines
• Most common in Ansible: | for shell/copy content, >- for long when conditions
Related Articles
• Ansible Playbook Structure & Best Practices • Ansible Playbook Examples: Complete Guide • Ansible Jinja2 Filters for Data TransformationSee also
• Ansible Multiline Strings: YAML Block Scalars | and > (Complete Guide)Category: installation