Posted on
Artificial Intelligence

Artificial Intelligence Ansible Automation

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Artificial Intelligence + Ansible Automation: Build Smarter Ops from Your Linux Terminal

You’ve automated the easy stuff. But writing, testing, and maintaining great Ansible is still work: authoring idempotent tasks, standardizing roles, triaging noisy alerts, and keeping inventories sane. What if a local AI assistant could do the grunt work while you stay in control?

In this post, you’ll learn practical ways to bring AI into your Ansible workflow directly from Bash. We’ll set up a local LLM (no cloud key needed), then use it to:

  • Draft and lint playbooks faster

  • Enrich inventories with context

  • Trigger self-healing actions from logs and alerts

  • Prototype ChatOps for natural-language-to-playbook dry runs

All examples use standard Linux tooling and can be glued together in your existing pipeline.

Why AI + Ansible is a good fit

  • Structured output: LLMs are surprisingly good at emitting YAML, which makes them ideal copilots for roles, tasks, and playbooks.

  • Pattern recognition: They can summarize logs and map symptoms to known remediation runbooks.

  • Speed with guardrails: Combine generated content with ansible-lint, Molecule, and --check --diff to keep quality high.

  • Local-first: With a local model (via Ollama), you keep data on your machine and avoid vendor lock-in.


Install the toolchain

Run the commands for your distro. We’ll install Ansible and a few helpers (pipx, jq, podman). Then we’ll add common Ansible dev tools (ansible-lint, Molecule) and a local LLM runtime (Ollama).

1) Base packages

Debian/Ubuntu (apt):

sudo apt update
sudo apt install -y ansible python3-venv python3-pip pipx jq git podman

Fedora/RHEL/CentOS (dnf):

sudo dnf install -y ansible python3-pip pipx jq git podman

openSUSE Leap/Tumbleweed (zypper):

sudo zypper refresh
sudo zypper install -y ansible python3-pip python3-virtualenv pipx jq git podman

If pipx isn’t found after install, ensure your PATH:

python3 -m pipx ensurepath
# then open a new shell or source your profile

2) Ansible dev tools (via pipx)

pipx install ansible-lint
pipx install molecule
pipx install "molecule-plugins[podman]"

Optional: Event-Driven Ansible rulebook CLI

pipx install ansible-rulebook

3) Local LLM runtime (Ollama)

Ollama provides a local API and model runner. The script detects apt/dnf/zypper and installs the right package:

curl -fsSL https://ollama.com/install.sh | sh
sudo systemctl enable --now ollama
# pull a small, capable model
ollama pull llama3

Note: If you prefer containers, you can also run Ollama via Podman/Docker. Check the Ollama docs for GPU support and model choices.


1) Let AI draft and you harden: generate + lint + test

Use a local model to draft a playbook, then lint and test it. You stay in control; AI handles boilerplate.

Generate a starting playbook:

mkdir -p playbooks
ollama run llama3 "Write an Ansible playbook that:

- hardens SSH on Debian/Ubuntu

- ensures Protocol 2, disables root login, sets AllowUsers to 'deploy'
Return YAML only with proper keys (name, hosts, become, tasks)." > playbooks/harden_ssh.yml

Lint for correctness and style:

ansible-lint playbooks/harden_ssh.yml

Dry-run with diffs against a target:

ansible-playbook -i hosts.ini playbooks/harden_ssh.yml --check --diff

Optional: Bake it into a role and test with Molecule + Podman:

molecule init role harden_ssh -d podman
# Move/merge tasks into roles/harden_ssh/tasks/main.yml
molecule converge -s default
molecule verify -s default

Tip:

  • Always ask the model to “output YAML only, valid Ansible syntax” to reduce cleanup.

  • Keep prompts precise: constraints and desired idempotent checks go a long way.


2) AI-assisted inventory enrichment (suggest groups/tags)

You can use AI to suggest inventory groups (e.g., dev/prod/web/db) from host facts and names, then you decide whether to accept changes.

Example script that:

  • Gathers facts for a host

  • Asks the model to pick a group from an allowlist

  • Prints a safe, reviewable suggestion

ai_inventory_suggest.sh:

#!/usr/bin/env bash
set -euo pipefail

INV_FILE="${1:-hosts.ini}"
HOST="${2:-}"
if [[ -z "$HOST" ]]; then
  echo "Usage: $0 <inventory.ini> <host>"
  exit 1
fi

mkdir -p facts
# Gather facts to JSON files under ./facts/
ansible -i "$INV_FILE" "$HOST" -m setup --tree facts/ >/dev/null

FACTS_FILE="facts/$HOST"
if [[ ! -f "$FACTS_FILE" ]]; then
  echo "No facts for $HOST (check connectivity)."
  exit 1
fi

MINI_JSON=$(jq '{hostname: .ansible_facts.ansible_hostname,
                 fqdn: .ansible_facts.ansible_fqdn,
                 os: .ansible_facts.ansible_distribution,
                 os_ver: .ansible_facts.ansible_distribution_version,
                 mem_mb: .ansible_facts.ansible_memtotal_mb}' "$FACTS_FILE")

