Commit Graph

245 Commits

Author SHA1 Message Date
rcourtman 1419179046 fix: Update test version fallback and fix lint warnings #64 2025-10-13 15:50:23 +00:00
rcourtman 6c88968d91 fix: Address Codex feedback on legacy SSH detection before release
Codex identified critical issues preventing release. All issues resolved:

1. FIXED: LXC container detection reliability
   - Added 4 detection methods (was 2):
     * Method 1: /.dockerenv (Docker)
     * Method 2: /proc/1/cgroup with more patterns (Docker/LXC)
     * Method 3: /run/systemd/container (systemd containers)
     * Method 4: /proc/1/environ container markers
   - Tested on LXC container (debian-go): detection confirmed working

2. FIXED: False positives from proxy outages
   - Now distinguishes "not configured" vs "temporarily down"
   - Checks if /usr/local/bin/pulse-sensor-proxy exists
   - If binary exists but socket missing = transient issue (no banner)
   - If binary missing and SSH keys present = legacy setup (show banner)

3. FIXED: Banner guidance insufficient
   - Added "Go to Nodes →" button that navigates to /settings/nodes
   - Users now have direct path to fix the issue
   - Banner message remains clear and concise

4. ADDED: Telemetry for removal criteria tracking
   - Backend logs: "Legacy SSH configuration detected" (WARN level)
   - Frontend logs: Banner shown/dismissed events to console
   - Enables data-driven removal per criteria: <1% for 30+ days
   - Log format: detection_type=legacy_ssh_migration for easy filtering

Testing:
- Created fake SSH key in /etc/pulse/.ssh/ on LXC container
- Verified detection triggered (legacySSHDetected: true)
- Verified telemetry logged: "Legacy SSH configuration detected"
- Removed fake key, verified detection cleared (null values)
- Container detection working via /run/systemd/container

Ready for release per Codex review.
2025-10-13 15:06:40 +00:00
rcourtman 92387022ec refactor: Mark legacy SSH detection as temporary migration scaffolding
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).
2025-10-13 14:54:52 +00:00
rcourtman 1bd1428d8a feat: Add detection for legacy SSH temperature monitoring
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
2025-10-13 14:40:03 +00:00
rcourtman 0a5b1b6c1d fix: Handle authorized_keys removal when all keys are managed
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
2025-10-13 14:35:06 +00:00
rcourtman 2eb9361c73 fix: Address final Codex review findings
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
2025-10-13 14:32:38 +00:00
rcourtman f246391271 fix: Improve setup script robustness and safety (Codex review)
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
2025-10-13 14:19:17 +00:00
rcourtman 8b4ce52498 feat: Add install/remove menu to setup script
Added a main menu at the beginning of the PVE setup script that gives users three options:

[I]nstall - Continue with normal setup (default)
[R]emove All - Complete uninstall of all Pulse components
[C]ancel - Exit without changes

The removal option comprehensively cleans up:
- pulse-sensor-proxy service, binary, and systemd unit
- pulse-sensor-proxy system user and data directories
- All SSH keys from authorized_keys (legacy and forced-command variants)
- LXC bind mounts from all container configs
- Pulse monitoring API tokens, user, and custom roles

This addresses user request for a clean removal path for everything
Pulse has installed on the host, including legacy components from
previous versions.
2025-10-13 13:59:20 +00:00
rcourtman 7fa01cafa6 polish: Clean up setup script output for professional presentation
Made the setup and installation output more concise and reassuring for users. Less verbosity, clearer messaging.

**Setup script improvements:**
- Changed "Container Detection" → "Enhanced Security"
- Simplified prompts: "Enable secure proxy? [Y/n]"
- Cleaned up success messages: "✓ Secure proxy architecture enabled"
- Removed verbose status messages (node-by-node cleanup output)
- Only show essential information users need to see

**install-sensor-proxy.sh improvements:**
- Added --quiet flag to suppress verbose output
- In quiet mode, only shows: "✓ pulse-sensor-proxy installed and running"
- Full output still available when run manually
- Removed redundant "Installation complete!" banners
- Cleaner legacy key cleanup messaging

