ARA Records Ansible — Ansible Playbook Reporting & Visualization

Scope: ARA (ARA Records Ansible) — an open-source Ansible callback plugin and Django-based reporting server that records every ansible and ansible-playbook run, exposes results via CLI, REST API, and a self-hosted web UI, and integrates with CI/CD, Prometheus, and LLMs via an MCP server.

Version covered: 1.8.0 (July 2026) License: GPLv3 Repository: codeberg.org/ansible-community/ara (mirrors: GitHub) Website: https://ara.recordsansible.org


Executive Summary

ARA (Another Recursive Acronym) Records Ansible and makes it easier to understand and troubleshoot playbook runs. It is an Ansible callback plugin that captures every playbook execution — tasks, hosts, results, facts, files, and metadata — and stores them in a database (SQLite, MySQL, or PostgreSQL). The recorded data is accessible through:

  • CLI (ara playbook list, ara host show, etc.) for scripting and terminal workflows
  • REST API for programmatic access and integrations
  • Web UI (self-hosted Django app) for visual browsing, filtering, and debugging
  • Prometheus exporter for metric scraping and alerting
  • MCP Server for LLM-driven analysis and troubleshooting

ARA is non-invasive: it works with existing Ansible setups, CI/CD pipelines (Jenkins, Rundeck, Zuul), git forges (GitHub, GitLab, Gitea, Forgejo), and tools like AWX, Ansible Runner, Ansible Navigator, Molecule, and Semaphore.


Architecture & How It Works

%%{init:{"theme":"neutral"}}%% flowchart LR A["📜 ansible-playbook playbook.yml"] --> B["ara_default callback plugin"] B --> C{"ARA_API_CLIENT"} C -->|"offline (default)"| D["📁 Local SQLite DB\n~/.ara/server/ansible.sqlite"] C -->|"http"| E["🌐 ARA API Server\nDjango REST + Web UI"] D --> F["ara CLI"] D --> G["ara-manage runserver\n(local web UI)"] E --> H["ara CLI\n(remote)"] E --> I["Web Browser\n(shared dashboard)"] E --> J["Prometheus Exporter\n:8001/metrics"] E --> K["🤖 MCP Server\n(LLM tools)"]

The ara_default callback plugin is the core component. It hooks into Ansible's notification system and collects data as the playbook runs:

  • Tasks — name, action (module), status, duration
  • Hosts — inventory name, facts (OS, kernel, Python, etc.)
  • Results — stdout, stderr, return code, diff, error messages
  • Files — playbook content, roles, tasks, templates, variables
  • Metadata — user, controller, Ansible version, Python version, CLI arguments, labels

This data is sent to the ARA API (either directly via Python in-process with the offline client, or over HTTP to a remote server).

%%{init:{"theme":"neutral"}}%% sequenceDiagram participant U as User participant A as Ansible participant C as ara_default callback participant API as ARA API Server participant DB as Database U->>A: ansible-playbook site.yml A->>C: task started / task finished C->>API: POST /api/v1/results API->>DB: INSERT result A->>C: playbook completed C->>API: playbook stats API->>DB: UPDATE playbook U->>API: GET /api/v1/playbooks API-->>U: JSON response U->>U: ara playbook list (CLI) Note over U,API: or browse http://server:8000

Core Features

Feature Description
Zero-config recording Install the package, set one env var, and every playbook is automatically recorded
Offline-first No server needed — records to local SQLite by default; spin up the UI any time with ara-manage runserver
Multiple database backends SQLite (default), MySQL/MariaDB, PostgreSQL
Distributed SQLite Serve multiple per-job databases from a single API instance — ideal for CI artifacts
Rich CLI List, show, delete, and get metrics for playbooks, plays, tasks, hosts, results, and records
REST API Full CRUD with filtering, pagination, ordering — browsable built-in interface at /api/v1/
Web UI Self-hosted Django reporting interface with playbook overviews, task drill-downs, host summaries, file diffs
Labels & naming Tag playbooks with custom labels and names for easy search and filtering
Authentication Optional read/write login, external auth (proxy headers), CORS configuration
Prometheus exporter Expose playbook/task/host metrics at /metrics for scraping and alerting
MCP Server Model Context Protocol server for LLM-driven troubleshooting and analysis
ara_record plugin Attach arbitrary key/value metadata to playbook reports (git SHA, URLs, JSON, logs)
ara_playbook plugin Look up playbook data from within Ansible plays (e.g., get the current playbook ID for a link)
ara_api lookup plugin Free-form API queries from Ansible playbooks
Privacy controls Ignore facts, files, arguments; disable recording of user/controller hostname
Container images Ready-to-run images on DockerHub and quay.io

Recording Workflow

