Posted on
Artificial Intelligence

Artificial Intelligence for Infrastructure Documentation

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

Artificial Intelligence for Infrastructure Documentation (Bash-first)

If your on-call rotation has ever been ruined by stale runbooks, this one’s for you. Infrastructure evolves daily; docs rarely keep up. The result: tribal knowledge, brittle handovers, and firefights. The good news: the shell already knows your environment, and AI can turn that raw state into living, readable documentation.

This article shows how to combine Bash, standard Linux tooling, and AI to:

  • Auto-inventory systems

  • Generate human-friendly Markdown (and diagrams)

  • Keep docs versioned alongside your code

  • Reduce drift with lightweight automation

You’ll get actionable scripts and commands you can drop into your existing workflow.


Why AI for infra docs works now

  • Your systems are introspectable: ip, lsblk, systemctl, lshw, ansible-inventory all produce structured data (often JSON).

  • LLMs excel at summarizing, normalizing, and explaining structure—exactly what good docs need.

  • Version control and CI/CD let you treat docs as code (traceable, reviewable, reproducible).

  • Local models (e.g., via Ollama) reduce data risk while keeping iteration fast.

Result: docs that describe “what is” (from Bash), “what it means” (from AI), and “when it changed” (from Git).


Prerequisites and installation

Install these cross-distro packages.

  • jq

  • lshw

  • graphviz

  • pandoc

  • ansible (optional, for inventory-based docs)

  • git

  • curl

  • iproute2/iproute

Ubuntu/Debian (apt):

sudo apt update
sudo apt install -y jq lshw graphviz pandoc ansible git curl iproute2

Fedora/RHEL/CentOS (dnf):

sudo dnf install -y jq lshw graphviz pandoc ansible git curl iproute

openSUSE (zypper):

sudo zypper refresh
sudo zypper install -y jq lshw graphviz pandoc ansible git curl iproute2

Optional: local AI via Ollama (Linux):

curl -fsSL https://ollama.com/install.sh | sh
# Then pull a model, e.g.:
ollama pull llama3

Tip: If you use a cloud model, set your API key via environment variables and never send secrets or private keys in prompts.


1) Gather ground truth with Bash (JSON-first)

Start by extracting machine-readable state. Save as collect_inventory.sh:

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

OUT="${1:-inventory.json}"

host=$(hostnamectl --static 2>/dev/null || hostname)
os=$(awk -F= '/^PRETTY_NAME=/{gsub("\"","");print $2}' /etc/os-release)
kernel=$(uname -r)

# Hardware and storage
lshw_json=$(sudo lshw -json 2>/dev/null || echo 'null')
lsblk_json=$(lsblk -J -o NAME,KNAME,FSTYPE,SIZE,MOUNTPOINT,TYPE,MODEL,VENDOR)

# Networking
ip_addr_json=$(ip -j addr 2>/dev/null || echo '[]')
ip_route_json=$(ip -j route 2>/dev/null || echo '[]')

