Posted on
Artificial Intelligence

Artificial Intelligence for Infrastructure Automation

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

Artificial Intelligence for Infrastructure Automation (with Bash-first workflows)

If you’ve ever been paged at 3 AM for a noisy alert only to run the same five commands you always run, you’ve felt the pain AI can relieve. We’re at a moment where large language models (LLMs) can read logs, propose actions, and draft clean Bash/Ansible snippets—while you keep policy, guardrails, and the final say. This post shows how to pair AI with the Unix philosophy: small, composable tools, glued together with Bash, for safer, faster infra automation.

What you’ll get:

  • Why AI for infra automation is valid right now (and where to be careful).

  • Concrete, Bash-first patterns that make AI useful from day one.

  • 3–5 actionable examples with ready-to-run scripts.

  • Installation instructions for apt, dnf, and zypper wherever tools are cited.

Note: All examples assume you explicitly approve changes. Keep a human in the loop.


Why AI belongs in your infra toolkit

  • It speaks logs and configs: LLMs are good at summarizing noisy logs (Ansible, systemd, kube, etc.), extracting root causes and next steps.

  • It drafts code quickly: Need an idempotent Ansible task or a portable Bash function? AI drafts, you lint and review.

  • It shifts toil left: Turn long runbooks into short prompts, then standardized scripts with tests.

  • It’s not magic: LLMs hallucinate. The recipe is deterministic tooling (Bash, Ansible, policy) plus AI as a suggestion engine, never an unsupervised actor. Add guardrails: linting, redaction, allowlists, and approvals.


Prerequisites

We’ll use common CLI tools plus Python for an API client. Replace $SUDO with sudo if needed.

Install on Debian/Ubuntu (apt):

$SUDO apt update
$SUDO apt install -y python3 python3-pip git curl jq ansible shellcheck

Install on Fedora/RHEL/CentOS (dnf):

$SUDO dnf install -y python3 python3-pip git curl jq ansible shellcheck
# If Ansible isn’t found on some RHEL versions, enable EPEL:
# $SUDO dnf install -y epel-release && $SUDO dnf install -y ansible

Install on openSUSE/SLES (zypper):

$SUDO zypper refresh
$SUDO zypper install -y python3 python3-pip git curl jq ansible shellcheck

Then install the OpenAI Python SDK (for a convenient CLI and API client):

python3 -m pip install --user --upgrade openai

Set your API key (substitute your value):

export OPENAI_API_KEY="sk-..."
# Optional: choose a model; adjust to your account’s available models
export MODEL="${MODEL:-gpt-4o-mini}"

Quick sanity check:

python3 - <<'PY'
import os, openai
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
r = client.chat.completions.create(model=os.getenv("MODEL","gpt-4o-mini"),
    messages=[{"role":"user","content":"Reply 'pong'"}])
print(r.choices[0].message.content)
PY

Actionable pattern 1: Generate safe Bash from a plain-English brief

Use AI to draft a script, then gate with shellcheck + bash -n before you run anything.

Create gen-bash.sh:

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

: "${OPENAI_API_KEY:?Missing OPENAI_API_KEY}"
MODEL="${MODEL:-gpt-4o-mini}"

prompt="${1:-"Write a portable bash script that prints disk usage per filesystem as JSON."}"

read -r -d '' SYS <<'EOF'
You are a strict Bash assistant. Output ONLY a bash script between triple backticks.
Constraints:

- Portable /bin/bash if needed; no destructive commands.

- Include set -euo pipefail and helpful comments.

- Prefer POSIX utilities (df, awk, sed, grep) and avoid dependencies unless noted.
EOF

tmp="$(mktemp)"
python3 - <<PY >"$tmp"
import os, json, openai, sys
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
sys_prompt = open(os.environ.get("SYS_PROMPT_FILE","/dev/stdin")).read() if False else """$SYS"""
user_prompt = """$prompt"""
r = client.chat.completions.create(
  model=os.getenv("MODEL","$MODEL"),
  messages=[
    {"role":"system","content":sys_prompt},
    {"role":"user","content":user_prompt}
  ],
  temperature=0
)
print(r.choices[0].message.content)
PY

code="$(awk '/^```/{c^=1;next} c' "$tmp" || true)"
if [ -z "${code:-}" ]; then
  echo "No code block found; raw output:"
  cat "$tmp"
  exit 1
fi

out="ai_script.sh"
printf "%s\n" "$code" > "$out"
chmod +x "$out"

echo "[i] Linting with shellcheck and parsing with bash -n..."
shellcheck "$out"
bash -n "$out"

echo "[✓] Generated and linted: $out"
echo "Review it, then run: ./ai_script.sh"

Usage:

./gen-bash.sh "Write a bash script that tails /var/log/auth.log, counts failed ssh logins per IP, and prints a top 10 table."