PROMPT=$(cat <<'EOF'
Given this host data, choose ONE group from this allowlist:
[ "dev", "stage", "prod", "web", "db", "cache" ].
Rules:

- Prefer "prod" if hostname or FQDN suggests prod/prod-*/*.prod.*

- Prefer "dev" or "stage" if name suggests it

- Otherwise infer from common roles in names (web, db, cache)
Return strict JSON: {"group": "<one>", "reason": "<short>"}
EOF
)

RESP=$(printf "System: You are a precise classifier.\nUser: %s\nHost data: %s\n" "$PROMPT" "$MINI_JSON" | \
       ollama run llama3)

# Try to extract the JSON object (handle models that add prose)
GROUP=$(echo "$RESP" | jq -r '.group' 2>/dev/null || true)
REASON=$(echo "$RESP" | jq -r '.reason' 2>/dev/null || true)

if [[ -z "$GROUP" || "$GROUP" == "null" ]]; then
  echo "Model did not return a valid group. Raw output:"
  echo "$RESP"
  exit 1
fi

echo "Suggested group for $HOST: [$GROUP] — $REASON"
echo "To apply, add the host under [$GROUP] in $INV_FILE, e.g.:"
echo
echo "[$GROUP]"
echo "$HOST"

Usage:

chmod +x ai_inventory_suggest.sh
./ai_inventory_suggest.sh hosts.ini web-01.example.com

Keep the human in the loop: review the suggestion, then update hosts.ini (or your inventory directory) accordingly.


3) Self-healing: AI picks a preapproved playbook

Let AI choose from a whitelist of playbooks and execute the mapped remediation. This example reads a log line or alert JSON from stdin, chooses an action, then runs ansible-playbook with --check first.

triage.sh:

#!/usr/bin/env bash
set -euo pipefail

INV="${1:-hosts.ini}"
LIMIT="${2:-all}"   # limit to a host/group
APPROVED=( "restart_nginx.yml" "clear_app_cache.yml" "bounce_celery.yml" "do_nothing" )

read -r -d '' POLICY <<'EOF' || true
You are an SRE triage helper. Pick ONE of these actions based on the incident text:

- restart_nginx.yml

- clear_app_cache.yml

- bounce_celery.yml

- do_nothing
Rules:

- Only choose an action from the list

- Prefer do_nothing if unclear
Return strict JSON: {"action":"<one-from-list>","rationale":"<short>"}
EOF

EVENT="$(cat)"  # read from stdin

RAW=$(printf "System: You decide remediations from a safe allowlist.\nUser: %s\nIncident: %s\n" "$POLICY" "$EVENT" | ollama run llama3)

ACTION=$(echo "$RAW" | jq -r '.action' 2>/dev/null || echo "")
REASON=$(echo "$RAW" | jq -r '.rationale' 2>/dev/null || echo "")

if [[ -z "$ACTION" ]]; then
  echo "Could not parse action. Raw output:"
  echo "$RAW"
  exit 2
fi

# Verify allowlist
FOUND="no"
for a in "${APPROVED[@]}"; do
  [[ "$a" == "$ACTION" ]] && FOUND="yes"
done

if [[ "$FOUND" != "yes" ]]; then
  echo "Model chose non-approved action: $ACTION"
  exit 3
fi

if [[ "$ACTION" == "do_nothing" ]]; then
  echo "Decision: do_nothing — $REASON"
  exit 0
fi

echo "Decision: $ACTION — $REASON"
echo "Dry-running remediation..."
ansible-playbook -i "$INV" "playbooks/$ACTION" --limit "$LIMIT" --check --diff

echo "Applying remediation..."
ansible-playbook -i "$INV" "playbooks/$ACTION" --limit "$LIMIT"

Example use with a log line:

echo 'Nginx upstream timed out, lots of 502s on /api' | ./triage.sh hosts.ini web

You can hook this into:

  • systemd unit OnFailure handlers

  • your alerting pipeline (pipe alert JSON into triage.sh)

  • CI/CD checks for known error patterns

Keep remediations minimal, idempotent, and well-tested. The allowlist is your safety net.


4) ChatOps prototype: natural language → dry-run playbook

Turn a sentence into a draft playbook, then immediately lint and dry-run it. Great for prototyping or guided ops.

ask-ansible.sh:

#!/usr/bin/env bash
set -euo pipefail

PROMPT="${*:-}"
if [[ -z "$PROMPT" ]]; then
  echo "Usage: $0 <what you want the playbook to do>"
  exit 1
fi

TMP="$(mktemp /tmp/ai-playbook.XXXXXX).yml"

REQ=$(cat <<'EOF'
Write a minimal Ansible playbook.
Requirements:

- YAML only, valid Ansible syntax

- Include: name, hosts: all, become: true, tasks

- Idempotent tasks, use package modules, handlers where sensible
EOF
)

ollama run llama3 "User request: $PROMPT. $REQ" > "$TMP"

echo "Generated playbook at $TMP"
echo "Linting..."
ansible-lint "$TMP" || true

echo "Dry-run (--check --diff) with inventory hosts.ini on hosts:all"
ansible-playbook -i hosts.ini "$TMP" --check --diff

Usage:

./ask-ansible.sh "install fail2ban and ensure it starts on boot with sane defaults"

Review the output, commit the result as a role, and expand tests as needed.


Best practices and cautions

  • Always lint, test, and dry-run: ansible-lint, Molecule, and --check --diff are non-negotiable.

  • Constrain the model:

    • Ask for YAML-only output.
    • Provide allowlists and rules for classification/triage.
  • Keep secrets out of prompts. Use vaults and environment variable redaction.

  • Prefer local models for sensitive environments; upgrade models when you need better reasoning.

  • Version and review AI-generated artifacts like any code.


Conclusion and next steps

AI won’t replace your ops expertise, but it will make you faster. Start small: 1) Generate and lint a playbook for a routine task. 2) Add the triage script with a tight allowlist for one service. 3) Pilot AI-assisted inventory suggestions and review them in code review.

From there, wire these pieces into your CI and monitoring. Your automation remains deterministic and reviewable; AI just accelerates the path from problem to playbook.

Call to action:

  • Set up the toolchain above

  • Try the four workflows on a non-prod inventory

  • Share what worked (and what didn’t) with your team

  • Iterate with stricter prompts, better tests, and clearer allowlists

Happy automating!