# Services (unit files)
services=$(systemctl list-unit-files --type=service --no-legend | awk '{print $1" "$2}' | awk 'NF' | jq -Rn '
  [inputs | capture("(?<name>\\S+)\\s+(?<state>\\S+)")]
')

# Top 10 listening sockets
listeners=$(ss -lntpH 2>/dev/null | head -n 50 | awk '{print $1,$4,$5,$6}' | jq -Rn '
  [inputs | capture("(?<proto>\\S+)\\s+(?<local>\\S+)\\s+(?<peer>\\S+)\\s+(?<proc>.*)")]
')

jq -n --arg host "$host" --arg os "$os" --arg kernel "$kernel" \
  --argjson lshw "$lshw_json" --argjson lsblk "$lsblk_json" \
  --argjson ipaddr "$ip_addr_json" --argjson iproute "$ip_route_json" \
  --argjson services "$services" --argjson listeners "$listeners" '
{
  collected_at: (now | todate),
  host: $host,
  os: $os,
  kernel: $kernel,
  hardware: $lshw,
  storage: $lsblk,
  networking: { addresses: $ipaddr, routes: $iproute },
  services: $services,
  listeners: $listeners
}
' | tee "$OUT"

Run it:

chmod +x collect_inventory.sh
./collect_inventory.sh infra-inventory.json

You now have a deterministic JSON snapshot of the box.


2) Turn JSON into Markdown with Bash

You can generate readable, zero-AI docs right from jq. Save as json_to_markdown.sh:

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

IN="${1:-infra-inventory.json}"
OUT="${2:-docs/$(hostname)-$(date +%F).md}"
mkdir -p "$(dirname "$OUT")"

jq -r '
def hdr($n): "# " + $n + "\n";
def shdr($n): "## " + $n + "\n";

hdr("System Documentation") +
"*Generated: \(.collected_at)*\n\n" +
shdr("Summary") +
"- Host: \(.host)\n" +
"- OS: \(.os)\n" +
"- Kernel: \(.kernel)\n\n" +

shdr("Network Interfaces") +
( .networking.addresses
  | map(select(.ifname != null))
  | map("### " + .ifname + "\n" +
        ( .addr_info // [] | map("- " + .local + "/" + (.prefixlen|tostring)) | join("\n") ) + "\n")
  | join("\n")
) +

shdr("Storage (lsblk)") +
( .storage.blockdevices
  | map("- " + .name + " (" + (.type//"") + ") " + (.size//"") + (if .mountpoint then " -> " + .mountpoint else "" end))
  | join("\n")
) + "\n\n" +

shdr("Services (unit files)") +
( .services
  | map("- " + .name + " - " + .state)
  | join("\n")
) + "\n\n" +

shdr("Listening Sockets (top)") +
( .listeners
  | map("- " + .proto + " " + .local + " " + (.proc|gsub("\"";"")) )
  | join("\n")
)
' "$IN" | tee "$OUT"

echo "Wrote $OUT"

Run it:

chmod +x json_to_markdown.sh
./json_to_markdown.sh infra-inventory.json

This baseline doc is already useful and reviewable in Git.


3) Add AI summaries and explanations (local or cloud)

Use AI to enrich the Markdown with architecture notes, risks, and action items.

Local (Ollama + llama3 example):

PROMPT=$(cat <<'EOF'
You are documenting a Linux host for SREs and auditors.

- Input: JSON inventory below

- Output: Append sections "Observations", "Potential Risks", "Notable Services", and "Next Steps" as Markdown bullets.

- Keep it concise, specific, and actionable. Do not invent data.

INVENTORY:
EOF
)
MODEL="llama3"
INPUT_JSON="infra-inventory.json"

{
  echo "$PROMPT"
  cat "$INPUT_JSON"
} | ollama generate -m "$MODEL" | tee -a docs/$(hostname)-$(date +%F).md

Cloud (replace with your provider; keep secrets out):

export OPENAI_API_KEY="YOUR_KEY"
PROMPT_FILE="prompt.txt"
cat > "$PROMPT_FILE" <<'EOF'
You are documenting a Linux host for SREs and auditors.

- Input: JSON inventory below

- Output: Append sections "Observations", "Potential Risks", "Notable Services", and "Next Steps" as Markdown bullets.

- Keep it concise, specific, and actionable. Do not invent data.

INVENTORY:
EOF

(
  cat "$PROMPT_FILE"
  cat infra-inventory.json
) | curl -s https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d @- | jq -r '.choices[0].message.content' | tee -a docs/$(hostname)-$(date +%F).md

Security tip:

  • Redact tokens, keys, and IPs if sending to any external service.

  • Consider local models for sensitive environments.


4) Auto-generate diagrams with Graphviz

Ask the AI to produce a Graphviz DOT from your JSON (e.g., interface-to-subnet view). Then render:

cat > network.dot <<'EOF'
digraph G {
  rankdir=LR;
  node [shape=box, fontname="monospace"];
  "host" [label="HOST: myserver"];
  "eth0" -> "10.0.1.0/24";
  "eth1" -> "192.168.50.0/24";
}
EOF

dot -Tpng network.dot -o docs/network.png

Link it in your Markdown:

![Network diagram](network.png)

You can script DOT generation from jq too, then let AI refine labels and grouping.


5) Keep docs close to code (Git hooks or CI)

Auto-refresh documentation on commits. Minimal pre-commit:

cat > .git/hooks/pre-commit <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

./collect_inventory.sh infra-inventory.json
./json_to_markdown.sh infra-inventory.json

# Optional: enrich with AI locally
if command -v ollama >/dev/null 2>&1; then
  PROMPT=$(cat <<'P'
Summarize key operational risks and next actions from the JSON inventory below as Markdown bullets.
Do not repeat already documented sections. Be concise and concrete.
P
)
  {
    echo "$PROMPT"
    cat infra-inventory.json
  } | ollama generate -m llama3 >> docs/$(hostname)-$(date +%F).md || true
fi

git add infra-inventory.json docs/
EOF
chmod +x .git/hooks/pre-commit

In CI, run the same scripts on a schedule to detect drift and open PRs with doc updates.


Real-world example: Document an Ansible inventory

If you manage fleets with Ansible, you can summarize roles, groups, and hostvars:

# Produce inventory JSON (replace with your inventory source)
ansible-inventory -i inventory.ini --list | tee fleet.json

# Ask AI for a fleet-level README
{
  echo "Create a fleet-level README.md summarizing groups, host counts, common vars, and any drift risks."
  echo "Output Markdown with sections: Overview, Groups, Roles, Variables of Interest, Notable Drift, Next Steps."
  cat fleet.json
} | ollama generate -m llama3 | tee FLEET-README.md

Pair that with Graphviz:

jq -r '
groups as $g
| "digraph Fleet {\nrankdir=LR;\nnode [shape=box];\n"
+ ( $g | to_entries
    | map( .key as $grp
           | ( .value.hosts // [] )
           | map("\""+$grp+"\" -> \""+.+ "\";")
           | join("\n")
      )
    | join("\n")
  )
+ "\n}\n"
' fleet.json > fleet.dot

dot -Tpng fleet.dot -o docs/fleet.png

Best practices

  • Start deterministic, then enrich: JSON via Bash, Markdown via jq, then AI summaries.

  • Keep prompts small and specific; ask for bullet lists, not prose essays.

  • Redact or hash sensitive values before AI steps.

  • Version everything; review AI output like code.

  • Test locally with a small model; scale up only as needed.


Conclusion and next steps

You don’t need a new platform to fix documentation drift—your shell already has the data. Combine:

  • Bash for ground truth

  • jq for structure

  • Graphviz for visuals

  • AI for concise explanations

Next steps: 1) Drop the two scripts into your repo and run them on one host.
2) Add the Git hook or a nightly CI job.
3) Experiment with the prompt to match your team’s style guide.
4) Extend to fleets via Ansible or your CMDB.

When the pager goes off, future-you will thank present-you for accurate, living docs.