Tip: Keep a curated prompt library (problem statements you trust) in version control.


Actionable pattern 2: Summarize and diagnose Ansible failures

Pipe verbose logs into an LLM for blast-radius assessment and remediation hints. Keep secrets redacted.

ai-ansible-diagnose.sh:

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

: "${OPENAI_API_KEY:?Missing OPENAI_API_KEY}"
MODEL="${MODEL:-gpt-4o-mini}"

playbook="${1:-site.yml}"
shift || true
args=("$@")

ts="$(date +%s)"
log="ansible_run_$ts.log"

# Example run; tune verbosity to your needs
if ! ansible-playbook -vvv "$playbook" "${args[@]}" 2>&1 | tee "$log"; then
  echo "[!] Playbook failed; summarizing…"
fi

# Simple redaction: mask IPs and potential tokens; extend to your needs
redacted="$(mktemp)"
sed -E \
  -e 's/([0-9]{1,3}\.){3}[0-9]{1,3}/<IP>/g' \
  -e 's/(password|token|secret)[^[:space:]]*/\1=<REDACTED>/Ig' \
  "$log" > "$redacted"

read -r -d '' USER <<'EOF'
You are an Ansible SME. Given verbose Ansible logs:

- Summarize the failure(s) in bullet points.

- Identify the failing tasks/hosts and likely root cause.

- Suggest safe, idempotent fixes (Ansible tasks or module usage).

- Include any missing privileges or package dependencies.

- If nothing failed, summarize key changes.
Respond succinctly.
EOF

python3 - <<PY
import os, openai, sys
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
with open("$redacted","r",errors="ignore") as f:
    logs = f.read()[-120000:] # keep payload reasonable
r = client.chat.completions.create(
  model=os.getenv("MODEL","$MODEL"),
  messages=[
    {"role":"system","content":"Be precise. If uncertain, say so."},
    {"role":"user","content":"""$USER\n\n<logs>\n"""+logs+"\n</logs>"}
  ],
  temperature=0
)
print(r.choices[0].message.content)
PY

Run:

./ai-ansible-diagnose.sh site.yml -i inventory.ini --limit web

Actionable pattern 3: Human-in-the-loop “self-healing” with systemd OnFailure

Let systemd trigger a helper that summarizes the failure and proposes remediations. You approve before any command runs.

ai-remediate.sh:

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

: "${OPENAI_API_KEY:?Missing OPENAI_API_KEY}"
MODEL="${MODEL:-gpt-4o-mini}"
UNIT="${1:-}"

journal_tmp="$(mktemp)"
journalctl -u "$UNIT" -n 500 --no-pager > "$journal_tmp" || true

redacted="$(mktemp)"
sed -E \
  -e 's/([0-9]{1,3}\.){3}[0-9]{1,3}/<IP>/g' \
  -e 's/([A-Za-z0-9_]*SECRET[A-Za-z0-9_]*|API[_-]?KEY)[^[:space:]]*/<REDACTED>/g' \
  "$journal_tmp" > "$redacted"

read -r -d '' USER <<'EOF'
You are a Linux SRE. Read the service logs and propose up to 3 safe remediation commands.
Constraints:

- Prefer diagnostic commands first (systemctl status, journalctl, curl -I).

- If a config change is needed, output the exact sed or tee command with backup.

- Never propose destructive commands (rm -rf, :(){}, mkfs, etc.).

- Output in this JSON schema:
{"summary":"...", "risk":"low|medium|high", "commands":["...","..."], "notes":"..."}
EOF

resp="$(python3 - <<PY
import os, json, openai
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
with open("$redacted","r") as f: logs = f.read()[-60000:]
r = client.chat.completions.create(
  model=os.getenv("MODEL","$MODEL"),
  messages=[
    {"role":"system","content":"Be concise and safe."},
    {"role":"user","content":"""$USER\n\n<logs>\n"""+logs+"\n</logs>"}
  ],
  temperature=0
)
print(r.choices[0].message.content)
PY
)"

echo "[AI Proposal]"
echo "$resp" | jq .

echo
read -r -p "Apply proposed commands? (y/N) " ans
if [[ "${ans,,}" == "y" ]]; then
  echo "$resp" | jq -r '.commands[]' | while read -r cmd; do
    echo "[run] $cmd"
    bash -lc "$cmd"
  done
else
  echo "Skipped."
fi

Wire it into systemd:

notify-ai@.service:

[Unit]
Description=AI remediation helper for %i
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/ai-remediate.sh %i

Example unit override for a service:

$SUDO mkdir -p /etc/systemd/system/yourservice.service.d
cat <<'EOF' | $SUDO tee /etc/systemd/system/yourservice.service.d/onfailure.conf
[Unit]
OnFailure=notify-ai@%n.service
EOF