%%{init:{"theme":"neutral"}}%% flowchart TD subgraph "Recording" P["ansible-playbook deploy.yml"] C["ara_default callback\n(Ansible plugin)"] P -->|"enabled via\nANSIBLE_CALLBACK_PLUGINS"| C end subgraph "Data Flow" C -->|"offline client"| SQLITE[("Local SQLite\n~/.ara/server/ansible.sqlite")] C -->|"HTTP client"| API[("ARA API Server\nMySQL/PostgreSQL/SQLite")] end subgraph "Consumption" SQLITE -->|"ara-manage runserver"| WEB["Web UI\nhttp://127.0.0.1:8000"] SQLITE --> CLI["ara CLI"] API --> WEB2["Web UI\n(shared dashboard)"] API --> CLI2["ara CLI\n(remote)"] API --> PROM["Prometheus\nExporter"] API --> MCP["MCP Server\n(LLM analysis)"] end

Installation Guide

Prerequisites

  • Python >= 3.10
  • Ansible (or ansible-core) installed for the same Python interpreter as ARA
  • Linux or macOS

Option 1: Local Recording (No Server) — Quick Start

This is the simplest mode. ARA records to a local SQLite database and you can launch a lightweight web UI on demand.

# 1. Install Ansible and ARA (with server dependencies for the web UI)
python3 -m pip install --user ansible "ara[server]"

# 2. Enable the ARA callback plugin
export ANSIBLE_CALLBACK_PLUGINS="$(python3 -m ara.setup.callback_plugins)"

# 3. Run a playbook as usual
ansible-playbook playbook.yml

# 4. List recorded playbooks via CLI
ara playbook list

# 5. Launch the web UI (serves at http://127.0.0.1:8000)
ara-manage runserver

Option 2: Persistent API Server (Docker)

For team dashboards, CI/CD aggregation, or long-term storage, run the ARA API server in a container:

# Create a data directory for settings and SQLite database
mkdir -p ~/.ara/server

# Start the API server (Docker)
docker run --name api-server --detach --tty \\
  --volume ~/.ara/server:/opt/ara -p 8000:8000 \\
  docker.io/recordsansible/ara-api:latest

# Or with Podman
podman run --name api-server --detach --tty \\
  --volume ~/.ara/server:/opt/ara -p 8000:8000 \\
  quay.io/recordsansible/ara-api:latest

Then configure clients to send data to it:

# Install only ARA (no server dependencies needed on the client)
python3 -m pip install --user ansible ara

# Configure the callback
export ANSIBLE_CALLBACK_PLUGINS="$(python3 -m ara.setup.callback_plugins)"

# Point to the API server
export ARA_API_CLIENT="http"
export ARA_API_SERVER="http://127.0.0.1:8000"

# Run a playbook
ansible-playbook playbook.yml

# Query remotely
ara playbook list

Option 3: Persistent API Server (Manual Install)

# Install with server dependencies
python3 -m pip install --user "ara[server]"

# Create a settings directory
mkdir -p ~/.ara/server

# Run database migrations
ara-manage migrate

# Create a superuser for the web UI
ara-manage createsuperuser

# Start the server (production: use gunicorn/uwsgi behind nginx)
ara-manage runserver 0.0.0.0:8000

Option 4: Database Backends (MySQL / PostgreSQL)

Set environment variables before starting the API server:

export ARA_DATABASE_ENGINE=mysql        # or postgresql
export ARA_DATABASE_NAME=ara
export ARA_DATABASE_USER=ara
export ARA_DATABASE_PASSWORD=secret
export ARA_DATABASE_HOST=db.example.com
export ARA_DATABASE_PORT=3306

# Then migrate and run as usual
ara-manage migrate
ara-manage runserver

Distribution Packages

Distribution Package Version
Fedora ara (official RPM) Up-to-date
Debian Bookworm ara-client, ara-server 1.5.8 (outdated)
Ubuntu 22.04/24.04 ara-client, ara-server 1.5.8 (outdated)
Arch Linux (AUR) python-ara 1.7.0 (outdated)
PyPI ara (official) 1.8.0 (latest)

Best practice: For production, use PyPI or the official container images. Distribution packages may lag behind. [1][6]


Configuration

Environment Variables

ARA is configured primarily through environment variables:

