- 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-inventoryall 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:

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.