$SUDO cp ai-remediate.sh /usr/local/bin/
$SUDO chmod +x /usr/local/bin/ai-remediate.sh
$SUDO cp notify-ai@.service /etc/systemd/system/
$SUDO systemctl daemon-reload
$SUDO systemctl restart yourservice

Guardrails:

  • Redact aggressively.

  • Keep commands read-only by default; require explicit approval.

  • Consider an allowlist and blocklist before executing.


Actionable pattern 4: AI change review in your Git pre-commit

Combine linting with an AI risk assessment for staged changes to Bash/Ansible.

.git/hooks/pre-commit:

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

files="$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(sh|bash|yml|yaml)$' || true)"
[ -z "$files" ] && exit 0

echo "[i] shellcheck…"
echo "$files" | xargs -r shellcheck || {
  echo "[!] shellcheck failed"
  exit 1
}

: "${OPENAI_API_KEY:?Missing OPENAI_API_KEY}"
MODEL="${MODEL:-gpt-4o-mini}"

patch="$(git diff --cached -U0 -- $files)"

read -r -d '' POLICY <<'EOF'
You are a security reviewer. Rate risk of this change and list any violations.

- Flag use of rm -rf, sudo without need, curl|bash installs, world-writable perms, plaintext secrets.

- Ensure Ansible tasks are idempotent and use modules (not raw shell) when possible.

- Reply JSON only: {"risk":"low|medium|high","findings":["..."],"advice":["..."]}
EOF

resp="$(
python3 - <<PY
import os, json, openai, sys
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
patch = open(0).read()
r = client.chat.completions.create(
  model=os.getenv("MODEL","$MODEL"),
  messages=[
    {"role":"system","content":"Be strict and specific."},
    {"role":"user","content":"""$POLICY\n\n<patch>\n"""+patch+"\n</patch>"}
  ],
  temperature=0
)
print(r.choices[0].message.content)
PY
<<< "$patch"
)"

echo "$resp" | jq .
risk="$(echo "$resp" | jq -r '.risk // "low"')"
if [[ "$risk" == "high" ]]; then
  echo "[!] AI flagged high risk. Commit aborted."
  exit 1
fi

Make it executable:

chmod +x .git/hooks/pre-commit

Real-world style example: Cross-distro package update via Ansible

Ask AI to draft a safe, idempotent task file that updates a package across apt/dnf/zypper hosts, then you review and adjust:

Prompt idea:

"Write an Ansible task list that updates the 'jq' package across Debian/Ubuntu (apt), Fedora/RHEL (dnf), and openSUSE/SLES (zypper). Use package facts, conditionals, and idempotent modules. Add a handler if a restart is recommended."

You’ll typically get something like:


- name: Ensure jq is updated (apt) apt: name: jq state: latest update_cache: yes when: ansible_facts.os_family == "Debian" - name: Ensure jq is updated (dnf) dnf: name: jq state: latest when: ansible_facts.os_family == "RedHat" - name: Ensure jq is updated (zypper) zypper: name: jq state: latest when: ansible_facts.os_family == "Suse"

Then you:

  • Verify facts and conditionals match your fleet.

  • Add notify handlers if needed.

  • Test in staging.


Installing the tools we used (recap)

Ansible, shellcheck, jq, curl, git:

  • apt:
$SUDO apt update
$SUDO apt install -y ansible shellcheck jq curl git
  • dnf:
$SUDO dnf install -y ansible shellcheck jq curl git
# On some RHEL releases: $SUDO dnf install -y epel-release && $SUDO dnf install -y ansible
  • zypper:
$SUDO zypper refresh
$SUDO zypper install -y ansible shellcheck jq curl git

OpenAI Python client:

python3 -m pip install --user --upgrade openai

Best practices and gotchas

  • Redact before you send: IPs, tokens, emails, hostnames if sensitive. Consider a proxy that enforces redaction templates.

  • Keep payloads small: Tail logs, sample metrics, or diff-only patches.

  • Determinism first: Lint, test, policy—and then AI. Not the other way around.

  • Record decisions: Store AI proposals and your approvals in artifacts for auditability.

  • Start narrow: Summarization and code drafting offer big wins with low risk.


Conclusion and next steps

AI won’t replace your Bash, but it will make it faster, safer, and more maintainable—if you keep it on a leash. Start with: 1) Install the tooling and wire OPENAI_API_KEY. 2) Use gen-bash.sh to draft a script you need this week. 3) Add ai-ansible-diagnose.sh to your CI/CD or post-failure flows. 4) Pilot the systemd OnFailure helper in a non-critical service. 5) Turn on the pre-commit hook in one repo.

When you’re ready, expand prompts, add allowlists/blocklists, and measure ticket MTTR. Share your best prompts and guardrails with your team—your future 3 AM self will thank you.