Variable Default Description
ANSIBLE_CALLBACK_PLUGINS (none) Must point to $(python3 -m ara.setup.callback_plugins) to enable ARA
ARA_API_CLIENT offline Client mode: offline (local SQLite) or http (remote API server)
ARA_API_SERVER http://127.0.0.1:8000 API server URL (HTTP client mode)
ARA_API_USERNAME (none) API auth username
ARA_API_PASSWORD (none) API auth password
ARA_API_TIMEOUT 30 HTTP request timeout in seconds
ARA_CALLBACK_THREADS 0 Thread pool size (0=no threads, recommended 4 for MySQL/PostgreSQL)
ARA_DEFAULT_LABELS (none) Comma-separated labels applied to all playbooks
ARA_ARGUMENT_LABELS remote_user,check,tags,skip_tags,subset CLI arguments auto-applied as labels
ARA_IGNORED_FACTS ansible_env Facts not saved (all to skip all)
ARA_IGNORED_FILES .ansible/tmp File path patterns not saved (supports regex: prefix)
ARA_IGNORED_ARGUMENTS extra_vars Ansible arguments not saved
ARA_RECORD_CONTROLLER true Record the controller hostname
ARA_RECORD_USER true Record the OS user
ARA_RECORD_TASK_CONTENT true Record task source content
ARA_LOCALHOST_AS_HOSTNAME false Use hostname instead of localhost in results

ansible.cfg

Equivalent settings can be placed in ansible.cfg:

[ara]
api_client = http
api_server = https://ara.example.com
api_username = user
api_password = password
callback_threads = 4
default_labels = prod,deploy
ignored_facts = all
localhost_as_hostname = true

Server Configuration

For the API server itself (set before starting ara-manage):

Variable Default Description
ARA_SECRET_KEY (auto-generated) Django secret key — set a fixed value in production
ARA_ALLOWED_HOSTS 127.0.0.1,localhost Allowed hostnames for the server
ARA_READ_LOGIN_REQUIRED false Require authentication to browse reports
ARA_WRITE_LOGIN_REQUIRED false Require authentication to record data
ARA_CORS_ORIGIN_WHITELIST (none) CORS allowed origins
ARA_DEBUG false Django debug mode

CLI Usage & Examples

Playbooks

# List recent playbooks
ara playbook list

# Filter by status
ara playbook list --status failed

# Filter by name or label
ara playbook list --name "deploy prod"
ara playbook list --label prod

# Show detailed info
ara playbook show 42

# Get playbook metrics
ara playbook metrics

# Delete old playbooks (older than 30 days)
ara playbook prune --days 30 --confirm

# Output as JSON
ara playbook list -f json

Tasks & Results

# List tasks for a playbook
ara task list --playbook 42

# Show task detail with source code
ara task show 1234

# List failed results
ara result list --status failed

# Show full result (stdout, stderr, return code)
ara result show 5678

Hosts

# List hosts
ara host list

# Show host facts
ara host show hostname.example.com

# Host metrics
ara host metrics

Records (Custom Metadata)

# List all records attached to playbooks
ara record list

# Show a specific record
ara record show 99

Data Lifecycle

# Expire playbooks stuck in "running" state for >24 hours
ara expire --hours 24 --confirm

Ansible Plugins & Use Cases

ara_record — Attach Metadata to Reports

Attach arbitrary data to playbook reports from within your playbooks:

- name: Record git version
  ara_record:
    key: "git_version"
    value: "{{ lookup('pipe', 'git rev-parse HEAD') }}"
    type: "text"     # text, url, json, list, dict

Types control how the data is rendered in the web UI:

- name: Record different data types
  ara_record:
    key: "{{ item.key }}"
    value: "{{ item.value }}"
    type: "{{ item.type }}"
  loop:
    - { key: "log", value: "Deployment complete", type: "text" }
    - { key: "ci_link", value: "https://ci.example.com/build/42", type: "url" }
    - { key: "artifacts", value: '{"version": "2.1.0"}', type: "json" }

Attach data after a playbook completes by specifying its ID:

ansible localhost -m ara_record \\
  -a "playbook=14 key=logs value={{ lookup('file', '/var/log/deploy.log') }}"

ara_playbook — Query Playbook Info from Ansible

- name: Get current playbook info
  ara_playbook:
  register: query

- name: Print link to this playbook's report
  debug:
    msg: "https://ara.example.com/playbooks/{{ query.playbook.id }}.html"

ara_api — Free-Form API Queries

- name: Count failed hosts across all playbooks
  ara_api:
    path: /api/v1/hosts?status=failed&limit=1
  register: result

Prometheus Exporter (New in 1.8.0)

ARA 1.8.0 (July 2026) introduces a built-in Prometheus exporter [5]:

# Start the exporter on :8001/metrics
ara prometheus --bind 0.0.0.0:8001

Exposed metrics include playbook counts by status, task durations, host result counts, and scrape health indicators. Includes example Prometheus rules and Grafana dashboard guidance in the documentation.


MCP Server — LLM-Driven Troubleshooting

ARA ships an optional Model Context Protocol (MCP) server that gives LLMs read-only access to recorded playbook data [3][4]. Models can analyze failures, compare runs, detect performance regressions, and identify secret leaks — all without dumping 60K+ tokens of terminal output into the context.