**Result:**
Users see a clean, professional installation flow that builds confidence. Technical details are hidden unless needed. Messages are clear and reassuring rather than verbose.
2025-10-13 13:51:17 +00:00
rcourtman 71c5ee6e8a feat: Auto-cleanup legacy SSH keys when migrating to proxy
When pulse-sensor-proxy is installed, automatically remove old SSH keys that were stored in the container for security.

Changes:

**install-sensor-proxy.sh:**
- Checks container for SSH private keys (id_rsa, id_ed25519, etc.)
- Removes any found keys from container
- Warns user that legacy keys were cleaned up
- Explains proxy now handles SSH

**Setup script (config_handlers.go):**
- After successful proxy install, removes old SSH keys from all cluster nodes
- Cleans up authorized_keys entries that match the old container-based key
- Keeps only proxy-managed keys (pulse-sensor-proxy comment)

This provides a clean migration path from the old direct-SSH method to the secure proxy architecture. Users upgrading from pre-v4.24 versions get automatic cleanup of insecure container-stored keys.
2025-10-13 13:47:19 +00:00
rcourtman b130c02cfb feat: Auto-install pulse-sensor-proxy during setup for containerized deployments
The setup script now automatically detects when Pulse is running in an LXC container and offers to install pulse-sensor-proxy on the host for enhanced security.

What happens:
1. After temperature monitoring is configured
2. Script detects Pulse IP and finds matching container
3. Prompts: "Install pulse-sensor-proxy for container X? [Y/n]"
4. Downloads and runs install-sensor-proxy.sh automatically
5. Falls back gracefully if proxy install fails

Benefits:
- One-command setup for users (no manual proxy installation)
- SSH keys stay on host (not in container)
- Containerized Pulse gets the secure architecture automatically
- Native installs unaffected (still use direct SSH)

This solves the UX problem where users had to manually run install-sensor-proxy.sh as a separate step.
2025-10-13 13:41:01 +00:00
rcourtman ce499245a0 refactor: Rename pulse-temp-proxy to pulse-sensor-proxy
The name "temp-proxy" implied a temporary or incomplete implementation. The new name better reflects its purpose as a secure sensor data bridge for containerized Pulse deployments.

Changes:
- Renamed cmd/pulse-temp-proxy/ to cmd/pulse-sensor-proxy/
- Updated all path constants and binary references
- Renamed environment variables: PULSE_TEMP_PROXY_* to PULSE_SENSOR_PROXY_*
- Updated systemd service and service account name
- Updated installation, rotation, and build scripts
- Renamed hardening documentation
- Maintained backward compatibility for key removal during upgrades
2025-10-13 13:17:05 +00:00
rcourtman 7917461b37 docs: Update temperature monitoring security notice for proxy architecture
Replaced outdated security warnings with accurate information about
the pulse-temp-proxy architecture:

- Removed scary 'legacy feature' and 'compromised container' warnings
- Explains secure proxy architecture for containerized deployments
- Notes that SSH keys are stored on Proxmox host (not in container)
- Clarifies container compromise does not expose credentials
- Includes information for both containerized and native installs
- More factual and less alarmist tone

The old message implied temperature monitoring was insecure for
containers, which is no longer true with pulse-temp-proxy.

Related to #528
2025-10-12 22:11:12 +00:00
rcourtman b93d8ef205 fix: Remove duplicate sshPublicKey argument in PVE setup script
The setup script generator was passing sshPublicKey twice but only
using it once, causing a Go fmt.Sprintf formatting error that leaked
into the generated bash script as '%!(EXTRA string=...)'.

This resulted in bash syntax errors when running the setup script.

Fixes #528
2025-10-12 22:01:16 +00:00
rcourtman 3c4193c43a fix: Add security gates for containerized temperature monitoring
Addresses #528

- Added opt-in confirmation prompt to setup script with security notice
- Added runtime warning when containerized Pulse uses SSH temperature monitoring
- Documented security considerations and hardening recommendations
- Users must explicitly confirm understanding before enabling in containers
2025-10-12 21:01:25 +00:00
rcourtman b8ae1d681b fix: Setup script now verifies temperature SSH connectivity from Pulse
When Pulse runs in a container (LXC/Docker), the setup script would claim
temperature monitoring was enabled on cluster nodes, but Pulse couldn't
actually SSH to them. The script ran on the Proxmox host which could SSH
fine, but didn't verify connectivity from Pulse itself.

