Ansible Nested Lists: Loop Over Lists of Lists (with_subelements, flatten)
By Luca Berton · Published 2024-01-01 · Category: installation
How to work with nested lists in Ansible playbooks. Use subelements, flatten, and nested loops to iterate over complex data structures with practical examples.

Introduction
CfgMgmtCamp 2025, the premier event for systems administrators, DevOps engineers, and Infrastructure as Code enthusiasts, is taking place in Ghent, Belgium, from February 3–5, 2025. Among the many notable speakers, Luca Berton, a globally recognized Ansible expert, will share his expertise on automating AI-driven environments.
See also: Luca Berton at CfgMgmtCamp 2025: Ansible Automation Expert on Neo4j GenAI
Session Overview: Automating AI-Powered Graph Databases with Ansible
Title: Automating AI-Powered Graph Databases with Ansible: A Neo4j GenAI Case Study Date & Time: February 4, 2025, 14:00–14:25 Location: Ansible 1 (B.1.017) Session Type: Short Talk (25 minutes)
In this insightful session, Luca Berton will demonstrate: • Automating the deployment of Neo4j GenAI environments using Ansible playbooks. • Integrating OpenAI for retrieval-augmented generation (RAG) tasks. • Best practices for configuring, managing, and optimizing AI-powered graph databases in hybrid cloud environments.
This talk is tailored for IT professionals looking to streamline complex AI setups using modern Infrastructure as Code (IaC) techniques. Expect hands-on demonstrations and actionable takeaways to enhance your automation journey.
About Luca Berton
Luca Berton is a seasoned Ansible Automation Expert and the author of best-selling books, including: • Ansible for Kubernetes by Example: Automate Your Kubernetes Cluster • Ansible for VMware by Example
With over 15 years of experience, Luca has been a key contributor to the open-source community. He has worked with Red Hat and JPMorgan Chase & Co., leading projects in automation, infrastructure hardening, and hybrid cloud deployments.
See also: Automating AI-Powered Graph Databases with Ansible: Insights from CfgMgmtCamp 2025
Don’t Miss This Event
CfgMgmtCamp 2025 offers a unique platform to connect with thought leaders and explore the latest in configuration management, automation, and DevOps. Luca Berton's session promises to be a highlight for anyone passionate about cutting-edge AI and Ansible automation.
For more details and registration, visit CfgMgmtCamp 2025.
---
Resources
Check out Luca Berton’s books and resources to dive deeper into Ansible automation: • Ansible by Example: 200+ Automation Examples • Ansible for Kubernetes by Example
Want to support Luca’s work? Donate on Patreon.
See also: Setting Up Neo4j GenAI Environment on Fedora Using Ansible
Working with Nested Lists
Flatten nested lists
- name: Flatten nested list
vars:
nested_packages:
- [nginx, curl]
- [git, vim]
- [htop]
ansible.builtin.apt:
name: "{{ nested_packages | flatten }}"
state: present
become: true
# Installs: nginx, curl, git, vim, htop
Loop over list of dictionaries with sub-lists
- name: Create users with multiple groups
vars:
users:
- name: alice
groups: [developers, docker]
- name: bob
groups: [developers, sudo]
- name: charlie
groups: [ops, docker, sudo]
ansible.builtin.user:
name: "{{ item.name }}"
groups: "{{ item.groups | join(',') }}"
append: true
loop: "{{ users }}"
become: true
with_subelements (nested iteration)
- name: Add SSH keys for each user
vars:
users:
- name: alice
keys:
- "ssh-rsa AAAA... alice@laptop"
- "ssh-rsa BBBB... alice@desktop"
- name: bob
keys:
- "ssh-rsa CCCC... bob@work"
ansible.posix.authorized_key:
user: "{{ item.0.name }}"
key: "{{ item.1 }}"
with_subelements:
- "{{ users }}"
- keys
become: true
Nested loop (cartesian product)
- name: Create directories for each app in each environment
vars:
apps: [frontend, backend, api]
envs: [dev, staging, prod]
ansible.builtin.file:
path: "/opt/{{ item.1 }}/{{ item.0 }}"
state: directory
mode: '0755'
with_nested:
- "{{ apps }}"
- "{{ envs }}"
become: true
# Creates: /opt/dev/frontend, /opt/dev/backend, ..., /opt/prod/api
Modern loop with product filter
- name: Same as above using loop + product
ansible.builtin.file:
path: "/opt/{{ item.1 }}/{{ item.0 }}"
state: directory
mode: '0755'
loop: "{{ apps | product(envs) | list }}"
become: true
Accessing Nested Data
vars:
servers:
web:
- host: web1.example.com
port: 80
- host: web2.example.com
port: 8080
db:
- host: db1.example.com
port: 5432
# Access nested values
- debug:
msg: "{{ servers.web[0].host }}:{{ servers.web[0].port }}"
# Output: web1.example.com:80
# Loop over dict + sub-list
- debug:
msg: "{{ item.key }}: {{ item.value | map(attribute='host') | join(', ') }}"
loop: "{{ servers | dict2items }}"
FAQ
When should I use with_subelements vs loop + subelements filter?
They're equivalent. The filter syntax is more modern:
# Old style
with_subelements:
- "{{ users }}"
- keys
# Modern style
loop: "{{ users | subelements('keys') }}"
How do I flatten only one level deep?
# flatten(1) only removes one nesting level
- debug:
msg: "{{ [[1, [2, 3]], [4, 5]] | flatten(1) }}"
# Output: [1, [2, 3], 4, 5]
How do I handle optional sub-lists?
Use default([]) to handle missing keys:
loop: "{{ users | subelements('keys', skip_missing=True) }}"
Related Articles
• Ansible flatten Filter: Flatten Nested Lists & Remove DuplicatesCategory: installation