Ansible CMDB — Generate Host Inventory Reports
Introduction
ansible-cmdb transforms Ansible fact-gathering output into browsable HTML reports, CSV files, and SQL databases. Instead of running ad-hoc commands to check what's running where, generate a complete inventory report: OS versions, IP addresses, memory, disk, installed packages — all in a searchable web page. It's infrastructure documentation that builds itself.
Installation
# pip install
pip install ansible-cmdb
# Debian/Ubuntu
apt-get install ansible-cmdb
# From source
git clone https://github.com/fboender/ansible-cmdb.git
cd ansible-cmdb
pip install .
# Verify
ansible-cmdb --version
Quick Start
# Step 1: Gather facts from all hosts
ansible -m setup --tree /tmp/facts all
# Step 2: Generate HTML report
ansible-cmdb /tmp/facts > cmdb.html
# Open in browser
xdg-open cmdb.html # Linux
open cmdb.html # macOS
That's it — two commands to a complete infrastructure report.
Gather Facts
# All hosts
ansible -m setup --tree /tmp/facts all
# Specific group
ansible -m setup --tree /tmp/facts webservers
# With custom inventory
ansible -i inventory/production -m setup --tree /tmp/facts all
# Limit to specific hosts
ansible -m setup --tree /tmp/facts --limit "web01,web02,db01" all
Each host produces a JSON file in the output directory:
/tmp/facts/
├── web01.example.com
├── web02.example.com
├── db01.example.com
└── lb01.example.com
Output Formats
HTML (Default)
# Full interactive HTML report
ansible-cmdb /tmp/facts > report.html
# With custom columns
ansible-cmdb -c name,os,ip,mem,cpus /tmp/facts > report.html
CSV
# CSV for spreadsheets
ansible-cmdb -t csv /tmp/facts > inventory.csv
# Import into Excel/Google Sheets for analysis
Markdown
# Markdown table
ansible-cmdb -t markdown /tmp/facts > inventory.md
SQL
# SQL INSERT statements
ansible-cmdb -t sql /tmp/facts > inventory.sql
# Import into database
sqlite3 cmdb.db < inventory.sql
JSON
# JSON output
ansible-cmdb -t json /tmp/facts > inventory.json
Custom Columns
# Select specific columns
ansible-cmdb -c name,os,ip,mem,cpus,disk /tmp/facts > report.html
# Available columns:
# name, fqdn, groups, os, ip, mac, arch,
# mem, cpus, disk, virt_type, vcpus,
# kernel, python_version, timestamp
Enrich with Inventory Data
# Include group and variable information
ansible-cmdb -i inventory/production /tmp/facts > report.html
# Multiple inventory sources
ansible-cmdb -i inventory/production -i inventory/staging /tmp/facts > report.html
Automate with Playbook
---
- name: Generate CMDB report
hosts: all
gather_facts: true
tasks:
- name: Save facts to file
ansible.builtin.copy:
content: "{{ ansible_facts | to_nice_json }}"
dest: "/tmp/facts/{{ inventory_hostname }}"
delegate_to: localhost
- name: Build report
hosts: localhost
connection: local
gather_facts: false
tasks:
- name: Generate HTML report
ansible.builtin.command:
cmd: ansible-cmdb /tmp/facts
register: cmdb_output
- name: Write report
ansible.builtin.copy:
content: "{{ cmdb_output.stdout }}"
dest: /var/www/html/cmdb/index.html
- name: Generate CSV
ansible.builtin.command:
cmd: ansible-cmdb -t csv /tmp/facts
register: csv_output
- name: Write CSV
ansible.builtin.copy:
content: "{{ csv_output.stdout }}"
dest: /var/www/html/cmdb/inventory.csv
Schedule Regular Reports
# Cron job to regenerate weekly
- name: Schedule CMDB generation
ansible.builtin.cron:
name: "Generate CMDB report"
minute: "0"
hour: "6"
weekday: "1"
job: >
ansible -m setup --tree /tmp/facts all &&
ansible-cmdb /tmp/facts > /var/www/html/cmdb/index.html
user: ansible
Custom Templates
# List available templates
ansible-cmdb --templates-list
# Use a specific template
ansible-cmdb -t html_fancy /tmp/facts > report.html
ansible-cmdb -t html_fancy_split /tmp/facts -p /var/www/html/cmdb/
# html_fancy_split creates per-host pages for large inventories
What the Report Shows
| Section | Data |
|---|---|
| Hostname | FQDN, short name |
| OS | Distribution, version, kernel |
| Hardware | CPUs, memory, architecture |
| Network | IP addresses, MAC, interfaces |
| Storage | Disk sizes, mount points |
| Groups | Ansible inventory groups |
| Virtualization | Type (kvm, docker, physical) |
| Python | Version installed |
| Timestamp | When facts were gathered |
Troubleshooting
| Issue | Solution |
|---|---|
| "No facts found" | Run ansible -m setup --tree /tmp/facts all first |
| Empty report | Check /tmp/facts/ has JSON files |
| Missing hosts | Host may be unreachable; check ansible all -m ping |
| Large inventory slow | Use html_fancy_split template for per-host pages |
| Facts stale | Re-run fact gathering; check timestamps in report |
| Custom facts missing | Ensure /etc/ansible/facts.d/ files exist on targets |
Alternatives
| Tool | Strength | vs ansible-cmdb |
|---|---|---|
| AWX/AAP | Full UI, RBAC, scheduling | Heavier; needs infrastructure |
| Ansible Facts caching | Built-in, no extra tool | No report generation |
| Netbox | Network-focused CMDB | More complex; separate system |
| Custom scripts | Fully flexible | More development effort |
Best Practices
- Schedule weekly regeneration — stale data is worse than no data
- Use
html_fancy_splitfor 100+ hosts — single HTML gets heavy - Store facts in git — track infrastructure changes over time
- Include inventory data —
-i inventoryadds group context - Serve via internal web server — make reports accessible to the team
- Generate CSV for management — non-technical stakeholders prefer spreadsheets
Conclusion
ansible-cmdb turns your existing Ansible fact-gathering into a self-updating infrastructure database. Two commands — gather facts, generate report — give you a searchable HTML page of every host, its OS, hardware, network, and groups. Schedule it weekly, serve it internally, and your infrastructure documentation stays current without manual effort.