Changes:
- Added /api/system/verify-temperature-ssh endpoint that tests SSH from Pulse
- Setup script now calls this endpoint after configuring cluster nodes
- Detects when Pulse is containerized and provides ProxyJump config instructions
- Shows clear success/failure status for each node

Addresses #528
2025-10-12 20:36:48 +00:00
rcourtman d3ca954d0e fix: Prevent caching of Docker agent install script and binaries
Add no-cache headers to both the install script and agent binary download endpoints to prevent browsers and curl from serving stale cached versions. This ensures users always get the latest install script with URL normalization fixes for trailing slash issues.

Fixes #528
2025-10-12 18:04:57 +00:00
rcourtman d8638abea4 Fix node config API to preserve fields on partial updates
The PUT /api/config/nodes/{id} endpoint was corrupting node configurations
when making partial updates (e.g., updating just monitorPhysicalDisks):

- Authentication fields (tokenName, tokenValue, password) were being cleared
  when updating unrelated settings
- Name field was being blanked when not included in request
- Monitor* boolean fields were defaulting to false

Changes:
- Only update name field if explicitly provided in request
- Only switch authentication method when auth fields are explicitly provided
- Preserve existing auth credentials on non-auth updates
- Applied fix to all node types (PVE, PBS, PMG)

Also enables physical disk monitoring by default (opt-out instead of opt-in)
and preserves disk data between polling intervals.
2025-10-12 17:50:55 +00:00
rcourtman a9377e20d6 Improve NVMe temperature handling 2025-10-12 16:06:55 +00:00
rcourtman 8701d8bb30 feat: capture Proxmox memory snapshots in diagnostics 2025-10-12 10:25:43 +00:00
rcourtman df70775066 docs: Update API docs and feature descriptions for Ceph, Docker, and updates 2025-10-11 22:21:51 +00:00
rcourtman f783fef716 Fix frontend performance issues by caching system settings
Backend was loading system settings from disk on every HTTP request
causing massive log spam and UI responsiveness issues. System settings
are now cached at startup and reloaded only when updated.

Also fixed tab cursor showing text cursor instead of pointer cursor.

Changes:
- Cache system settings in Router struct with mutex protection
- Load settings once at startup instead of on every request
- Add reloadSystemSettings() method to refresh cache when settings change
- Hook up cache reload in config handlers after successful save
- Add cursor-pointer to tab CSS classes for proper hover cursor
2025-10-11 17:22:22 +00:00
rcourtman fe1518457a fix: auto-detect update channel from current version and add background checker
- Auto-detect update channel from current version when config is empty
  (RC users automatically get RC updates, stable users get stable)
- Add background update checker that runs on startup and hourly
- Add GetCachedUpdateInfo() method to return cached update info
- Update /api/version endpoint to include updateAvailable from cache
- Fixes issue where RC users on rc.4 weren't seeing rc.5 updates

This ensures RC testers continue receiving RC notifications while
stable users stay on the stable channel, all without explicit config.
2025-10-10 19:46:52 +00:00
rcourtman d6e61e73ec fix: resolve Docker container permission and path errors in v4.22.0-rc.4
- Fix update history using hardcoded /var/lib/pulse instead of configured data dir
- Skip mock.env watching in Docker environments to avoid 'no such file' errors

Fixes issue #529

Update History Path:
- Modified NewUpdateHandlers to accept dataDir parameter
- Pass r.config.DataPath from router (honors PULSE_DATA_DIR=/data in Docker)
- Maintains backward compatibility with default /var/lib/pulse when empty

Mock Env Watcher:
- Check PULSE_DOCKER env var and skip mock.env watching if true
- Only watch /opt/pulse/mock.env if directory exists (not in containers)
- Guard all mock.env operations to prevent errors when path is empty
- Clean up log messages to only show mock_env_path when actually watching
2025-10-10 18:17:38 +00:00
rcourtman 81f96537e2 fix: resolve docker-agent-install 401 error from trailing slash in PULSE_URL
- Strip trailing slash from PULSE_URL in install script to prevent double-slash URLs
- Add path normalization in router for defense-in-depth on public endpoint matching
- Fixes issue #528 where users copying URLs with trailing slashes got 401 errors

