- Changed temperature monitoring menu from [K/r/s] to [1/2/3]
- Now all multi-choice menus use numbers consistently
- Main menu: [1/2/3]
- Temperature menu: [1/2/3] (was [K/r/s])
- Yes/no questions still use y/n (standard convention)
- 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
Implements automatic temperature monitoring setup for standalone
Proxmox/Pimox nodes without manual SSH key configuration.
Changes:
- Add /api/system/proxy-public-key endpoint to expose proxy's SSH public key
- Setup script now detects standalone nodes (non-cluster)
- Auto-fetches and installs proxy SSH key with forced commands
- Add Raspberry Pi temperature support via cpu_thermal and /sys/class/thermal
- Enhance setup script with better error handling for lm-sensors installation
- Add RPi detection to skip lm-sensors and use native thermal interface
Security:
- Public key endpoint is safe (public keys are meant to be public)
- All installed keys use forced command="sensors -j" with full restrictions
- No shell access, port forwarding, or other SSH features enabled
Fixes two issues with the sensor proxy installation:
1. Local node IP detection now uses exact matching instead of substring matching to avoid false negatives
2. Removes duplicate output filtering in the setup script wrapper
These changes ensure that the proxy SSH key is correctly configured on the local node during cluster installations.
Implements automated cleanup workflow when nodes are deleted from Pulse, removing all monitoring footprint from the host. Changes include a new RPC handler in the sensor proxy for cleanup requests, enhanced node deletion modal with detailed cleanup explanations, and improved SSH key management with proper tagging for atomic updates.
The setup script was restarting the container but never running the
pct set command to configure the bind mount. This meant the socket
was never accessible inside the container.
Now runs: pct set <ctid> -mp0 /run/pulse-sensor-proxy,mp=/mnt/pulse-proxy
before restarting the container to ensure the mount is configured.
Improvements to pulse-sensor-proxy:
- Fix cluster discovery to use pvecm status for IP addresses instead of node names
- Add standalone node support for non-clustered Proxmox hosts
- Enhanced SSH key push with detailed logging, success/failure tracking, and error reporting
- Add --pulse-server flag to installer for custom Pulse URLs
- Configure www-data group membership for Proxmox IPC access
UI and API cleanup:
- Remove unused "Ensure cluster keys" button from Settings
- Remove /api/diagnostics/temperature-proxy/ensure-cluster-keys endpoint
- Remove EnsureClusterKeys method from tempproxy client
The setup script already handles SSH key distribution during initial configuration,
making the manual refresh button redundant.
- Add comprehensive test coverage for alerts package with 285+ new tests
- Implement ThresholdsTable component with metric thresholds display
- Enhance Alerts page UI with improved layout and metric filtering
- Add frontend component tests for Alerts page and ThresholdsTable
- Set up Vitest testing infrastructure for SolidJS components
- Improve config persistence with better validation
- Expand discovery tests with 333+ test cases
- Update API, configuration, and Docker monitoring documentation
Fixed a fmt.Sprintf argument alignment issue in the PVE setup script that
caused a bash syntax error at the end of script execution. The error
manifested as "syntax error near unexpected token EXTRA" followed by the
serverHost URL.
Root cause: 23 arguments were provided for 22 %s placeholders. An extra
tokenName at position 15 pushed all subsequent arguments off by one,
leaving the final serverHost with no placeholder to fill.
Fix: Removed duplicate tokenName at position 15 and ensured serverHost
is correctly positioned at position 22 for the "Host URL" placeholder.
The REGISTER_JSON template at line 3311 was getting storagePerms instead of tokenName
for the tokenId field, causing 'Missing required fields' errors during auto-registration.
Added tokenName parameter before storagePerms to shift all subsequent parameters.
Fixes #<issue-number>
Fixes two issues found in v4.24.0-rc.1:
1. Setup script menu now uses numbered options [1/2/3] instead of
[I/r/c] for better UX (maintains backward compatibility)
2. Temperature verification endpoint now requires authentication
(wraps HandleVerifyTemperatureSSH with RequireAuth middleware)
These fixes address user feedback and prepare for v4.24.0-rc.2.
Addresses user concern about technical debt: detection code exists only
to handle migration from SSH-in-container to proxy architecture, not to
serve functional purpose of the application.
Changes:
- Add PULSE_LEGACY_DETECTION env var to disable detection without redeployment
- Add explicit removal criteria: v5.0 or <1% detection rate for 30+ days
- Mark all detection code with "MIGRATION SCAFFOLDING" warnings
- Create MIGRATION_SCAFFOLDING.md to track temporary code across codebase
- Document removal instructions for when migration period ends
Backend:
- internal/api/router.go: detectLegacySSH() checks env var and has removal plan
- internal/api/types.go: HealthResponse fields documented as temporary
Frontend:
- src/components/LegacySSHBanner.tsx: Component marked with removal criteria
- src/App.tsx: Banner integration (will be removed with component)
This approach balances user safety during migration (auto-detection catches
rushed admins who skip changelogs) with long-term code cleanliness (explicit
removal plan prevents indefinite technical debt).
Added automatic detection to alert users when they're using the old
SSH-in-container method for temperature monitoring so they can upgrade
to the secure proxy architecture.
**Detection Logic:**
- Checks if Pulse is running in a container (Docker or LXC)
- Checks if SSH keys exist in data directory (/etc/pulse/.ssh)
- Checks if pulse-sensor-proxy socket is NOT available
- Sets legacySSHDetected and recommendProxyUpgrade flags in health endpoint
**API Changes:**
- Added fields to HealthResponse:
- legacySSHDetected: true when old method detected
- recommendProxyUpgrade: true when upgrade is recommended
- proxyInstallScriptAvailable: always true
**Use Case:**
Users who set up temperature monitoring before the proxy feature
won't know they should upgrade. This detection allows the frontend
to show a banner prompting them to re-run the setup script to
migrate to the secure proxy architecture.
**Frontend Integration (to be added):**
Frontend can poll /api/health and show a dismissible banner similar
to UpdateBanner when legacySSHDetected is true, with a button to
view the setup script.
Addresses #123
Codex caught an edge case in the authorized_keys removal logic:
**Problem:**
When authorized_keys contains ONLY pulse-managed keys, `grep -vF` returns
exit code 1 (no lines matched the inverse filter). The previous code only
executed the rewrite on exit 0, leaving managed keys in place when they
should have been removed.
**Solution:**
- Capture grep exit code explicitly
- Treat both exit 0 (lines remain) and exit 1 (all removed) as success
- Only treat exit codes > 1 as actual errors
- Properly handles the "remove all keys" scenario
This ensures complete removal works even when the file contains nothing
but Pulse-managed entries.
Addresses #123
Fixed three remaining issues from Codex's final review:
**1. nullglob State Management (line 3124)**
- Replaced shopt -s/u nullglob with compgen -G check
- Prevents changing global shell behavior that could affect later globs
- More explicit and safer pattern matching
**2. authorized_keys Permission Preservation (lines 3116-3117)**
- Now uses chmod/chown --reference to preserve original ownership/perms
- Falls back gracefully if --reference not available
- Proper cleanup on mv failure to prevent temp file leaks
- Aborts atomically if operations fail, leaving original untouched
**3. Multi-Address Container Detection (lines 3750-3761)**
- Iterates over ALL IPs from hostname -I, not just first one
- Handles dual-stack (IPv4 + IPv6) and multi-IP containers
- Uses break 2 to exit both loops when match found
- Prevents false negatives when Pulse IP is not the first address
All operations now handle edge cases properly: non-root accounts,
dual-stack networking, empty directories, and partial failures.
Addresses #123
Applied Codex's security and reliability recommendations:
**SSH Key Safety:**
- Added "pulse-managed-key" comment marker to all SSH keys
- Removal now targets only marked keys (prevents deleting operator keys)
- Uses atomic file replacement via mktemp for authorized_keys edits
**Idempotency Improvements:**
- LXC config glob now uses nullglob to handle empty directories
- pveum token removal handles missing users gracefully (|| printf '')
- All systemctl operations wrapped with || true for non-systemd hosts
- sed operations in loops protected with || true
**Container Detection:**
- Validates container is running before IP check (pct status)
- Confirms container exists with pct config before proceeding
- Uses printf '' instead of || true for command substitution
- Handles IPv6 and multi-IP scenarios more reliably
**Network Operations:**
- curl now uses --fail --show-error --silent --location
- Error messages visible to users instead of silenced
- Better diagnostics when download fails
**Migration Safety:**
- Verifies pulse-sensor-proxy service is active before key removal
- Fallback check for binary existence if systemd unavailable
- Preserves legacy SSH keys if proxy not confirmed healthy
- Clear messaging about deferred cleanup
All cleanup operations are now fully idempotent and safe for
repeated execution, even on partially-configured hosts.
Addresses #123