Posted on
Artificial Intelligence

MCP Checklists

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

MCP Checklists: A Bash-First Way to Keep Linux Boxes Healthy, Compliant, and Patched

If you’ve ever chased a 3 a.m. outage back to a full disk, a missed kernel fix, or a stale config, you know the pain is rarely about tools—it’s about discipline. Checklists turn “I thought someone handled that” into “we know it’s handled.” This post shows how to build an MCP Checklist—Maintenance, Compliance, and Patching—driven by Bash and cross-distro package managers, so you can prevent the avoidable and standardize what matters.

What we’ll solve

  • A lightweight, vendor-neutral routine you can run on any Linux server

  • Clear, auditable outputs for health, compliance posture, and patch status

  • Repeatable automation you can schedule and version-control

Think of this as a pilot’s preflight for your fleet: short, predictable, and relentlessly effective.


Why MCP checklists work (and why Bash?)

  • Checklists reduce cognitive load and variance. Your future self (or teammate) won’t forget the boring but critical steps.

  • Bash is ubiquitous. No agents. No heavyweight frameworks required. It’s easy to wire into cron, systemd timers, or CI.

  • Compliance and patching are measurable. You can export reports, track drift, and prove due diligence.


Prerequisites: Install common tools

We’ll use a few standard packages. Choose the block that matches your distro.

  • Debian/Ubuntu (apt):
sudo apt-get update
sudo apt-get install -y jq curl git smartmontools auditd openscap-scanner scap-security-guide lynis
sudo systemctl enable --now auditd
  • RHEL/CentOS/Fedora (dnf):
sudo dnf install -y jq curl git smartmontools audit openscap-scanner scap-security-guide lynis
sudo systemctl enable --now auditd
  • SUSE/openSUSE (zypper):
sudo zypper refresh
sudo zypper install -y jq curl git smartmontools audit openscap-utils scap-security-guide lynis
sudo systemctl enable --now auditd

Notes:

  • The oscap binary comes from openscap-scanner (apt/dnf) or openscap-utils (zypper).

  • Lynis is optional but very handy for quick hardening audits.


Step 1 — Start with a single, portable checklist script

Create mcp-checklist.sh as your one-command entry point. It detects the package manager, runs health checks, a compliance scan, and lists patches. Commit it to git and use it everywhere.

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

# Colors for visibility (optional)
ok() { printf "[OK] %s\n" "$*"; }
warn() { printf "[WARN] %s\n" "$*" >&2; }
fail() { printf "[FAIL] %s\n" "$*" >&2; }

detect_pm() {
  if command -v apt-get >/dev/null 2>&1; then PM=apt
  elif command -v dnf >/dev/null 2>&1; then PM=dnf
  elif command -v zypper >/dev/null 2>&1; then PM=zypper
  else fail "Unsupported distro: need apt, dnf or zypper"; exit 1; fi
  ok "Package manager: $PM"
}

health_checks() {
  echo "== Health: disk usage >80% (excluding tmpfs/devtmpfs) =="
  if ! df -hPT -x tmpfs -x devtmpfs | awk '$7 ~ "^/" && ($6+0) > 80 { print; found=1 } END{ exit !found }'; then
    ok "Disks OK"
  else
    warn "High disk usage detected"
  fi

  echo "== Health: failed systemd units =="
  if ! systemctl --failed --no-legend | tee /dev/stderr | grep -q .; then
    ok "No failed units"
  else
    warn "Investigate failed units above"
  fi

  echo "== Health: load vs CPU cores =="
  read one five fifteen _ < /proc/loadavg
  cores=$(nproc)
  awk -v l="$one" -v c="$cores" 'BEGIN{ if (l>c){ exit 0 } else { exit 1 }}' \
    && warn "1-min load ($one) exceeds core count ($cores)" || ok "Load within capacity"

  echo "== Health: memory pressure >90% =="
  free -m | awk '/Mem:/ { pct=($3/$2*100); if (pct>90){ print "Memory high:", pct"%"; exit 0 } else { exit 1 } }' \
    && warn "Memory is above 90%" || ok "Memory OK"

  echo "== Health: time sync =="
  tsync=$(timedatectl show -p NTPSynchronized --value 2>/dev/null || echo "unknown")
  if [ "$tsync" = "yes" ]; then ok "NTP synchronized"
  else warn "NTP not synchronized (check chrony/ntpd/systemd-timesyncd)"; fi

  echo "== Health: SMART overall status =="
  found_bad=0
  for d in /dev/sd? /dev/nvme?n1; do
    [ -e "$d" ] || continue
    if sudo smartctl -H "$d" 2>/dev/null | awk '/overall-health/ && $NF!="PASSED" {exit 0} END{exit 1}'; then
      warn "SMART issue on $d"; found_bad=1
    fi
  done
  [ "$found_bad" -eq 0 ] && ok "SMART looks good" || true
}