The install script now normalizes PULSE_URL with ${PULSE_URL%/} before concatenating
with /download/pulse-docker-agent, preventing https://example.com//download URLs.

The router normalization provides additional resilience for path matching, though the
existing path traversal check already blocks double slashes at ServeHTTP level.
2025-10-10 18:09:55 +00:00
rcourtman 91222face7 fix: comprehensive Docker agent token security improvements
This commit addresses 6 critical security and UX issues in Docker agent
token handling identified through code review:

**High Priority Fixes:**
1. Fix stale token in command preview - Changed DockerAgents to use
   getInstallCommandTemplate() that always returns placeholder, allowing
   CommandBuilder to handle all token substitution reactively. Command
   preview now updates live as user types.

2. Fix misleading "multiple tokens" messaging - Updated token generation
   modal to accurately reflect single-token backend model with red warning:
   "This will immediately invalidate your existing token". Prevents operators
   from unknowingly breaking active Docker agents.

3. Close proxy auth bypass vulnerability - Both HandleRegenerateAPIToken
   and HandleValidateAPIToken now explicitly reject requests when proxy auth
   is configured but validation fails (returns 401). Prevents unauthenticated
   access when proxy auth is enabled.

**Medium Priority Fixes:**
4. Disable buttons when no stored token - "Use This Token" and "Copy" buttons
   now properly disabled with contextual tooltips when browser hasn't saved
   a token, eliminating confusing silent no-ops.

5. Improve frontend error handling - Token validation now distinguishes
   between authentication errors (401/403), rate limiting (429), network
   failures, and actual invalid tokens. No longer mislabels auth failures
   as "invalid token".

**Low Priority Fixes:**
6. Add authentication to validate-token endpoint - Endpoint now requires
   admin authentication (same as regenerate-token), preventing unauthenticated
   token guessing oracle despite rate limiting.

**New Component:**
- CommandBuilder.tsx: Interactive command builder with live preview,
  state-based visual cues, inline token generation, and validation

**Security Impact:**
- Closes unauthenticated validation surface
- Enforces proper proxy auth gating
- Prevents accidental exposure of security model
- Rate limiting maintained (10 attempts/min)

**UX Impact:**
- Clear, accurate error messages
- Live-updating command preview
- Contextual token management
- Disabled states prevent confusion

Reviewed and verified by both Claude Code and Codex with no regressions found.
2025-10-10 17:54:53 +00:00
rcourtman 5294ed8e4e feat: integrate update system with API endpoints
Wire up the adapter-based update system to HTTP API:

**Enhanced UpdateHandlers:**
- Initialize UpdateHistory and UpdaterRegistry
- Register all deployment adapters (systemd, proxmoxve, docker, aur)
- Handlers now have access to history and updater registry

**New API Endpoints:**
- GET /api/updates/plan?version=X - Get update plan for deployment
  * Returns canAutoUpdate, instructions, prerequisites, estimated time
  * Deployment-specific based on detected type
- GET /api/updates/history?limit=N&status=X - List update history
  * Supports filtering by status (success/failed/in_progress)
  * Returns audit log entries with full metadata
- GET /api/updates/history/entry?id=X - Get specific history entry
  * Retrieve detailed information about past update

**Existing Endpoints Still Work:**
- GET /api/updates/check - Check for available updates
- POST /api/updates/apply - Apply update (legacy manager)
- GET /api/updates/status - Get current update status

The system now supports both:
- Legacy update flow (existing install.sh wrapper in manager.go)
- New adapter-based flow (prepared for frontend integration)

Next: Frontend components to consume new endpoints.
2025-10-10 15:42:21 +00:00
rcourtman 30fa3fd810 feat: add complete Proxmox Mail Gateway (PMG) monitoring support
Add comprehensive PMG monitoring with mail statistics, queue depth tracking,
spam distribution analysis, and quarantine monitoring. Includes full discovery
support and UI consistency improvements across all Proxmox products.

