Commit graph

741 commits

Author SHA1 Message Date
rcourtman
f7936cb540 Fix duplicate allowed_nodes in sensor proxy installer
The install-sensor-proxy.sh script was blindly appending allowed_nodes
sections to the config file without checking if they already existed.
When the script was re-run or if the initial config already had an
allowed_nodes section, this created duplicate YAML keys that caused
the proxy service to fail with parse errors.

Changes:
- Add update_allowed_nodes() helper function that safely updates the
  allowed_nodes section by removing any existing ones first
- Replace all three cat >> config.yaml heredocs with calls to the
  helper function (cluster nodes, standalone mode, pvecm fallback)
- Uses awk to properly parse and remove multi-line YAML sections

This makes the installer idempotent and prevents config corruption on
re-runs.

Fixes issue where proxy service crashed with:
  'mapping key "allowed_nodes" already defined at line X'
2025-11-14 21:43:31 +00:00
rcourtman
387a68ef18 Allow dev builds to skip proxy version gate 2025-11-14 21:34:55 +00:00
rcourtman
e708727725 Improve sensor proxy socket verification 2025-11-14 20:14:25 +00:00
rcourtman
7cfe998fca Make download tests use temp bin dir 2025-11-14 13:59:50 +00:00
rcourtman
1c7991954e CI: remove unsupported vitest args 2025-11-14 13:41:16 +00:00
rcourtman
20194d9bb7 Add CI build workflow and tighten proxy diagnostics 2025-11-14 13:32:29 +00:00
rcourtman
65fbd72b15 feat: add shared status indicators
Related to #677
2025-11-14 12:42:08 +00:00
rcourtman
349f5627e5 monitoring: add poll watchdog to prevent worker leaks (refs #696) 2025-11-14 11:24:59 +00:00
rcourtman
6e9a62f663 Ensure Windows download finds .exe (related to #684) 2025-11-14 10:59:45 +00:00
rcourtman
1d0d23d237 Related to #710: harden Windows installer arch detection 2025-11-14 10:50:56 +00:00
rcourtman
1ed69d35b6 docs: highlight runbooks in index and script verification checklist 2025-11-14 10:39:10 +00:00
rcourtman
dca562b7b4 docs: reference log forwarding runbook in sensor proxy guides 2025-11-14 10:37:09 +00:00
rcourtman
4693900f8b docs: document sensor proxy log forwarding 2025-11-14 01:12:25 +00:00
rcourtman
da192dd4c2 docs: surface operations runbooks in main readme 2025-11-14 01:08:41 +00:00
rcourtman
34bf5f524b docs: add auto-update troubleshooting 2025-11-14 01:07:32 +00:00
rcourtman
7a9c420912 docs: clarify auto-update flow and surface proxy guide 2025-11-14 01:06:11 +00:00
rcourtman
a163988bf5 docs: add auto-update runbook 2025-11-14 01:05:06 +00:00
rcourtman
1aec43b1ac docs: escape table pipes in sensor proxy readme 2025-11-14 01:01:55 +00:00
rcourtman
9864258207 docs: add operations runbooks and audit fixes 2025-11-14 01:01:21 +00:00
rcourtman
4d021f8a50 Related to #701: improve sensor proxy installer caching 2025-11-14 00:51:54 +00:00
rcourtman
b77330b1be Clarify sensor proxy HTTPS workflow in docs 2025-11-14 00:48:41 +00:00
rcourtman
a278b52b5e Explain HTTPS-first temperature architecture 2025-11-14 00:45:20 +00:00
rcourtman
bfb8fd4a64 Document v4.31.0 release highlights 2025-11-14 00:43:16 +00:00
rcourtman
86bc617940 Fix YAML syntax errors in workflow files 2025-11-13 23:54:55 +00:00
rcourtman
99b53afc49 Add branch trigger for testing 2025-11-13 23:48:19 +00:00
rcourtman
b650f7e174 Add minimal test workflow 2025-11-13 23:45:23 +00:00
rcourtman
3f8c994aa9 Use GITHUB_EVENT_PATH to parse inputs avoiding template context errors 2025-11-13 23:44:40 +00:00
rcourtman
f1303cf339 Fix workflow inputs context for push events 2025-11-13 23:42:59 +00:00
rcourtman
a8b6143408 Re-add tag trigger to enable workflow 2025-11-13 23:37:48 +00:00
rcourtman
039aba5df1 Match dry-run workflow format exactly 2025-11-13 23:29:56 +00:00
rcourtman
f886a3a422 Rename workflow file to force new workflow_id 2025-11-13 23:29:19 +00:00
rcourtman
cb8c1075fd Remove tag trigger to test workflow_dispatch 2025-11-13 23:28:57 +00:00
rcourtman
7e90ce0377 Add test workflow to diagnose dispatch issue 2025-11-13 23:26:39 +00:00
rcourtman
b36c988173 Add new pulse-release workflow with unique name 2025-11-13 23:23:39 +00:00
rcourtman
8f42dae363 Remove duplicate release workflows to force GitHub re-indexing 2025-11-13 23:23:16 +00:00
rcourtman
cc42007b00 Force workflow re-index for v4.31.0 release 2025-11-13 23:18:12 +00:00
rcourtman
33d712c185 Prepare v4.31.0 release 2025-11-13 23:14:01 +00:00
rcourtman
4f8b807f0c Refine Windows host installer logging (related to #709) 2025-11-13 23:09:22 +00:00
rcourtman
f2b888386c Remove installer v2 rollout doc 2025-11-13 22:36:01 +00:00
rcourtman
6d591920d9 Remove CONTRIBUTING-SCRIPTS doc 2025-11-13 22:34:21 +00:00
rcourtman
70673c1fdc Improve temperature proxy diagnostics and tests 2025-11-13 22:31:53 +00:00
rcourtman
319bf56a6f Add context timeout to local temperature collection
The getTemperatureLocal() function was running sensors without a timeout,
which could cause HTTP requests to hang if the sensors command stalled.

This adds context.Context parameter and uses exec.CommandContext to ensure
local temperature collection respects the same 15-second timeout as SSH-based
collection.

Fixes issue where HTTP mode worked for remote nodes but timed out for
self-monitoring on the same host.
2025-11-13 20:15:05 +00:00
rcourtman
9cb151d836 Add localhost to allowed_source_subnets for self-monitoring
The HTTP mode installer now includes 127.0.0.1/32 in allowed_source_subnets
to permit self-monitoring queries from localhost. This fixes 403 Forbidden
errors when nodes query their own sensor-proxy instance.

Related to HTTP mode implementation for external PVE hosts.
2025-11-13 19:34:11 +00:00
rcourtman
3c707a7368 Fix HTTP mode reliability: add context timeouts to SSH collection
Critical fix for intermittent HTTP endpoint hangs identified by Codex analysis.

## Root Cause
SSH collection via getTemperatureViaSSH() had no timeout, causing HTTP
handlers to block indefinitely when sensors command hung. This held node-level
mutexes and rate limit slots, creating cascading failures where subsequent
requests queued indefinitely.

## Solution
- Thread request context through to SSH execution
- Add exec.CommandContext with 15s timeout (vs 30s HTTP client timeout)
- Create execCommandWithLimitsContext() to wrap SSH commands
- Ensures handlers always release locks and respond within deadline

## Impact
- HTTP temps endpoint now responds in ~70ms consistently
- Temperature data successfully collected and displayed in Pulse
- Eliminates 'context deadline exceeded' errors
- Prevents node gate deadlocks from slow/stuck SSH sessions

Related to Codex session 019a7e99-00fc-7903-afa3-01100baf47c6
2025-11-13 19:09:50 +00:00
rcourtman
e2bd514899 Fix HTTP mode for pulse-sensor-proxy and improve installer safety
## HTTP Server Fixes
- Add source IP middleware to enforce allowed_source_subnets
- Fix missing source subnet validation for external HTTP requests
- HTTP health endpoint now respects subnet restrictions

## Installer Improvements
- Auto-configure allowed_source_subnets with Pulse server IP
- Add cluster node hostnames to allowed_nodes (not just IPs)
- Fix node validation to accept both hostnames and IPs
- Add Pulse server reachability check before installation
- Add port availability check for HTTP mode
- Add automatic rollback on service startup failure
- Add HTTP endpoint health check after installation
- Fix config backup and deduplication (prevent duplicate keys)
- Fix IPv4 validation with loopback rejection
- Improve registration retry logic with detailed errors
- Add automatic LXC bind mount cleanup on uninstall

## Temperature Collection Fixes
- Add local temperature collection for self-monitoring nodes
- Fix node identifier matching (use hostname not SSH host)
- Fix JSON double-encoding in HTTP client response

Related to #XXX (temperature monitoring fixes)
2025-11-13 18:22:36 +00:00
rcourtman
71217dfae4 Add HTTP mode support to sensor-proxy installer
Implements complete HTTP mode installation workflow for external PVE hosts.

New installer features:
- `--http-mode` flag: Enable HTTP server mode for remote temperature monitoring
- `--http-addr <addr>` flag: Configure listen address (default :8443)
- Auto-generates self-signed TLS certificates (4096-bit RSA, 10-year validity)
- Registers with Pulse API and receives authentication token
- Configures systemd service with proper security hardening

Installation workflow (HTTP mode):
1. Validate --pulse-server parameter is provided
2. Generate TLS certificate with SAN (hostname + IPs)
3. Call Pulse API POST /api/temperature-proxy/register
4. Receive and store auth token securely (mode 600)
5. Append HTTP config to config.yaml
6. Update systemd service with TLS paths
7. Start service

TLS certificate generation:
- Uses openssl req with RSA 4096-bit keys
- 10-year validity period
- SubjectAltName includes hostname + all IPs
- Files stored in /etc/pulse-sensor-proxy/tls/
- Permissions: 640 root:pulse-sensor-proxy
- Logs SHA256 fingerprint for audit

API registration:
- Calls POST /api/temperature-proxy/register
- Payload: {"hostname": "...", "proxy_url": "https://..."}
- Response: {"token": "...", "pve_instance": "..."}
- Aborts installation on registration failure (fail-fast)
- Token stored in config.yaml

Systemd service updates:
- Adds ReadOnlyPaths=/etc/pulse-sensor-proxy/tls for HTTP mode
- RestrictAddressFamilies already includes AF_INET/AF_INET6
- Maintains all existing security hardening

Error handling:
- Validates required parameters before starting
- Aborts on TLS generation failure
- Aborts on API registration failure
- Provides actionable troubleshooting guidance
- Logs clear error messages

Security:
- Tokens stored with mode 600, owned by service user
- TLS keys protected with mode 640
- Service runs as unprivileged pulse-sensor-proxy user
- Full systemd hardening maintained

Usage example:
  curl -fsSL https://pulse-server/download/install-sensor-proxy.sh | \
    bash -s -- --http-mode --pulse-server https://pulse.example.com:7655

Related to #571
2025-11-13 16:33:12 +00:00
rcourtman
a2b8940873 Add Pulse API endpoints for temperature proxy registration
Implements REST API endpoints to enable automatic registration of
temperature proxies during sensor-proxy installation.

API endpoints:
- POST /api/temperature-proxy/register
  - Accepts: hostname, proxy_url
  - Returns: authentication token
  - Finds matching PVE instance and configures proxy URL/token
  - No authentication required (called during installation)

- DELETE /api/temperature-proxy/unregister?hostname=X
  - Removes proxy configuration from PVE instance
  - Requires admin authentication

Implementation:
- Uses config.ConfigPersistence for loading/saving nodes.enc
- Matches PVE instances by hostname in Host field or ClusterEndpoints
- Generates cryptographically secure random tokens (32 bytes, base64)
- Atomic config updates (load → modify → save)

Next step: Update install-sensor-proxy.sh to call registration API

Related to #571
2025-11-13 16:20:47 +00:00
rcourtman
22f092f941 Add HTTP mode to pulse-sensor-proxy for multi-instance temperature monitoring
This implements HTTP/HTTPS support for pulse-sensor-proxy to enable
temperature monitoring across multiple separate Proxmox instances.

Architecture changes:
- Dual-mode operation: Unix socket (local) + HTTPS (remote)
- Unix socket remains default for security/performance (no breaking change)
- HTTP mode enables temps from external PVE hosts

Backend implementation:
- Add HTTPS server with TLS + Bearer token authentication to sensor-proxy
- Add TemperatureProxyURL and TemperatureProxyToken fields to PVEInstance
- Add HTTP client (internal/tempproxy/http_client.go) for remote proxy calls
- Update temperature collector to prefer HTTP proxy when configured
- Fallback logic: HTTP proxy → Unix socket → direct SSH (if not containerized)

Configuration:
- pulse-sensor-proxy config: http_enabled, http_listen_addr, http_tls_cert/key, http_auth_token
- PVEInstance config: temperature_proxy_url, temperature_proxy_token
- Environment variables: PULSE_SENSOR_PROXY_HTTP_* for all HTTP settings

Security:
- TLS 1.2+ with modern cipher suites
- Constant-time token comparison (timing attack prevention)
- Rate limiting applied to HTTP requests (shared with socket mode)
- Audit logging for all HTTP requests

Next steps:
- Update installer script to support HTTP mode + auto-registration
- Add Pulse API endpoint for proxy registration
- Generate TLS certificates during installation
- Test multi-instance temperature collection

Related to #571 (multi-instance architecture)
2025-11-13 16:13:53 +00:00
rcourtman
ea80a6153c Increase rate limiting for startup bursts
Increased default rate limits to handle Pulse startup polling:
- Per-peer burst: 5 → 10 requests (handles multi-node clusters with retries)
- Per-peer interval: 1s → 500ms (1 QPS → 2 QPS, 60/min → 120/min)

This prevents the proxy from being disabled during Pulse startup when it
polls all nodes simultaneously. The previous limits were too restrictive
for clusters with 3+ nodes.
2025-11-13 15:42:26 +00:00
rcourtman
cd9d63d464 Fix #571: Installer now auto-configures allowed_nodes for temperature monitoring
When cluster IPC validation fails (due to systemd hardening), the proxy
falls back to allowlist-based validation. The installer now automatically
populates allowed_nodes with:

- Cluster mode: All discovered cluster member IPs
- Standalone mode: localhost IP addresses (including 127.0.0.1/localhost)
- Fallback mode: localhost IPs when pvecm unavailable

This ensures out-of-the-box temperature monitoring works on fresh installs
without manual configuration.
2025-11-13 15:37:30 +00:00