compliance_scan() {
  echo "== Compliance: OpenSCAP (best-effort) =="
  if command -v oscap >/dev/null 2>&1; then
    SSG_DS=$(sudo find /usr/share/xml /usr/share/openscap -type f -name "ssg-*-ds.xml" 2>/dev/null | head -n1 || true)
    if [ -n "${SSG_DS:-}" ]; then
      echo "Using content: $SSG_DS"
      echo "Available profiles (subset):"
      oscap info "$SSG_DS" | awk '/Profile id/ && NR<=10{print} END{if (NR>10) print "..."}'
      # You should pick a profile that matches your distro, e.g., ssg-ubuntu2204-ds.xml + cis profile
      PROFILE="${PROFILE:-$(oscap info "$SSG_DS" | awk -F: '/Profile id/{print $2; exit}' | xargs)}"
      if [ -n "$PROFILE" ]; then
        echo "Running profile: $PROFILE"
        sudo oscap xccdf eval --profile "$PROFILE" --report mcp-oscap-report.html "$SSG_DS" || true
        ok "OpenSCAP report: mcp-oscap-report.html"
      else
        warn "No profile auto-detected; run 'oscap info $SSG_DS' and set PROFILE=..."
      fi
    else
      warn "No SSG data stream found; ensure scap-security-guide is installed"
    fi
  else
    warn "oscap not found; skipping OpenSCAP"
  fi

  echo "== Compliance: Lynis quick audit =="
  if command -v lynis >/dev/null 2>&1; then
    sudo lynis audit system --quiet --report-file mcp-lynis-report.dat || true
    ok "Lynis report: mcp-lynis-report.dat"
  else
    warn "lynis not found; skipping Lynis"
  fi

  echo "== Compliance: auditd status =="
  systemctl is-active --quiet auditd && ok "auditd active" || warn "auditd not active"
}

list_patches() {
  echo "== Patching: list available updates =="
  case "$PM" in
    apt)
      sudo apt-get update -qq
      echo "-- All upgradable packages --"
      apt list --upgradable 2>/dev/null | tail -n +2 || true
      echo "-- Likely security updates (heuristic) --"
      apt list --upgradable 2>/dev/null | grep -Ei 'security|debian-security|ubuntu-security' || true
      ;;
    dnf)
      sudo dnf -q check-update || true
      echo "-- Security advisories --"
      dnf updateinfo list security all || true
      echo "-- All updates --"
      dnf check-update || true
      ;;
    zypper)
      sudo zypper -q refresh
      echo "-- All patches --"
      zypper -q list-patches || true
      echo "-- Security patches --"
      zypper -q list-patches -g security || true
      ;;
  esac
}

maybe_patch() {
  # Set APPLY=1 to enable unattended patching; defaults to dry-run
  [ "${APPLY:-0}" -eq 1 ] || { warn "Dry-run mode; set APPLY=1 to patch"; return; }
  echo "== Applying updates (APPLY=1) =="
  case "$PM" in
    apt) sudo DEBIAN_FRONTEND=noninteractive apt-get -y upgrade ;;
    dnf) sudo dnf -y upgrade --security || sudo dnf -y upgrade ;;
    zypper) sudo zypper -n patch ;;
  esac
  ok "Patching complete (reboot may be required)"
}

