- 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 --diffto 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 --diffare 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!