mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 03:20:11 +00:00
fix: improve turnkey temperature monitoring for standalone nodes
- Fix script input handling to work with standard curl | bash pattern by prioritizing /dev/tty - Add Raspberry Pi temperature sensor support (cpu_thermal chip and generic temp sensors) - Add comprehensive documentation for turnkey standalone node setup - Fix printf formatting error in setup script
This commit is contained in:
parent
669d7dc05c
commit
de3bb47930
3 changed files with 64 additions and 2 deletions
|
|
@ -158,6 +158,40 @@ The auto-setup script (Settings → Nodes → Setup Script) will prompt you to c
|
|||
|
||||
If the node is part of a Proxmox cluster, the script will now detect the other members and offer to configure the same SSH/lm-sensors setup on each of them automatically—confirm when prompted to roll it out cluster-wide.
|
||||
|
||||
### Turnkey Setup for Standalone Nodes (v4.25.0+)
|
||||
|
||||
**For standalone nodes** (not in a Proxmox cluster) running **containerized Pulse**, the setup script now automatically configures temperature monitoring with zero manual steps:
|
||||
|
||||
1. The script detects the node is standalone (not in a cluster)
|
||||
2. Automatically fetches the temperature proxy's SSH public key from your Pulse server via `/api/system/proxy-public-key`
|
||||
3. Installs it with forced commands (`command="sensors -j"`) automatically
|
||||
4. Temperature monitoring "just works" - no manual SSH key management needed!
|
||||
|
||||
**Example output:**
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Standalone Node Temperature Setup
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Detected: This is a standalone node (not in a Proxmox cluster)
|
||||
|
||||
Fetching temperature proxy public key...
|
||||
✓ Retrieved proxy public key
|
||||
✓ Temperature proxy key installed (restricted to sensors -j)
|
||||
|
||||
✓ Standalone node temperature monitoring configured
|
||||
The Pulse temperature proxy can now collect temperature data
|
||||
from this node using secure SSH with forced commands.
|
||||
```
|
||||
|
||||
**Security:**
|
||||
- Public keys are safe to expose (it's in the name!)
|
||||
- Forced commands restrict the key to only `command="sensors -j"`
|
||||
- All other SSH features disabled (no-port-forwarding, no-pty, etc.)
|
||||
- Works exactly like cluster setups, but fully automated
|
||||
|
||||
**Note:** This only works for containerized Pulse deployments where the temperature proxy is running. For native (non-containerized) installs, you'll still need to provide your Pulse server's public key manually as described in step 3 above.
|
||||
|
||||
## Setup (Manual)
|
||||
|
||||
If you skipped SSH setup during auto-setup, you can configure it manually:
|
||||
|
|
|
|||
|
|
@ -3847,8 +3847,11 @@ if [ "$SSH_ALREADY_CONFIGURED" = true ]; then
|
|||
if [ -t 0 ]; then
|
||||
read -p "> " -n 1 -r SSH_ACTION
|
||||
else
|
||||
# When stdin is not a terminal (e.g., curl | bash), try /dev/tty first, then stdin for piped input
|
||||
if read -p "> " -n 1 -r SSH_ACTION </dev/tty 2>/dev/null; then
|
||||
:
|
||||
elif read -t 2 -n 1 -r SSH_ACTION 2>/dev/null && [ -n "$SSH_ACTION" ]; then
|
||||
echo "$SSH_ACTION"
|
||||
else
|
||||
echo "(No terminal available - keeping existing configuration)"
|
||||
SSH_ACTION="k"
|
||||
|
|
@ -3909,8 +3912,11 @@ else
|
|||
if [ -t 0 ]; then
|
||||
read -n 1 -r SSH_REPLY
|
||||
else
|
||||
# When stdin is not a terminal (e.g., curl | bash), try /dev/tty first, then stdin for piped input
|
||||
if read -n 1 -r SSH_REPLY </dev/tty 2>/dev/null; then
|
||||
:
|
||||
elif read -t 2 -n 1 -r SSH_REPLY 2>/dev/null && [ -n "$SSH_REPLY" ]; then
|
||||
echo "$SSH_REPLY"
|
||||
else
|
||||
echo "(No terminal available - skipping temperature monitoring)"
|
||||
SSH_REPLY="n"
|
||||
|
|
@ -4247,12 +4253,12 @@ if [ "$AUTO_REG_SUCCESS" != true ]; then
|
|||
else
|
||||
echo " Token Value: [See token output above]"
|
||||
fi
|
||||
echo " Host URL: %s"
|
||||
echo " Host URL: YOUR_PROXMOX_HOST:8006"
|
||||
echo ""
|
||||
fi
|
||||
`, serverName, time.Now().Format("2006-01-02 15:04:05"), pulseIP,
|
||||
tokenName, tokenName, tokenName, tokenName, tokenName, tokenName,
|
||||
authToken, pulseURL, serverHost, tokenName, tokenName, storagePerms, sshPublicKey, pulseURL, pulseURL, pulseURL, pulseURL, authToken, pulseURL, tokenName, serverHost)
|
||||
authToken, pulseURL, serverHost, tokenName, tokenName, storagePerms, sshPublicKey, pulseURL, pulseURL, pulseURL, pulseURL, authToken, pulseURL, pulseURL, tokenName, serverHost)
|
||||
|
||||
} else { // PBS
|
||||
script = fmt.Sprintf(`#!/bin/bash
|
||||
|
|
|
|||
|
|
@ -226,6 +226,8 @@ func (tc *TemperatureCollector) parseSensorsJSON(jsonStr string) (*models.Temper
|
|||
|
||||
// parseCPUTemps extracts CPU temperature data from a sensor chip
|
||||
func (tc *TemperatureCollector) parseCPUTemps(chipMap map[string]interface{}, temp *models.Temperature) {
|
||||
foundPackageTemp := false
|
||||
|
||||
for sensorName, sensorData := range chipMap {
|
||||
sensorMap, ok := sensorData.(map[string]interface{})
|
||||
if !ok {
|
||||
|
|
@ -236,6 +238,7 @@ func (tc *TemperatureCollector) parseCPUTemps(chipMap map[string]interface{}, te
|
|||
if strings.Contains(sensorName, "Package id") || strings.Contains(sensorName, "Tdie") {
|
||||
if tempVal := extractTempInput(sensorMap); !math.IsNaN(tempVal) {
|
||||
temp.CPUPackage = tempVal
|
||||
foundPackageTemp = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,6 +256,25 @@ func (tc *TemperatureCollector) parseCPUTemps(chipMap map[string]interface{}, te
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no package temperature was found (e.g., Raspberry Pi), look for generic temp sensors
|
||||
if !foundPackageTemp {
|
||||
for sensorName, sensorData := range chipMap {
|
||||
sensorMap, ok := sensorData.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Look for generic temperature sensors (e.g., "temp1" on Raspberry Pi)
|
||||
if strings.HasPrefix(sensorName, "temp") || strings.HasPrefix(sensorName, "Temp") {
|
||||
if tempVal := extractTempInput(sensorMap); !math.IsNaN(tempVal) && tempVal > 0 {
|
||||
temp.CPUPackage = tempVal
|
||||
temp.CPUMax = tempVal
|
||||
break // Use the first valid generic temp sensor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parseNVMeTemps extracts NVMe temperature data from a sensor chip
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue