Ansible to_yaml & to_nice_yaml Filters: Format Data as YAML (Guide)
By Luca Berton · Published 2026-04-03 · Category: database-automation
How to format data as YAML in Ansible with to_yaml, to_nice_yaml, from_yaml filters. Convert dicts and lists to YAML strings. Practical Jinja2 YAML examples.
The to_nice_yaml and to_yaml filters convert Ansible variables into YAML-formatted strings. They're essential for generating configuration files and debugging complex data structures.
to_yaml: Compact YAML
- name: Convert to compact YAML
ansible.builtin.debug:
msg: "{{ my_dict | to_yaml }}"
Output: {key1: value1, key2: value2}
See also: Ansible from_json & to_json Filters: Parse & Convert JSON (Guide)
to_nice_yaml: Human-Readable YAML
- name: Convert to readable YAML
ansible.builtin.debug:
msg: "{{ my_dict | to_nice_yaml }}"
Output:
key1: value1
key2: value2
Control Indentation
- name: Custom indent
ansible.builtin.debug:
msg: "{{ complex_data | to_nice_yaml(indent=4) }}"
See also: Ansible map Filter: Extract Attributes from Lists (Complete Guide)
Generate Configuration Files
- name: Write YAML config file
ansible.builtin.copy:
content: "{{ app_config | to_nice_yaml }}"
dest: /etc/myapp/config.yml
mode: '0644'
With a header comment
- name: Write config with header
ansible.builtin.copy:
content: |
# Auto-generated by Ansible - DO NOT EDIT
# Generated on {{ ansible_date_time.iso8601 }}
{{ app_config | to_nice_yaml }}
dest: /etc/myapp/config.yml
Practical Examples
Generate Docker Compose file
- name: Define compose config
ansible.builtin.set_fact:
compose_config:
version: "3.8"
services:
web:
image: "nginx:latest"
ports:
- "80:80"
volumes:
- "./html:/usr/share/nginx/html"
- name: Write docker-compose.yml
ansible.builtin.copy:
content: "{{ compose_config | to_nice_yaml }}"
dest: /opt/app/docker-compose.yml
Debug complex variables
- name: Pretty-print all host facts
ansible.builtin.debug:
msg: "{{ ansible_mounts | to_nice_yaml }}"
Generate Kubernetes manifests
- name: Create K8s deployment
ansible.builtin.copy:
content: "{{ k8s_deployment | to_nice_yaml }}"
dest: "/opt/k8s/deployment-{{ app_name }}.yml"
See also: Ansible map vs selectattr vs json_query: Filter Data the Right Way
to_nice_yaml vs to_yaml vs to_json
| Filter | Format | Human Readable | Use Case |
|--------|--------|---------------|----------|
| to_yaml | Compact YAML | No | Inline values |
| to_nice_yaml | Indented YAML | Yes | Config files |
| to_json | Compact JSON | No | API payloads |
| to_nice_json | Indented JSON | Yes | JSON config files |
Handle Special Characters
# to_nice_yaml handles quoting automatically
- set_fact:
config:
password: "p@ss:word{special}"
path: "/opt/my app/config"
- copy:
content: "{{ config | to_nice_yaml }}"
dest: /tmp/config.yml
# Output properly quotes strings with special characters
Width Control
# Prevent line wrapping for long strings
- debug:
msg: "{{ data | to_nice_yaml(width=1000) }}"
FAQ
Why does to_nice_yaml add quotes around some values?
YAML has special characters (:, #, {, etc.). The filter adds quotes when values contain characters that could be misinterpreted.
Can I control the YAML version output?
The filter uses PyYAML defaults (YAML 1.1). For YAML 1.2 compliance, post-process the output or use custom Jinja2 filters.
How do I handle boolean values?
PyYAML may represent booleans as true/false. If you need yes/no or True/False, convert with string filters before serialization.
Basic Usage
- vars:
config:
server:
host: 0.0.0.0
port: 8080
database:
host: db.example.com
port: 5432
name: myapp
debug:
msg: "{{ config | to_nice_yaml }}"
Output:
database:
host: db.example.com
name: myapp
port: 5432
server:
host: 0.0.0.0
port: 8080
Control Indentation
- debug:
msg: "{{ config | to_nice_yaml(indent=4) }}"
Write YAML Config Files
- name: Generate app config
ansible.builtin.copy:
content: "{{ app_config | to_nice_yaml }}"
dest: /etc/myapp/config.yml
mode: '0644'
become: true
to_yaml vs to_nice_yaml
- vars:
data: { a: 1, b: [1, 2, 3] }
debug:
msg:
- "Compact: {{ data | to_yaml }}"
# {a: 1, b: [1, 2, 3]}
- "Nice: {{ data | to_nice_yaml }}"
# a: 1
# b:
# - 1
# - 2
# - 3
YAML Filters Reference
| Filter | Output |
|--------|--------|
| to_yaml | Compact single-line YAML |
| to_nice_yaml | Human-readable indented YAML |
| from_yaml | Parse YAML string to data |
| to_json | Compact JSON |
| to_nice_json | Pretty-printed JSON |
Generate Kubernetes Manifests
- vars:
deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
ansible.builtin.copy:
content: "{{ deployment | to_nice_yaml }}"
dest: /opt/k8s/deployment.yml
In Templates
# config.yml.j2
---
{{ app_settings | to_nice_yaml }}
FAQ
Why does to_nice_yaml add quotes around some strings?
YAML auto-quotes values that look like booleans (yes, no, true), numbers, or contain special characters. This is correct YAML behavior.
How do I prevent sorting keys?
As of Ansible 2.14+, keys maintain insertion order by default in Python 3.7+.
Can I use to_nice_yaml with Ansible Vault encrypted values?
No — encrypted values must stay as !vault tagged strings. Use to_nice_yaml only for unencrypted data.
Basic Usage
- vars:
config:
database:
host: db.internal
port: 5432
cache:
enabled: true
ttl: 3600
debug:
msg: "{{ config | to_nice_yaml }}"
Output:
cache:
enabled: true
ttl: 3600
database:
host: db.internal
port: 5432
to_yaml vs to_nice_yaml
- debug:
msg: "{{ config | to_yaml }}"
# Compact: {cache: {enabled: true, ttl: 3600}, database: {host: db.internal, port: 5432}}
- debug:
msg: "{{ config | to_nice_yaml }}"
# Human-readable with proper indentation
Control Indentation
- debug:
msg: "{{ config | to_nice_yaml(indent=4) }}"
# With custom width (line wrap)
- debug:
msg: "{{ config | to_nice_yaml(indent=2, width=120) }}"
Write YAML to File
- copy:
content: "{{ app_config | to_nice_yaml }}"
dest: /etc/myapp/config.yml
become: true
# With header comment
- copy:
content: |
# Managed by Ansible - DO NOT EDIT
{{ app_config | to_nice_yaml }}
dest: /etc/myapp/config.yml
Generate Config Files
- vars:
nginx_config:
worker_processes: auto
events:
worker_connections: 1024
http:
sendfile: true
keepalive_timeout: 65
gzip: true
copy:
content: "{{ nginx_config | to_nice_yaml }}"
dest: /opt/myapp/nginx-config.yml
from_yaml + to_nice_yaml (Reformat)
# Read messy YAML, write clean YAML
- slurp: { src: /etc/myapp/config.yml }
register: raw
- copy:
content: "{{ raw.content | b64decode | from_yaml | to_nice_yaml }}"
dest: /etc/myapp/config.yml
In Templates
{# config.yml.j2 #}
# Auto-generated by Ansible
{{ config_data | to_nice_yaml }}
Combine and Output
- vars:
defaults:
log_level: info
port: 8080
overrides:
log_level: debug
set_fact:
final: "{{ defaults | combine(overrides) }}"
- copy:
content: "{{ final | to_nice_yaml }}"
dest: /etc/myapp/config.yml
YAML Filter Reference
| Filter | Output |
|--------|--------|
| to_yaml | Compact single-line YAML |
| to_nice_yaml | Formatted multi-line YAML |
| to_nice_yaml(indent=4) | Custom indentation |
| from_yaml | Parse YAML string to object |
| to_json | Compact JSON |
| to_nice_json | Formatted JSON |
FAQ
Why does to_nice_yaml sort keys?
YAML dumper sorts keys alphabetically by default. This is normal and doesn't affect functionality.
How do I preserve key order?
You can't with to_nice_yaml — it uses Python's YAML dumper which sorts keys. Use template with Jinja2 for exact control.
Strings with special characters?
to_nice_yaml automatically quotes strings that contain YAML special characters (:, #, {, etc.).
Related Articles
• rendering Jinja2 templates with Ansible • Ansible JSON Conversion Guide • container lifecycle with Ansible • argv form of Ansible command • Nginx deployment with AnsibleCategory: database-automation