Day-to-Day Automation and Reporting with Ansible

Eran Goldman-Malka · November 24, 2025

Running a playbook manually is a proof of concept. Running it on a schedule with structured output, failure alerts, audit logs, and a compliance dashboard is operational patch management. The gap between the two is where most automation efforts stall—not because the tooling is missing, but because the reporting and scheduling layers never get built.

Scheduling Options

Method Best for
Cron Simple, single-host control nodes; no UI required
AWX / AAP Teams; role-based access; inventory management; job history
CI/CD (GitHub Actions / GitLab) Infrastructure-as-code workflows; change-controlled patching

Cron example (patch every Sunday at 02:00):

crontab -e
# Add:
0 2 * * 0 /usr/bin/ansible-playbook -i /opt/ansible/inventory/production/hosts.yml \
  /opt/ansible/playbooks/patch-linux.yml \
  --vault-password-file /opt/ansible/.vault_pass \
  >> /var/log/ansible-patch.log 2>&1

AWX / Ansible Automation Platform — create a Job Template pointing at your playbook and inventory, then attach a Schedule with a cron expression through the UI or API. AWX stores every job run, its output, and its status, giving you an audit log without any extra tooling.


Structured Logging with Callbacks

Ansible’s callback plugins transform run output into structured formats for storage or downstream processing.

Enable JSON logging in ansible.cfg:

[defaults]
stdout_callback = json
callback_whitelist = json, timer, profile_tasks

Or write to a log file:

[defaults]
log_path = /var/log/ansible/patch.log

For per-run JSON reports, use the json callback and redirect output:

ANSIBLE_STDOUT_CALLBACK=json ansible-playbook patch-linux.yml \
  -i inventory/production/hosts.yml \
  > /var/log/ansible/patch-$(date +%Y%m%d-%H%M%S).json

Patch Compliance Reporting

Generate a per-host compliance summary by registering results and writing them to a central location.

---
- name: Collect patch compliance data
  hosts: all
  become: true
  gather_facts: true

  tasks:
    - name: Get list of available security updates (Debian/Ubuntu)
      ansible.builtin.shell: apt-get --just-print upgrade 2>/dev/null | grep ^Inst | wc -l
      register: pending_updates
      changed_when: false
      when: ansible_os_family == "Debian"

    - name: Get last apt history entry
      ansible.builtin.shell: grep "Start-Date" /var/log/apt/history.log | tail -1
      register: last_patch_date
      changed_when: false
      when: ansible_os_family == "Debian"

    - name: Write compliance report entry
      ansible.builtin.lineinfile:
        path: /tmp/patch_compliance_.csv
        line: ",,,,"
        create: true
      delegate_to: localhost

- name: Consolidate compliance report
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Add CSV header
      ansible.builtin.lineinfile:
        path: /tmp/patch_compliance_.csv
        insertbefore: BOF
        line: "hostname,distro,version,pending_updates,last_patched"

SIEM Integration

Push patch results to a SIEM or log aggregator using the uri module or syslog.

POST to an HTTP endpoint (Splunk HEC, Elastic, etc.):

- name: Send patch result to SIEM
  ansible.builtin.uri:
    url: ""
    method: POST
    headers:
      Authorization: "Splunk "
      Content-Type: application/json
    body_format: json
    body:
      event:
        host: ""
        source: ansible-patch
        timestamp: ""
        updates_installed: ""
        reboot_required: ""
        status: "success"
    status_code: 200
  delegate_to: localhost

Write to syslog on each host:

- name: Log patch result to syslog
  ansible.builtin.command: >
    logger -t ansible-patch -p local0.info
    "host= status=patched updates="
  changed_when: false

Slack and Email Notifications

Slack (using community.general):

- name: Notify Slack on patch completion
  community.general.slack:
    token: ""
    channel: "#patch-ops"
    msg: >
      *Patch run completed* — 
      Hosts: 
      Failed: 
  delegate_to: localhost
  run_once: true

Email (using community.general.mail):

- name: Send patch summary email
  community.general.mail:
    host: ""
    port: 587
    username: ""
    password: ""
    to: ops-team@example.com
    subject: "Ansible Patch Report "
    body: ""
  delegate_to: localhost
  run_once: true

Drift Detection and Remediation

Drift means a host is no longer in the expected state—a package was manually installed, a service was changed outside of Ansible, or an update was applied through a different channel.

Detect drift with --check --diff on a scheduled basis:

# Run daily in check mode — alert if any changes would be made (i.e., drift found)
ansible-playbook -i inventory/production/hosts.yml playbooks/baseline.yml \
  --check --diff 2>&1 | tee /tmp/drift-$(date +%Y%m%d).log

# Alert if drift detected
if grep -q "changed=" /tmp/drift-$(date +%Y%m%d).log; then
  echo "Drift detected — review /tmp/drift-$(date +%Y%m%d).log" | \
    mail -s "Ansible drift alert" ops-team@example.com
fi

Automated remediation — run the playbook without --check on the same schedule to continuously enforce the desired state. This is appropriate for configuration items (file contents, service states) but requires careful thought before applying to patch state, where a forced upgrade could break compatibility.


Audit Trail Best Practices

  • Version control all playbooks and inventories in Git; every change is attributed and timestamped.
  • Use AWX or Automation Platform for a persistent job history accessible without SSH.
  • Store per-run JSON logs in an append-only location (object storage or SIEM) to satisfy audit requirements.
  • Log become escalations: who ran which playbook, on which inventory, at what time, from which control node.
  • Rotate but retain logs for the period required by your compliance framework (commonly 12 months for PCI-DSS, 7 years for some financial regulations).

Previous: Windows Server Patching with Ansible

Next in the series: Production Checklist and Maturity Roadmap — pre/during/post patching checklists, common pitfalls, and the path from manual to fully automated compliance-driven operations.

Twitter, Facebook