# Clone the repo and set up a virtualenv
git clone https://codeberg.org/ansible-community/ara ~/.ara/git/ara
cd ~/.ara/git/ara
python3 -m venv .venv
.venv/bin/pip install httpx mcp

Configure in your MCP client (Claude Code, VS Code, Cursor, Ollama, etc.):

{
  "mcpServers": {
    "ara": {
      "command": "/home/user/.ara/git/ara/.venv/bin/python",
      "args": ["/home/user/.ara/git/ara/contrib/mcp/ara_mcp.py"],
      "env": {
        "ARA_API_SERVER": "http://127.0.0.1:8000"
      }
    }
  }
}

The server exposes 13 tools across two categories [4]:

Foundation tools (direct API-to-text): get/list playbooks, tasks, hosts, results, files.

Wrapper tools (aggregated analysis): - troubleshoot_playbook — aggregates failures, code context, host facts, and a summary for debugging - troubleshoot_host — host-centric failure view - analyze_performance — cross-run timing analysis, slowest tasks, variance detection

Works with any MCP-compatible client and any model that supports tool use — including open-weight models like Qwen3, Devstral, GLM, and GPT-OSS.


Distributed SQLite Backend

For CI/CD environments where many jobs run concurrently, ARA supports a distributed SQLite mode. Instead of fighting SQLite's write concurrency limits, each CI job records to its own database. The ARA API server dynamically loads the correct database based on the URL path.

/var/www/logs/
├── job-1/ara-report/ansible.sqlite
├── job-2/some/path/ara-report/ansible.sqlite
└── job-3/dev/ara-report/ansible.sqlite

Configure with:

export ARA_DISTRIBUTED_SQLITE=true
export ARA_DISTRIBUTED_SQLITE_ROOT=/var/www/logs

The server then serves: - http://example.org/job-1/ara-report - http://example.org/job-2/some/path/ara-report

This approach is ideal for CI systems (Zuul, Jenkins) where each job produces its own artifact.


Web UI

The ARA web reporting interface is a self-hosted Django application that provides:

  • Dashboard — overview of recent playbooks with status indicators
  • Playbook view — detailed breakdown of plays, tasks, results per host
  • Host view — facts and result history per host
  • File browser — view recorded playbook/task/role source files with line-level context for results
  • Search & filter — by name, label, status, user, controller, date range
  • Static generationara-manage generate /path/to/output for offline archives

A live demo is available at https://demo.recordsansible.org.


Live Demo

Explore a live instance of ARA populated with real playbook data:

  • URL: https://demo.recordsansible.org
  • API: https://demo.recordsansible.org/api/v1/
  • Pre-loaded with playbooks from the ARA project's own CI

Tip: Use the API browser at https://demo.recordsansible.org/api/v1/ to explore the data model interactively — playbooks, tasks, hosts, results, and files are all linked by RESTful relationships.


Community & Project Status

Metric Value
GitHub Stars ~2,000
Forks 181
Contributors 45
Commits 1,083+
Release 1.8.0 (July 2026)
License GPLv3
Used by 640+ dependent repositories
Primary maintainer David Moreau-Simard (rfc2549)

The project is part of the ansible-community organization on GitHub, with primary development on Codeberg.

Community resources: - Blog: https://ara.recordsansible.org/blog/ - Documentation: https://ara.readthedocs.io/ - Ko-fi (support): https://ko-fi.com/rfc2549


References

# Source Type Key Finding
[1] ARA Project, Official Website, 2026. https://ara.recordsansible.org Project site ARA records Ansible playbooks and provides CLI, REST API, and web reporting
[2] ARA Project, Read the Docs — v1.8.0, 2026. https://ara.readthedocs.io/en/latest/ Official docs Complete documentation for install, config, API, CLI, plugins, and MCP server
[3] ARA Project, GitHub Repository, 2026. https://github.com/ansible-community/ara Source code ~2K stars, 181 forks, 45 contributors, GPLv3
[4] ARA Project, MCP Server Documentation, 2026. https://ara.readthedocs.io/en/latest/mcp-server.html Feature docs 13 MCP tools for LLM access to playbook data, including troubleshoot and performance analysis wrappers
[5] ARA Project, Prometheus Exporter, 2026. https://ara.readthedocs.io/en/latest/prometheus-exporter.html Feature docs Built-in Prometheus metrics exporter added in 1.8.0
[6] ARA Project, Distribution Packages, 2026. https://ara.readthedocs.io/en/latest/distribution-packages.html Reference Official packages on PyPI, Fedora, Debian, Ubuntu, Arch (AUR)

Last updated: 2026-07-30