- Posted on
- • Artificial Intelligence
Artificial Intelligence CDN Optimisation
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
AI-Driven CDN Optimisation with Bash: Predict, Pre‑warm, and Profit
Ever watched a blog post go viral and your origin creak while your CDN cache is still cold? Or seen TTFB spike because your TTLs aren’t tuned for real traffic patterns? AI can help you predict what users will want next—and your Bash toolbox can put those predictions to work.
This post shows you how to glue together logs, a lightweight AI prompt, and a few trusty CLI tools to:
Forecast hot assets from recent traffic
Pre-warm the CDN before the crowd shows up
Auto-tune cache TTLs based on predicted demand
Automate it all with cron
All from a Linux shell.
Why this is worth your time
CDN caches are only as good as what’s in them and how long they stay. Manual tuning can’t keep up with flash crowds or product drops.
AI (even a small LLM prompt) can spot likely next-clicks and hot segments from raw logs—without standing up a full ML pipeline.
Pre-warming and adaptive TTLs reduce TTFB and increase offload, saving origin resources and often cutting costs.
You don’t need to rewrite your stack—just add a thin AI-driven loop onto your existing CDN and NGINX/Apache logs.
Prerequisites (install once)
We’ll use curl, jq, and cron. Install them with your package manager:
Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y curl jq cron
sudo systemctl enable --now cron
Fedora/RHEL/CentOS (dnf):
sudo dnf install -y curl jq cronie
sudo systemctl enable --now crond
openSUSE (zypper):
sudo zypper refresh
sudo zypper install -y curl jq cron
sudo systemctl enable --now cron
Optional: if you run NGINX and want to auto-reload TTL maps:
- Debian/Ubuntu:
sudo apt install -y nginx
- Fedora/RHEL/CentOS:
sudo dnf install -y nginx
- openSUSE:
sudo zypper install -y nginx
Optional (local inference instead of a cloud LLM): Ollama
curl -fsSL https://ollama.com/install.sh | sh
# example model
ollama pull llama3.1:8b
Note: If you use a cloud LLM, set environment variables (export them in your shell or a .env file used by cron):
export AI_BASE_URL="https://api.openai.com/v1" # Any OpenAI-compatible endpoint works
export AI_MODEL="gpt-4o-mini" # Or your chosen model
export AI_API_KEY="sk-..." # Your API key
Architecture at a glance
Collect a sliding window of access logs.
Ask an LLM to return a compact JSON list of “hot” URLs and recommended TTLs.
Pre-warm those URLs via HEAD/GET through your CDN hostname.
Optionally write an NGINX TTL map and reload.
Run every 10 minutes via cron.
Step 1 — Sample your CDN/NGINX logs
This snippet extracts the most-hit paths from your recent log lines (Nginx combined format assumed), strips obvious noise, and builds a JSON payload for AI input.
#!/usr/bin/env bash
set -euo pipefail
LOG_FILE="${LOG_FILE:-/var/log/nginx/access.log}"
SAMPLE_LINES="${SAMPLE_LINES:-50000}"
WORK_DIR="${WORK_DIR:-/tmp/ai-cdn}"
mkdir -p "$WORK_DIR"
# Pull last N lines and extract request paths from NGINX combined log format
tail -n "$SAMPLE_LINES" "$LOG_FILE" \
| awk -F\" '($2 ~ /^GET|^HEAD/){split($2,a," "); print a[2]}' \
| grep -E '^/[A-Za-z0-9._~:/?#@!$&'"'"'()*+,;=%-]+' \
| grep -v -E '\?(utm_|fbclid|gclid|_ga=)' \
| grep -v -E '(\.php|\.cgi|/admin|/login|/wp-admin|/cart|/checkout)' \
| awk 'length($0) < 200' \
| sort \
| uniq -c \
| sort -nr \
| head -n 500 \
| awk '{count=$1; $1=""; path=substr($0,2); printf("{\"path\":\"%s\",\"hits\":%s}\n", path, count)}' \
> "$WORK_DIR/paths.ndjson"
jq -s '.' "$WORK_DIR/paths.ndjson" > "$WORK_DIR/paths.json"
echo "Built sample at $WORK_DIR/paths.json"
Tip:
Adjust filters to match your app (e.g., keep image/video extensions; exclude admin/auth).
If you use Apache, update the awk extraction appropriately.
Step 2 — Ask AI to predict “what’s hot next”
We’ll ask an OpenAI-compatible endpoint to return a compact JSON object with:
hot: a de-duped, ordered array of URLs to pre-warm
ttl_seconds: TTL recommendations per path
Cloud LLM example (OpenAI-compatible API):
#!/usr/bin/env bash
set -euo pipefail
WORK_DIR="${WORK_DIR:-/tmp/ai-cdn}"
AI_BASE_URL="${AI_BASE_URL:-https://api.openai.com/v1}"
AI_MODEL="${AI_MODEL:-gpt-4o-mini}"
AI_API_KEY="${AI_API_KEY:?AI_API_KEY not set}"
AI_MAX_URLS="${AI_MAX_URLS:-100}"
PROMPT_SYS='You are a CDN operations assistant. From recent request paths and hit counts, predict the next hot URLs for the next 30–60 minutes and suggest TTLs. Output ONLY compact JSON:
{"hot":["/a","/b"],"ttl_seconds":{"/a":3600,"/b":1800}}
Rules:
- Max '"$AI_MAX_URLS"' entries in "hot".
- Include only cacheable, GET-able assets (no admin/auth/private).
- Prefer static assets and popular product/category pages.
- TTLs: 10m–2h. Shorter for frequently changing pages, longer for static assets.
- No extra text.'
DATA_JSON=$(cat "$WORK_DIR/paths.json" | jq -c .)
HOUR_UTC=$(date -u +%H)
REQ=$(jq -n \
--arg model "$AI_MODEL" \
--arg sys "$PROMPT_SYS" \
--arg data "$DATA_JSON" \
--arg hour "$HOUR_UTC" \
'{
model: $model,
temperature: 0.2,
messages: [
{role:"system", content:$sys},
{role:"user", content: ("Recent paths (JSON array): " + $data + "\nCurrent UTC hour: " + $hour)}
]
}')
curl -sS \
-H "Authorization: Bearer $AI_API_KEY" \
-H "Content-Type: application/json" \
-d "$REQ" \
"$AI_BASE_URL/chat/completions" \
| jq -r '.choices[0].message.content' \
> "$WORK_DIR/ai_raw.txt"
# Ensure valid JSON; fall back to top hitters if AI returns junk
if ! jq -e . >/dev/null 2>&1 < "$WORK_DIR/ai_raw.txt"; then
echo "AI returned non-JSON; falling back to top 50."
jq -r '.[0:50] | map(.path) | {hot:., ttl_seconds:{}}' "$WORK_DIR/paths.json" > "$WORK_DIR/ai.json"
else
cat "$WORK_DIR/ai_raw.txt" > "$WORK_DIR/ai.json"
fi
jq -r '.hot[]' "$WORK_DIR/ai.json" > "$WORK_DIR/hot_paths.txt"
echo "AI predicted $(wc -l < "$WORK_DIR/hot_paths.txt") hot paths"
Local LLM with Ollama (optional):
# Assuming ollama serve is running and a model is pulled
PROMPT=$(cat <<'EOF'
SYSTEM:
You are a CDN operations assistant...
[Same JSON-only rules as above]
USER:
Recent paths (JSON array): __DATA__
Current UTC hour: __HOUR__
EOF
)
DATA_JSON=$(cat "$WORK_DIR/paths.json" | jq -c .)
HOUR_UTC=$(date -u +%H)
PROMPT_FILLED="${PROMPT/__DATA__/$DATA_JSON}"
PROMPT_FILLED="${PROMPT_FILLED/__HOUR__/$HOUR_UTC}"
curl -s http://localhost:11434/api/generate \
-d "$(jq -n --arg m "llama3.1:8b" --arg p "$PROMPT_FILLED" '{model:$m,prompt:$p,stream:false}')" \
| jq -r '.response' > "$WORK_DIR/ai.json"
jq -r '.hot[]' "$WORK_DIR/ai.json" > "$WORK_DIR/hot_paths.txt"
Privacy note: If using a cloud LLM, ensure you don’t send PII, tokens, or secrets. The filters above strip common noise, but review for your app.
Step 3 — Pre-warm your CDN
Hit the predicted hot URLs through your CDN hostname (not origin) with fast, parallel HEAD requests. This fills edge caches ahead of demand.
#!/usr/bin/env bash
set -euo pipefail
WORK_DIR="${WORK_DIR:-/tmp/ai-cdn}"
CDN_HOST="${CDN_HOST:?Set CDN_HOST to your CDN zone, e.g. cdn.example.com}"
CONCURRENCY="${CONCURRENCY:-16}"
# Use HEAD to avoid heavy origin load; switch to GET for CDNs that need object body to cache
xargs -I{} -P "$CONCURRENCY" \
curl -sSI "https://$CDN_HOST{}" \
-H 'User-Agent: ai-cdn-prewarmer/1.0' \
-H 'Cache-Control: no-transform' \
-o /dev/null \
-w '%{http_code} %{url_effective}\n' \
< "$WORK_DIR/hot_paths.txt" \
| tee "$WORK_DIR/prewarm_report.txt"
Tips:
Handle variants (webp/avif, mobile) if your site uses content negotiation.
Pre-warm regional POPs by running the job from different regions or via proxies if needed.
Step 4 — Adaptive TTL maps (NGINX example)
If you terminate at NGINX and use proxy_cache, you can feed AI-suggested TTLs into a map include and reload.
First, create an include file and a simple map (once):
sudo tee /etc/nginx/conf.d/cache-ttl-map.conf >/dev/null <<'NGINX'
map $request_uri $ai_cache_ttl {
default 10m;
include /etc/nginx/conf.d/hot-uris.ttl;
}
# Example usage in your location/server:
# proxy_cache_valid 200 $ai_cache_ttl;
NGINX
sudo touch /etc/nginx/conf.d/hot-uris.ttl
sudo nginx -t && sudo systemctl reload nginx
Now, write TTLs from AI output and reload:
#!/usr/bin/env bash
set -euo pipefail
WORK_DIR="${WORK_DIR:-/tmp/ai-cdn}"
TTL_FILE="/etc/nginx/conf.d/hot-uris.ttl"
if [[ -f "$WORK_DIR/ai.json" ]] && command -v nginx >/dev/null 2>&1; then
# Convert {"ttl_seconds":{"/a":3600,...}} to NGINX map lines: /a 3600s;
if jq -e '.ttl_seconds' "$WORK_DIR/ai.json" >/dev/null 2>&1; then
sudo bash -c "jq -r '.ttl_seconds | to_entries[] | \"\(.key) \(.value)s;\"' '$WORK_DIR/ai.json' > '$TTL_FILE'"
sudo nginx -t && sudo systemctl reload nginx
echo "Updated TTL map and reloaded NGINX."
else
echo "No ttl_seconds provided; skipping TTL update."
fi
else
echo "NGINX not found or ai.json missing; skipping TTL update."
fi
If you’re not on NGINX, adapt the same idea to your edge platform (e.g., VCL for Varnish, edge rules for your CDN provider).
Step 5 — Automate with cron
Run the full loop every 10 minutes. Place a wrapper at /usr/local/bin/ai-cdn-optimize.sh:
#!/usr/bin/env bash
set -euo pipefail
export LOG_FILE="/var/log/nginx/access.log"
export WORK_DIR="/tmp/ai-cdn"
export AI_BASE_URL="${AI_BASE_URL:-https://api.openai.com/v1}"
export AI_MODEL="${AI_MODEL:-gpt-4o-mini}"
export AI_API_KEY="${AI_API_KEY:?AI_API_KEY not set}"
export AI_MAX_URLS="${AI_MAX_URLS:-100}"
export CDN_HOST="${CDN_HOST:?Set CDN_HOST e.g. cdn.example.com}"
export CONCURRENCY="${CONCURRENCY:-16}"
# 1) sample logs
/path/to/step1.sh
# 2) ask AI
/path/to/step2.sh
# 3) pre-warm
/path/to/step3.sh
# 4) TTL update (optional)
/path/to/step4.sh
Create a cron job:
sudo tee /etc/cron.d/ai-cdn-optimize >/dev/null <<'CRON'
*/10 * * * * root /usr/local/bin/ai-cdn-optimize.sh >> /var/log/ai-cdn-optimize.log 2>&1
CRON
Service enablement recap:
Debian/Ubuntu: systemctl enable --now cron
Fedora/RHEL/CentOS: systemctl enable --now crond
openSUSE: systemctl enable --now cron
Real-world notes and guardrails
Keep it safe: Do not pre-warm authenticated or user-specific URLs. Filter aggressively.
Respect robots, rate limits, and provider billing. Throttle pre-warm concurrency if needed.
Measure: Track TTFB, cache hit ratio, origin CPU/egress before and after. Aim for higher offload and lower p95 TTFB.
Cost/latency trade-offs: Long TTLs are great for static assets, shorter for fast-changing pages. Let the AI propose, but you decide the bounds.
Rollback: Keep a default TTL map and revert if AI output looks wrong.
Conclusion and next steps
You don’t need a data science team to get AI benefits at the edge. A few Bash scripts + your logs + a small LLM prompt can:
Predict and pre-warm hot content
Auto-tune TTLs based on demand
Reduce TTFB and origin load during spikes
Your next step: 1) Install prerequisites (curl, jq, cron) using apt/dnf/zypper. 2) Wire up the scripts against your logs and CDN hostname. 3) Test on a staging CDN zone, then schedule via cron. 4) Measure results and iterate on filters/prompt.
Have questions or want a production-hardened version for your stack? Drop a comment with your distro/CDN and we’ll tailor a script.