Backend:
- Add pkg/pmg package with complete API client for PMG operations
- Implement mail statistics collection (inbound/outbound, spam, virus, bounces)
- Add queue depth monitoring (active, deferred, hold, incoming queues)
- Support spam score distribution and quarantine totals
- Add PMG-specific discovery logic to differentiate from PVE on port 8006
- Extend mock data generator with realistic PMG instances and metrics
- Add PMG node configuration support in config system

Frontend:
- Create MailGateway.tsx component with detailed PMG dashboard
- Display mail flow statistics with time-series charts
- Show queue depth with color-coded warnings (>50 messages or >30min age)
- Add spam distribution histogram and quarantine status
- Support cluster node status with individual queue monitoring
- Add PMG to network discovery with purple branding and mail icon
- Implement conditional navigation (hide PMG tab when no instances configured)
- Standardize discovery UI controls across PVE/PBS/PMG settings pages

API:
- Add /api/config/pmg endpoints for node configuration
- Support PMG-specific monitoring toggles (mail stats, queues, quarantine)
- Extend system settings with PMG configuration options

Discovery:
- Detect PMG vs PVE on shared port 8006 using /api2/json/statistics/mail endpoint
- Return 'pmg' type for mail gateway servers in discovery results
- Update DiscoveryModal to display PMG servers with appropriate styling

This completes ecosystem monitoring support for all three Proxmox products:
Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
2025-10-10 14:30:51 +00:00
rcourtman 7427a75117 feat: support standard Authorization header for API authentication
Add support for Authorization: Bearer <token> header as a fallback
for environments that strip custom headers like X-API-Token. Docker
agent now sends both headers for maximum compatibility.
2025-10-09 23:03:46 +00:00
rcourtman 95f99767e5 Surface shared storage on all nodes refs #522 2025-10-09 22:55:27 +00:00
rcourtman 5758f1e016 Improve alert notification routing and frontend alert visuals 2025-10-09 10:58:53 +00:00
rcourtman 8aebbe3b54 Revamp alerts and Docker host management 2025-10-07 14:51:55 +00:00
rcourtman bb312ed022 Add Docker monitoring integration with agent-based architecture
Implements comprehensive Docker monitoring with a dedicated agent that collects
container metrics and reports them to the main Pulse server. Adds Docker-specific
alert rules and threshold management with a redesigned UI.

Backend changes:
- Add Docker agent binary with container metrics collection
- Implement Docker host and container models with CPU/memory tracking
- Add Docker-specific alert types (offline, state, health)
- Extend threshold system to support Docker resources
- Add WebSocket message types for Docker agent communication
- Implement Docker agent API endpoints for registration and metrics

Frontend changes:
- Add Docker monitoring page with host/container views
- Add Docker agent settings panel for configuration
- Reorganize thresholds page with Proxmox/Docker tabs
- Add Docker-specific alert threshold management
- Improve layout consistency with vertical stacking
- Fix defensive null checks and TypeScript errors

This change enables monitoring of Docker containers across multiple hosts
with the same alerting and threshold capabilities as Proxmox resources.
2025-10-05 17:51:16 +00:00
rcourtman 062268d4e7 Restrict temperature monitoring SSH key to sensors command
Refs #101
2025-10-04 15:38:34 +00:00
rcourtman 1ced8949f9 Add Ceph monitoring support and UI integration 2025-10-03 22:09:17 +00:00
rcourtman ad3d4b8194 Fix alert acknowledgement sync across websocket updates 2025-10-03 17:25:33 +00:00
rcourtman f61cbb3508 Resolve alert regressions and improve diagnostics 2025-10-03 14:56:27 +00:00
rcourtman 49be28bcae Add Pushover webhook custom field handling 2025-10-01 19:09:06 +00:00
rcourtman 6f2b6268a4 perf: optimize mock mode state retrieval and JSON encoding
Improve performance when serving /api/state in mock mode by optimizing
alert handling and JSON serialization.

Changes:
- Add UpdateAlertSnapshots() to cache alerts without blocking
- Use lazy population of alert snapshots to avoid lock contention
- Switch to json.Marshal for better performance with large payloads
- Add debug logging to track /api/state performance
- Simplify GetState() logic in mock mode