main() {
  detect_pm
  health_checks
  compliance_scan
  list_patches
  maybe_patch
}

main "$@"

Make it executable:

chmod +x mcp-checklist.sh

Run it:

./mcp-checklist.sh
  • Set PROFILE= to pick a specific OpenSCAP profile.

  • Set APPLY=1 to allow the script to apply updates.


Step 2 — Standardize fast health signals

The health_checks() function intentionally focuses on issues that create outages:

  • Disks >80% full on real mounts

  • Failed systemd units (services that matter)

  • Load > core count (a red flag, not an absolute rule)

  • Memory pressure >90%

  • Time not synchronized (breaks TLS, logs, Kerberos, etc.)

  • SMART failing drives

Tweak thresholds to match your environment and export results as JSON if you prefer:

./mcp-checklist.sh | tee "mcp-$(hostname)-$(date +%F).log"

Step 3 — Get a defensible compliance posture

  • OpenSCAP gives you machine-readable checks and an HTML report you can hand to auditors. Use scap-security-guide content that matches your OS version. List available profiles:
oscap info /usr/share/xml/scap/ssg/content/*-ds.xml

Pick a profile (e.g., CIS, RHEL STIG, Ubuntu CIS) and run:

sudo oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_cis_level1_server --report oscap.html /path/to/ssg-<distro>-ds.xml
  • Lynis is great for quick hardening advice:
sudo lynis audit system --report-file lynis.dat

Use both: OpenSCAP for formal compliance, Lynis for pragmatic hygiene.


Step 4 — Treat patching as a routine, not an event

List and apply updates in a controlled way. The script shows:

  • apt: all upgrades and a best-effort “security” filter (based on repo naming)

  • dnf: security advisories via updateinfo

  • zypper: security patches via -g security

To apply safely on maintenance windows:

APPLY=1 ./mcp-checklist.sh

Pair with Livepatch/Ksplice/KGraft if available, and reboot when kernels or glibc change.


Step 5 — Automate and scale

  • Cron:
echo "15 2 * * 1 root /opt/mcp/mcp-checklist.sh > /var/log/mcp-weekly.log 2>&1" | sudo tee /etc/cron.d/mcp-weekly
  • systemd timer (more robust):
# /etc/systemd/system/mcp.service
[Unit]
Description=MCP Checklist
[Service]
Type=oneshot
ExecStart=/opt/mcp/mcp-checklist.sh
StandardOutput=append:/var/log/mcp.log
StandardError=inherit

# /etc/systemd/system/mcp.timer
[Unit]
Description=Run MCP weekly
[Timer]
OnCalendar=Mon 02:15
Persistent=true
[Install]
WantedBy=timers.target

Enable:

sudo systemctl daemon-reload
sudo systemctl enable --now mcp.timer
  • Fleet-friendly: run over SSH in parallel (Ansible, pssh, or a tiny loop) and collect artifacts:
for h in $(cat hosts.txt); do
  ssh -o BatchMode=yes "$h" 'bash -s' < mcp-checklist.sh > "reports/${h}-$(date +%F).log" 2>&1 &
done
wait

Real-world example

A team running this weekly across ~120 mixed-distro servers caught:

  • Two disks degrading via SMART before they failed

  • Drifted NTP on three nodes causing TLS handshake failures

  • 40+ outstanding security advisories on a legacy app tier

They remediated in the same week, documented via OpenSCAP/Lynis reports, and baked the checklist into a systemd timer. Outages related to these issues dropped to zero.


Conclusion and next steps

MCP checklists make the important things easy to do every time: maintain health, prove compliance, and patch routinely. You now have:

  • A portable Bash script you can run today

  • Clear install commands for apt, dnf, and zypper

  • A pattern you can extend with org-specific checks

Your move: 1) Install the prerequisites for your distro (see above). 2) Drop mcp-checklist.sh in /opt/mcp, commit it to git, and run it. 3) Pick an OpenSCAP profile and schedule it weekly with a systemd timer. 4) Iterate—add service-specific checks, export JSON, ship logs to your SIEM.

Small, consistent steps beat big, sporadic efforts. Make MCP your new default.