DEV Community

Cover image for Strengthen Your Server with Automated Security Audits Using Ansible
Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on • Edited on

Strengthen Your Server with Automated Security Audits Using Ansible

Hello, I'm Maneshwar. I'm building git-lrc, an AI code reviewer that runs on every commit. It is free, unlimited, and source-available on Github. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product.

DevOps often emphasizes CI/CD, observability, and automation. But what about API documentation?

Keeping APIs well-documented can be challenging, especially in large organizations with numerous repositories.

Let's explore how to approach API documentation in a DevOps context.

Automating API Documentation: A Solution for Modern DevOps

Traditional methods of API documentation often involve manual effort and are prone to becoming outdated quickly. In modern DevOps environments, where code changes frequently, automation is key to keeping documentation synchronized and accurate.

Let's dive into some strategies for automating API documentation within your DevOps workflow:d uptime — but what about proactive security hardening?

This post walks you through how to set up automated, cron-based security auditing with ClamAV and Lynis, powered by Ansible, and how to post alerts directly to Discord.

You'll go from this:

ansible-playbook -i hosts.ini cron-all.yml -v
Enter fullscreen mode Exit fullscreen mode

To an infrastructure where every server audits itself and sends alerts every night, with zero manual effort.

Tools Used

  • Ansible — to orchestrate setup across all servers.
  • ClamAV — antivirus for Linux.
  • Lynis — a comprehensive Linux security auditing tool.
  • Cron — for scheduled execution.
  • Discord Webhooks — to notify you in real time.
  • Ansible Galaxy — for clean project structure.

Project Layout

Let’s generate a reusable role using Galaxy:

ansible-galaxy init roles/cron-all
Enter fullscreen mode Exit fullscreen mode

Here’s the final structure:

ansible/
├─ ansible.cfg
├─ cron-all.yml
├─ hosts.ini
├─ requirements.yml
├─ roles/
│  └─ cron-all/
│     ├─ tasks/
│     │  ├─ main.yml
│     │  ├─ crons.yml
│     │  └─ security_audit_issues.yml
│     ├─ templates/
│     │  ├─ crons.j2
│     │  └─ security_audit_issues.sh.j2
...
Enter fullscreen mode Exit fullscreen mode

The Ansible Playbook

# cron-all.yml
---
- name: Install crons on all hosts
  hosts: all
  become: yes
  gather_facts: true
  remote_user: ubuntu
  become_user: ubuntu
  roles:
    - cron-all
Enter fullscreen mode Exit fullscreen mode

This runs the cron-all role as ubuntu, while elevating when needed for root-level tasks (e.g. installing packages or accessing /var/log).

Installing ClamAV & Lynis with Ansible

# roles/cron-all/tasks/security_audit_issues.yml
- name: Install ClamAV and Lynis
  ansible.builtin.apt:
    name:
      - clamav
      - lynis
    state: present
    update_cache: true
  become: true
Enter fullscreen mode Exit fullscreen mode

Also ensure fresh virus definitions and set up directories for logs and quarantine:

- name: Ensure ClamAV virus definitions are up to date
  ansible.builtin.command: freshclam
  register: clamav_update
  changed_when: "'updated' in clamav_update.stdout"
  failed_when: false
  become: true

- name: Create log directory for security audit
  ansible.builtin.file:
    path: /home/ubuntu/crons/log
    state: directory
    owner: ubuntu
    group: ubuntu
    mode: "0755"
Enter fullscreen mode Exit fullscreen mode

Scheduling the Cron Job

A smart cron loop pulls jobs from a template:

# roles/cron-all/tasks/crons.yml
- name: Add custom cron jobs to ubuntu user crontab
  vars:
    lines: "{{ lookup('template', 'crons.j2').splitlines() }}"
  ansible.builtin.cron:
    name: "{{ (idx > 0 and lines[idx-1].strip().startswith('#')) | ternary(lines[idx-1] | trim | regex_replace('^#\\s*', ''), ' '.join(item.split()[5:])) }}"
    minute: "{{ item.split()[0] }}"
    hour: "{{ item.split()[1] }}"
    day: "{{ item.split()[2] }}"
    month: "{{ item.split()[3] }}"
    weekday: "{{ item.split()[4] }}"
    job: "{{ ' '.join(item.split()[5:]) }}"
    user: ubuntu
  loop: "{{ lines }}"
  loop_control:
    index_var: idx
  when: item | trim | length > 0 and not item.strip().startswith('#')
Enter fullscreen mode Exit fullscreen mode

The actual cron job comes from a template:

# roles/cron-all/templates/crons.j2
# 11:00 PM IST (converted to 17:30 UTC)
30 17 * * * sudo /bin/bash -lc "/home/ubuntu/crons/scan_and_audit.sh > /home/ubuntu/crons/log/scan_and_audit.log 2>&1"
Enter fullscreen mode Exit fullscreen mode

The Audit Script

This Bash script:

  • Logs to /var/log/security_audit_<timestamp>.log
  • Runs clamscan across /
  • Runs lynis audit system
  • Sends the results to Discord via webhook
# roles/cron-all/templates/security_audit_issues.sh.j2
#!/bin/bash
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

TIMESTAMP=$(date '+%Y-%m-%d_%H-%M')
LOG_FILE="/var/log/security_audit_$TIMESTAMP.log"
WEBHOOK_URL="https://discord.com/api/webhooks/..."  # Replace this

echo "🔐 Security Audit - $TIMESTAMP" | tee "$LOG_FILE"
echo "Running ClamAV scan..." | tee -a "$LOG_FILE"
mkdir -p /var/quarantine
clamscan -r / --infected --move=/var/quarantine | tee -a "$LOG_FILE"
CLAM_EXIT=${PIPESTATUS[0]}

echo -e "\nRunning Lynis audit..." | tee -a "$LOG_FILE"
lynis audit system | tee -a "$LOG_FILE"
LYNIS_EXIT=${PIPESTATUS[0]}

# Prepare status
if [[ $CLAM_EXIT -eq 0 && $LYNIS_EXIT -eq 0 ]]; then
    STATUS="✅ Security audit completed successfully."
else
    STATUS="⚠️ Security audit completed with issues."
fi

read -r -d '' PAYLOAD << EOF
{ "content": "**$STATUS**" }
EOF

curl -X POST "$WEBHOOK_URL" \
  -F "payload_json=$PAYLOAD" \
  -F "file=@$LOG_FILE"
Enter fullscreen mode Exit fullscreen mode

Running ItMake sure your hosts.ini points to your servers:

[all]
your-server-ip ansible_user=
Enter fullscreen mode Exit fullscreen mode
ansible-playbook -i hosts.ini cron-all.yml -v
Enter fullscreen mode Exit fullscreen mode

With LiveAPI, you can generate interactive API docs that allow users to search and execute endpoints directly from the browser.

Return only the cleaned text without any additional commentary:

git-lrc
*AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.*

Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.

⭐ Star it on GitHub:

GitHub logo HexmosTech / git-lrc

Free, Unlimited AI Code Reviews That Run on Commit

git-lrc logo

git-lrc

Free, Unlimited AI Code Reviews That Run on Commit


git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.

See It In Action

See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements

git-lrc-intro-60s.mp4

Why

  • 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production.
  • 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong.
  • 🔁 Build a habit, ship better code. Regular review → fewer bugs → more robust code → better results in your team.
  • 🔗 Why git? Git is universal. Every editor, every IDE, every AI…




Top comments (0)