Performance improvements:
- Eliminates alert manager lock during /api/state requests
- Reduces JSON encoding overhead for large mock datasets
- Ensures sub-second response times even with 7 nodes and 90+ guests

Testing:
- Mock mode returns state instantly without blocking
- Alert snapshots populate correctly on first request
- Debug logs confirm fast execution path
2025-10-01 13:35:49 +00:00
rcourtman c664204b59 feat: add OIDC logout URL support and improve UX
Enhancements for OIDC authentication based on user feedback from issue #327:

1. Add OIDC logout URL support
   - New OIDC_LOGOUT_URL environment variable
   - UI field in OIDC settings panel for logout URL configuration
   - Properly redirects to IdP logout endpoint (e.g., Authentik end-session)
   - Stored in config and returned via security status API

2. Fix redirect URL help text in UI
   - Handle empty defaultRedirect string properly
   - Improved help text when PUBLIC_URL is not set
   - Clarify when auto-detection vs manual config is needed

3. Documentation improvements
   - Add note about using https:// in PUBLIC_URL/OIDC_REDIRECT_URL when behind TLS proxy
   - Document OIDC_LOGOUT_URL environment variable
   - Clarify X-Forwarded-Proto header behavior in OIDC docs
   - Add better guidance for Authentik users on HTTPS setup

4. Frontend improvements
   - Add HS256 signature algorithm error message in Login component
   - Display OIDC logout URL when available

These changes address the remaining OIDC UX issues reported by users,
particularly around logout functionality and reverse proxy configuration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-01 10:59:22 +00:00
rcourtman 2b4b6a08e1 fix: resolve OIDC authentication issues with DISABLE_AUTH and improve UX
Fixes multiple OIDC authentication issues reported in GitHub issue #327:

1. Fix DISABLE_AUTH=true disabling OIDC sessions
   - Reorder authentication checks to validate proxy auth and OIDC sessions
     before checking DISABLE_AUTH flag
   - Allows OIDC to function even when basic auth is disabled

2. Fix missing username display for OIDC users
   - Add GetSessionUsername() function to look up username from session ID
   - Set X-Authenticated-User header for OIDC authenticated requests
   - Update security status endpoint to return oidcUsername field
   - Display OIDC username in UI header alongside logout button

3. Fix missing logout button for OIDC users
   - Set hasAuth(true) when OIDC session is detected in frontend
   - Update security status endpoint to return OIDC info even when
     DISABLE_AUTH=true
   - Properly initialize WebSocket and load user preferences for OIDC sessions

4. Add documentation for Authentik HS256/RS256 issue
   - Document requirement for RSA signing key in Authentik
   - Add troubleshooting entry for signature algorithm mismatch
   - Provide clear resolution steps in CONFIGURATION.md and OIDC.md

All changes maintain backward compatibility and follow defensive security
practices. X-Forwarded-Proto header handling was verified to be correct.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-01 10:53:19 +00:00
rcourtman 4160d2e68b feat: add SSH key removal option to Quick Setup and fix node deletion
- Enhanced Quick Setup script to detect existing SSH configuration
  - Offers Keep/Remove/Skip options when SSH key already exists
  - Provides clean removal of SSH key from authorized_keys
  - Shows manual removal instructions for lm-sensors package
- Fixed ConfigWatcher panic on double-close during shutdown
- Fixed node deletion to allow removing the last node
  - Added SaveNodesConfigAllowEmpty method for explicit admin actions
  - Fixed deleted node host extraction before removal
- Display Quick Setup command after copying to clipboard
- Improved node name matching for temperature data
  - Handles .lan suffix variations between config and WebSocket state

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-01 10:25:56 +00:00
rcourtman d0f049d373 refactor: improve setup script output professionalism
- Remove excessive emojis and decorative elements
- Use clear, concise language throughout
- Simplify progress indicators to simple checkmarks
- Remove unnecessary tips and verbose explanations
- Improve error message clarity
- Use proper capitalization (not ALL CAPS for emphasis)
- Clean up temperature monitoring prompt to be more direct

