Skip to content

Ubuntu Server Nightly Health Report Discord

Keith Lewis edited this page Jun 1, 2026 · 3 revisions

Support the Channel โ˜•

If you found this guide helpful and are feeling extra appreciative, consider supporting the channel:

๐ŸŒ™ Nightly Ubuntu Server Health Report for Discord

Image below of the report!

This guide walks you through setting up an automated Bash script that monitors the health of your Ubuntu server and sends a daily summary directly to a Discord channel via webhooks. ๐Ÿ“ˆ

This script is particularly tailored for setups using software RAID (mdadm), Btrfs/Ext4 file systems, and NVMe drives, providing a comprehensive snapshot of your system's health, thermals, and security status. ๐Ÿ–ฅ๏ธ๐Ÿ›ก๏ธ

๐Ÿงฐ Prerequisites

Before setting up the script, ensure your server has the necessary command-line tools installed. You can install any missing packages using apt:

sudo apt update
sudo apt install jq curl lm-sensors mdadm btrfs-progs

(Note: If you haven't used lm-sensors before, you may need to run sudo sensors-detect to allow your system to read motherboard and CPU temperatures.) ๐ŸŒก๏ธ

๐Ÿ”— Step 1: Create a Discord Webhook

To send messages to Discord, you need a Webhook URL for your target channel.

  1. In Discord, go to the channel where you want the reports to appear. ๐Ÿ’ฌ
  2. Click the Edit Channel (gear icon) > Integrations > Webhooks > New Webhook. โš™๏ธ
  3. Name the webhook (e.g., "NAS Monitor") and copy the Webhook URL. ๐Ÿ“‹
  4. ๐Ÿšจ Important: The URL format looks like this: [https://discord.com/api/webhooks/CHANNEL_ID/TOKEN](https://discord.com/api/webhooks/CHANNEL_ID/TOKEN). When pasting this into the script configuration below, make sure you are swapping in your actual CHANNEL_ID and TOKEN where it says redacted/redacted.

๐Ÿ“œ Step 2: The Script

Create a new file on your server, for example, /usr/local/bin/discord-health-report.sh:

sudo nano /usr/local/bin/discord-health-report.sh

Paste the following code into the file:

#!/bin/bash

# --- CONFIGURATION ---
WEBHOOK_URL="https://discord.com/api/webhooks/redacted/redacted"
SERVER_NAME=$(hostname)
IP_ADDR=$(hostname -I | awk '{print $1}')
MAIN_POOL="/mnt/main_storage"
NVME_POOL="/mnt/nvme_storage"

# --- DATA GATHERING ---

# 1. System Info & Performance
UPTIME=$(uptime -p)
LOAD=$(uptime | awk -F'load average:' '{ print $2 }')
RAM_USAGE=$(free -h | awk '/^Mem:/ {print $3 " / " $2}')
STORAGE_DETAILS=$(df -h | grep "^/dev/" | awk '{print "โ€ข " $6 ": " $3 " / " $2 " (" $5 ")"}')

# 2. Thermal Stats (CPU, Mobo, Drives)
TEMP_CPU=$(sensors | grep "Package id 0:" | awk '{print $4}')
TEMP_MOBO=$(sensors | grep -iE -m 1 "(board|acpitz|composite)" | awk '{print $2}')
TEMP_DRIVES=$(sensors | grep -E "^(sd[a-z]|nvme|Composite)" | awk '{print "โ€ข " $1 " " $2 " " $3}')
THERMAL_BLOCK="**CPU:** ${TEMP_CPU:-N/A}\n**Mobo:** ${TEMP_MOBO:-N/A}\n**Drives:**\n$TEMP_DRIVES"

# 3. METADATA SYNC: Main-Storage (RAID 5)
# Monitoring the "Reddit Problem": Comparing Event counts on sda, sdc, sdd
EV_A=$(sudo mdadm --examine /dev/sda | grep -i "Events" | awk '{print $3}')
EV_C=$(sudo mdadm --examine /dev/sdc | grep -i "Events" | awk '{print $3}')
EV_D=$(sudo mdadm --examine /dev/sdd | grep -i "Events" | awk '{print $3}')

if [ "$EV_A" -eq "$EV_C" ] && [ "$EV_C" -eq "$EV_D" ]; then
    META_MAIN="โœ… Sync OK ($EV_A)"
    META_COLOR="GREEN"
else
    META_MAIN="โš ๏ธ MISMATCH: A:$EV_A C:$EV_C D:$EV_D"
    META_COLOR="RED"
fi

# 4. RAID 0 STATUS: NVME-Storage
# Since RAID 0 has no "Events", we just verify both drives are 'active sync'
NVME_CHECK=$(sudo mdadm --detail /dev/md/NVME-Storage | grep "active sync" | wc -l)
if [ "$NVME_CHECK" -eq "2" ]; then
    META_NVME="โœ… Both Drives Active"
else
    META_NVME="โš ๏ธ DRIVE MISSING (RAID 0 CRITICAL)"
    META_COLOR="RED"
fi

# 5. FILESYSTEM HEALTH
# Btrfs Check for Main-Storage (Checksum/IO errors)
BTRFS_ERR=$(sudo btrfs device stats "$MAIN_POOL" | awk '{sum+=$2} END {print sum}')
if [ "$BTRFS_ERR" -eq "0" ]; then BTRFS_S="โœ… Clean"; else BTRFS_S="โš ๏ธ $BTRFS_ERR Errors"; META_COLOR="RED"; fi

# Ext4 Check for NVMe-Storage
if tune2fs -l /dev/md/NVME-Storage | grep -q "Filesystem state:.*clean"; then FS_NVME="โœ… Clean"; else FS_NVME="โš ๏ธ Error"; META_COLOR="RED"; fi

# 6. GENERAL RAID STATUS
RAID_INFO=$(awk '/^md/ {printf "โ€ข %s: %s (%s)\n", $1, $3, $4}' /proc/mdstat)
if grep -q "blocks.*_.*]" /proc/mdstat; then RAID_H="โš ๏ธ DEGRADED"; META_COLOR="RED"; else RAID_H="โœ… Healthy"; fi

# 7. LOGINS & UPDATES
UPDATE_COUNT=$(apt-get -s upgrade | grep -P '^\d+ upgraded' | cut -d" " -f1)
REBOOT_S=$( [ -f /var/run/reboot-required ] && echo "โš ๏ธ REBOOT REQUIRED" || echo "No Reboot Required" )
RECENT_LOGINS=$(last -a --since yesterday | grep -vE "(wtmp|reboot|^$)" | head -n 5 | awk '{print $1 " (" $(NF) ")"}')

# --- FINAL PAYLOAD ---
[ "$META_COLOR" == "RED" ] && FINAL_COLOR=16711680 || FINAL_COLOR=5814783

JSON_PAYLOAD=$(jq -n \
    --arg title "Daily Server Report: $SERVER_NAME" --arg color "$FINAL_COLOR" \
    --arg raidh "$RAID_H" --arg btrfs "$BTRFS_S" --arg meta_m "$META_MAIN" --arg meta_n "$META_NVME" \
    --arg raidinfo "$RAID_INFO" --arg storage "$STORAGE_DETAILS" --arg thermals "$THERMAL_BLOCK" \
    --arg ram "$RAM_USAGE" --arg uptime "$UPTIME" --arg load "$LOAD" \
    --arg updates "$UPDATE_COUNT" --arg reboot "$REBOOT_S" --arg logins "$RECENT_LOGINS" \
    '{
        username: "NAS Monitor",
        embeds: [{
            title: $title, color: ($color | tonumber),
            fields: [
                {name: "๐Ÿšจ RAID Health", value: $raidh, inline: true},
                {name: "๐Ÿ›ก๏ธ Btrfs (Main)", value: $btrfs, inline: true},
                {name: "๐Ÿ”— Main Sync", value: $meta_m, inline: true},
                {name: "โšก NVMe Status", value: $meta_n, inline: true},
                {name: "๐Ÿ’ฝ Array Details", value: ("```\n" + $raidinfo + "\n```"), inline: false},
                {name: "๐Ÿ’พ Storage", value: ("```\n" + $storage + "\n```"), inline: false},
                {name: "๐ŸŒก๏ธ Thermals", value: $thermals, inline: true},
                {name: "๐Ÿง  RAM", value: $ram, inline: true},
                {name: "โณ Uptime", value: $uptime, inline: true},
                {name: "โš™๏ธ Load", value: $load, inline: true},
                {name: "๐Ÿ“ฆ Updates", value: $updates, inline: true},
                {name: "๐Ÿ›ก๏ธ Security", value: $reboot, inline: true},
                {name: "๐Ÿ”‘ Logins", value: ("```\n" + $logins + "\n```"), inline: false}
            ],
            footer: {text: ("Report generated at " + (now | strftime("%Y-%m-%d %H:%M:%S")))}
        }]
    }')

curl -H "Content-Type: application/json" -d "$JSON_PAYLOAD" "$WEBHOOK_URL"

๐Ÿ› ๏ธ Step 3: Customization & Permissions

Before running the script, review the following hardware-specific variables and adjust them to match your setup:

  • MAIN_POOL and NVME_POOL variables in the configuration block. ๐Ÿ—„๏ธ
  • The /dev/sda, sdc, sdd mappings in Section 3 (Metadata Sync). ๐Ÿ”„
  • The /dev/md/NVME-Storage paths in Sections 4 and 5. โšก

Once configured, make the script executable:

sudo chmod +x /usr/local/bin/discord-health-report.sh

โฑ๏ธ Step 4: Automate with Cron

To have this report sent nightly, add it to your root crontab. ๐Ÿ“…

  1. Open the crontab editor:
    sudo crontab -e
  2. Add a line at the bottom to schedule the script. For example, to run it every night at 11:30 PM, use:
    30 23 * * * /usr/local/bin/discord-health-report.sh
  3. Save and exit. Your server will now automatically report its status to your Discord channel every night! ๐ŸŽ‰

Screenshot_20260321_113621_Discord

Clone this wiki locally