Thanks SimonF. I actually got it to work using a fake sensor directory and pointed Beszel to it. Here's the script if anyone else is interested in it. I have it running on array startup. #!/bin/bash
set -u
set -o pipefail
########################################
# CONFIG
########################################
FAKE_SYS="/mnt/user/appdata/beszel/sys_spoof"
REAL_HWMON="/sys/class/hwmon"
CMD="/usr/sbin/ipmi-sensors"
LOG="/mnt/user/appdata/beszel/ipmi-bridge.log"
INTERVAL=10
LOCK="/tmp/ipmi-beszel.lock"
mkdir -p "$FAKE_SYS/class/hwmon"
########################################
# LOGGING
########################################
exec >> "$LOG" 2>&1
ts() { date "+%Y-%m-%d %H:%M:%S"; }
########################################
# SINGLE INSTANCE LOCK
########################################
if [[ -e "$LOCK" ]]; then
oldpid="$(cat "$LOCK" 2>/dev/null || true)"
if [[ -n "${oldpid:-}" ]] && kill -0 "$oldpid" 2>/dev/null; then
echo "[$(ts)] Bridge already running (pid=$oldpid). Exiting."
exit 0
fi
fi
echo $$ > "$LOCK"
cleanup() {
echo "[$(ts)] IPMI → Beszel bridge stopped"
rm -f "$LOCK"
}
trap cleanup EXIT INT TERM
echo "[$(ts)] IPMI → Beszel bridge started"
ipmi_failed=0
first_run=1
########################################
# MAIN LOOP
########################################
while true; do
########################################
# Link ONLY NVMe sensors
########################################
find "$FAKE_SYS/class/hwmon" -maxdepth 1 -type l -delete 2>/dev/null || true
nvme_count=0
for d in "$REAL_HWMON"/hwmon*; do
[[ -e "$d/name" ]] || continue
name=$(cat "$d/name")
if [[ "$name" == nvme* ]]; then
bn=$(basename "$d")
ln -sfn "$d" "$FAKE_SYS/class/hwmon/$bn"
((nvme_count++))
fi
done
########################################
# Create IPMI hwmon node
########################################
IPMI_HWMON="$FAKE_SYS/class/hwmon/hwmon_ipmi"
mkdir -p "$IPMI_HWMON"
echo "ipmi" > "$IPMI_HWMON/name"
find "$IPMI_HWMON" -maxdepth 1 -type f ! -name "name" -delete 2>/dev/null || true
########################################
# Read IPMI
########################################
output="$($CMD --comma-separated-output --no-header-output --quiet-cache 2>/dev/null || true)"
if [[ -z "$output" ]]; then
if [[ "$ipmi_failed" -eq 0 ]]; then
echo "[$(ts)] WARNING: ipmi-sensors returned no data"
ipmi_failed=1
fi
sleep "$INTERVAL"
continue
fi
if [[ "$ipmi_failed" -eq 1 ]]; then
echo "[$(ts)] IPMI sensors recovered"
ipmi_failed=0
fi
########################################
# Export temps + fans
########################################
t=1
f=1
while IFS=, read -r id name type reading unit event; do
name=$(echo "$name" | sed 's/^"//;s/"$//' | xargs)
type=$(echo "$type" | sed 's/^"//;s/"$//' | xargs)
reading=$(echo "$reading" | sed 's/^"//;s/"$//' | xargs)
[[ -z "$reading" || "$reading" == "N/A" ]] && continue
if [[ "$type" == "Temperature" ]]; then
milli=$(awk -v v="$reading" 'BEGIN{printf "%.0f", v*1000}')
echo "$milli" > "$IPMI_HWMON/temp${t}_input"
echo "$name" > "$IPMI_HWMON/temp${t}_label"
((t++))
continue
fi
if [[ "$type" == "Fan" ]]; then
rpm=$(awk -v v="$reading" 'BEGIN{printf "%.0f", v}')
echo "$rpm" > "$IPMI_HWMON/fan${f}_input"
echo "$name" > "$IPMI_HWMON/fan${f}_label"
((f++))
continue
fi
done <<< "$output"
########################################
# First run info
########################################
if [[ "$first_run" -eq 1 ]]; then
echo "[$(ts)] Exporting: temps=$((t-1)) fans=$((f-1)) nvme=$nvme_count"
echo "[$(ts)] Update interval: ${INTERVAL}s"
first_run=0
fi
chmod -R a+rX "$FAKE_SYS" 2>/dev/null || true
sleep "$INTERVAL"
done