The setup script now presents a more professional, enterprise-ready
appearance while maintaining all functionality.
2025-10-01 08:14:49 +00:00
rcourtman fdf0e0b958 feat: automate SSH key generation and embedding in setup scripts
- Add getOrGenerateSSHKey() function that automatically generates SSH keypair if needed
- Embed SSH public key directly in setup scripts (no manual copy/paste required)
- Simplify temperature monitoring setup - user just types 'y' and it's done
- Improves UX: removes manual steps for SSH key setup

Changes:
- internal/api/config_handlers.go: Add SSH key generation and auto-embedding
- frontend-modern/src/components/Settings/NodeModal.tsx: Remove dead setupCode modal code
- Setup script now includes embedded SSH_PUBLIC_KEY variable

User workflow before:
1. Run setup script
2. Prompted to run commands on Pulse server
3. Copy SSH public key manually
4. Paste into setup script
5. Done

User workflow now:
1. Run setup script
2. Type 'y' for temperature monitoring
3. Done (SSH key automatically installed)
2025-10-01 08:10:48 +00:00
rcourtman 6bfaa8b79a fix: OIDC redirect URL now respects X-Forwarded-Proto header
Addresses #327 - Users behind reverse proxies (Traefik, nginx, etc) were
experiencing redirect loop issues because the redirect URL was being built
with http:// instead of https:// when X-Forwarded-Proto was set.

Changes:
- Build OIDC redirect URL dynamically from each request instead of at startup
- Respect X-Forwarded-Proto and X-Forwarded-Host headers from reverse proxies
- Update UI help text to clarify auto-detection behavior
- Add debug logging to show how redirect URL is constructed

When redirect URL is not explicitly configured, Pulse now builds it from
the incoming request headers, properly detecting HTTPS when behind a proxy.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-30 21:06:20 +00:00
rcourtman edb8702e77 fix CI errors: remove unused imports and format Go code
addresses unused TypeScript variables and gofmt formatting issues
2025-09-30 19:59:55 +00:00
rcourtman fd52a7add1 improve oidc error logging and documentation
addresses #327

- added detailed logging when ID token verification fails
- added better error messages for common OIDC issues
- updated docs with Authentik-specific configuration
- added troubleshooting section for redirect loops and invalid_id_token errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-30 19:52:55 +00:00
rcourtman 745c2b4c6b rebalance temperature monitoring messaging - reassuring but honest
Changed from scary warnings to confident, reassuring tone:

Before:
- "⚠️ IMPORTANT: This grants SSH access..."
- Emphasized risks and compromise scenarios
- Made users feel unsafe enabling the feature

After:
- "Works just like Ansible, Saltstack, etc."
- Emphasizes this is industry-standard approach
- Compares to trusted automation tools
- Focuses on what it does, not what could go wrong
- Still transparent about security model
- Removes duplicate/contradictory sections

The feature is secure and follows best practices. The messaging should
reflect confidence in the design while still being transparent.

Users should feel good about enabling it, not scared.
2025-09-30 19:16:30 +00:00
rcourtman d5bd6c7676 improve SSH setup security messaging for temperature monitoring
- Make it clear SSH setup is OPTIONAL
- Explain security model upfront before user commits
- Detail exactly what access is being granted (root SSH, sensors only)
- Warn users to only proceed if they trust Pulse server
- Better differentiate public vs private keys
- Show exactly where the key is stored
- Explain how to revoke access
- Add comprehensive security documentation
- Include advanced option for command restrictions in authorized_keys
- Add risk assessment and best practices

This ensures users make informed decisions about SSH access to their
critical Proxmox infrastructure.
2025-09-30 19:13:23 +00:00
rcourtman d78c388cd0 add SSH key setup to auto-setup script for temperature monitoring
- Prompts user to set up SSH access during auto-setup
- Guides user to paste their Pulse server's public key
- Adds key to /root/.ssh/authorized_keys
- Installs lm-sensors automatically
- Runs sensors-detect --auto for proper sensor detection
- Optional: user can skip and set up later manually
- Includes validation of SSH key format
- Shows clear instructions for manual setup if skipped

This ensures temperature monitoring works out-of-the-box for users
who run the auto-setup script.
2025-09-30 19:10:45 +00:00