WIP: Fix temperature proxy registration persistence (incomplete)

This commit contains multiple fixes for temperature proxy registration,
but the core issue remains unresolved.

## What's Fixed:
1. Added config pointer and reloadFunc to TemperatureProxyHandlers
2. Added SetConfig method to keep handler in sync with router config changes
3. Added config reload after registration to prevent monitor from overwriting
4. Fixed installer port conflict detection and duplicate YAML key issues
5. Added comprehensive debug logging throughout registration flow

## What's Still Broken:
The TemperatureProxyURL, TemperatureProxyToken, and TemperatureProxyControlToken
fields are NOT persisting to nodes.enc after SaveNodesConfig is called.

Debug logs confirm:
- HandleRegister correctly updates nodesConfig.PVEInstances[matchedIndex]
- The correct data is passed to SaveNodesConfig (verified in logs)
- SaveNodesConfig completes without errors
- Config reload executes successfully
- BUT after Pulse restart, the fields are empty when loaded from disk

The bug is in SaveNodesConfig serialization or file writing logic itself.

Related files:
- internal/api/temperature_proxy.go: Registration handler
- internal/config/persistence.go: SaveNodesConfig implementation
- internal/config/config.go: PVEInstance struct definition
This commit is contained in:
rcourtman
2025-11-19 20:12:19 +00:00
parent 714c2b753d
commit 7d0bbaf961
5 changed files with 160 additions and 70 deletions

View File

@@ -3418,6 +3418,12 @@ echo " Pulse Monitoring Setup for Proxmox VE"
echo "============================================"
echo ""
PULSE_URL="%s"
SERVER_HOST="%s"
TOKEN_NAME="%s"
PULSE_TOKEN_ID="pulse-monitor@pam!${TOKEN_NAME}"
SETUP_SCRIPT_URL="$PULSE_URL/api/setup-script?type=pve&host=$SERVER_HOST&pulse_url=$PULSE_URL"
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo "Please run this script as root"
@@ -3497,10 +3503,10 @@ case "$ENVIRONMENT" in
# 1) Create or reuse the Pulse monitoring API token
pveum user add pulse-monitor@pam --comment "Pulse monitoring service"
pveum aclmod / -user pulse-monitor@pam -role PVEAuditor
pveum user token add pulse-monitor@pam %s --privsep 0
pveum user token add pulse-monitor@pam "$TOKEN_NAME" --privsep 0
# 2) Install or update pulse-sensor-proxy on the host
curl -sSL "%s/api/install/install-sensor-proxy.sh" | bash -s -- --ctid ${CTID_DISPLAY} --pulse-server "%s"
curl -sSL "$PULSE_URL/api/install/install-sensor-proxy.sh" | bash -s -- --ctid ${CTID_DISPLAY} --pulse-server "$PULSE_URL"
# 3) Ensure the proxy socket is mounted into this container
NEXT_MP=\$(pct config ${CTID_DISPLAY} | awk '\$1 ~ /^mp[0-9]+:/ && index(\$0, "mp=/mnt/pulse-proxy") {gsub(":", "", \$1); print \$1; exit}')
@@ -3510,7 +3516,7 @@ pct exec ${CTID_DISPLAY} -- test -S /mnt/pulse-proxy/pulse-sensor-proxy.sock &&
EOF
echo "For the simplest experience, run this script on your Proxmox host instead:"
echo " curl -sSL \"%s/api/setup-script?type=pve&host=%s&pulse_url=%s\" | bash"
echo " curl -sSL \"$SETUP_SCRIPT_URL\" | bash"
echo ""
echo "Exiting without error. Re-run after completing the host steps."
exit 0
@@ -3519,23 +3525,23 @@ EOF
echo "This script requires Proxmox host tooling (pveum)."
echo ""
echo "Run on your Proxmox host:"
echo " curl -sSL \"%s/api/setup-script?type=pve&host=%s&pulse_url=%s\" | bash"
echo " curl -sSL \"$SETUP_SCRIPT_URL\" | bash"
echo ""
echo "Manual setup steps:"
echo " 1. On Proxmox host, create API token:"
echo " pveum user add pulse-monitor@pam --comment \"Pulse monitoring service\""
echo " pveum aclmod / -user pulse-monitor@pam -role PVEAuditor"
echo " pveum user token add pulse-monitor@pam %s --privsep 0"
echo " pveum user token add pulse-monitor@pam "$TOKEN_NAME" --privsep 0"
echo ""
echo " 2. In Pulse: Settings → Nodes → Add Node (enter token from above)"
echo ""
echo " 3. (Optional) For temperature monitoring on containerized Pulse:"
echo ""
echo " For LXC containers, run on Proxmox host:"
echo " curl -sSL %s/api/install/install-sensor-proxy.sh | bash -s -- --ctid <CTID> --pulse-server %s"
echo " curl -sSL $PULSE_URL/api/install/install-sensor-proxy.sh | bash -s -- --ctid <CTID> --pulse-server $PULSE_URL"
echo ""
echo " For Docker containers, run on Proxmox host:"
echo " curl -sSL %s/api/install/install-sensor-proxy.sh | bash -s -- --standalone --pulse-server %s"
echo " curl -sSL $PULSE_URL/api/install/install-sensor-proxy.sh | bash -s -- --standalone --pulse-server $PULSE_URL"
echo " Then add to docker-compose.yml:"
echo " volumes:"
echo " - /run/pulse-sensor-proxy:/run/pulse-sensor-proxy:rw"
@@ -3809,25 +3815,25 @@ echo "Generating API token..."
# Check if token already exists
TOKEN_EXISTED=false
if pveum user token list pulse-monitor@pam 2>/dev/null | grep -q "%s"; then
if pveum user token list pulse-monitor@pam 2>/dev/null | grep -q "$TOKEN_NAME"; then
TOKEN_EXISTED=true
echo ""
echo "================================================================"
echo "WARNING: Token '%s' already exists!"
echo "WARNING: Token '$TOKEN_NAME' already exists!"
echo "================================================================"
echo ""
echo "To create a new token, first remove the existing one:"
echo " pveum user token remove pulse-monitor@pam %s"
echo " pveum user token remove pulse-monitor@pam $TOKEN_NAME"
echo ""
echo "Or create a token with a different name:"
echo " pveum user token add pulse-monitor@pam %s-$(date +%%s) --privsep 0"
echo " pveum user token add pulse-monitor@pam ${TOKEN_NAME}-$(date +%%s) --privsep 0"
echo ""
echo "Then use the new token ID in Pulse (e.g., pulse-monitor@pam!%s-1234567890)"
echo "Then use the new token ID in Pulse (e.g., ${PULSE_TOKEN_ID}-1234567890)"
echo "================================================================"
echo ""
else
# Create token silently first
TOKEN_OUTPUT=$(pveum user token add pulse-monitor@pam %s --privsep 0)
TOKEN_OUTPUT=$(pveum user token add pulse-monitor@pam "$TOKEN_NAME" --privsep 0)
# Extract the token value for auto-registration
TOKEN_VALUE=$(echo "$TOKEN_OUTPUT" | grep "│ value" | awk -F'│' '{print $3}' | tr -d ' ' | tail -1)
@@ -3884,11 +3890,8 @@ else
SERVER_HOSTNAME=$(hostname -s 2>/dev/null || hostname)
SERVER_IP=$(hostname -I | awk '{print $1}')
# Send registration to Pulse
PULSE_URL="%s"
# Check if host URL was provided
HOST_URL="%s"
HOST_URL="$SERVER_HOST"
if [ "$HOST_URL" = "https://YOUR_PROXMOX_HOST:8006" ] || [ -z "$HOST_URL" ]; then
echo ""
echo "❌ ERROR: No Proxmox host URL provided!"
@@ -3901,7 +3904,7 @@ else
echo " curl -sSL \"$PULSE_URL/api/setup-script?type=pve&host=https://192.168.0.5:8006&pulse_url=$PULSE_URL\" | bash"
echo ""
echo "📝 For manual setup, use the token created above with:"
echo " Token ID: pulse-monitor@pam!%s"
echo " Token ID: $PULSE_TOKEN_ID"
echo " Token Value: [See above]"
echo ""
exit 1
@@ -3909,7 +3912,7 @@ else
# Construct registration request with setup code
# Build JSON carefully to preserve the exclamation mark
REGISTER_JSON='{"type":"pve","host":"'"$HOST_URL"'","serverName":"'"$SERVER_HOSTNAME"'","tokenId":"pulse-monitor@pam!%s","tokenValue":"'"$TOKEN_VALUE"'","authToken":"'"$AUTH_TOKEN"'"}'
REGISTER_JSON='{"type":"pve","host":"'"$HOST_URL"'","serverName":"'"$SERVER_HOSTNAME"'","tokenId":"'"$PULSE_TOKEN_ID"'","tokenValue":"'"$TOKEN_VALUE"'","authToken":"'"$AUTH_TOKEN"'"}'
# Send registration with setup code
REGISTER_RESPONSE=$(echo "$REGISTER_JSON" | curl -s -X POST "$PULSE_URL/api/auto-register" \
@@ -4043,7 +4046,7 @@ SSH_SENSORS_KEY_ENTRY="command=\"sensors -j\",no-port-forwarding,no-X11-forwardi
TEMPERATURE_ENABLED=false
TEMP_MONITORING_AVAILABLE=true
MIN_PROXY_VERSION="%s"
PULSE_VERSION_ENDPOINT="%s/api/version"
PULSE_VERSION_ENDPOINT="$PULSE_URL/api/version"
STANDALONE_PROXY_DEPLOYED=false
SKIP_TEMPERATURE_PROMPT=false
PROXY_SOCKET_EXISTED_AT_START=false
@@ -4067,7 +4070,7 @@ version_ge() {
}
# Check if temperature proxy is available and override SSH key if it is
PROXY_KEY_URL="%s/api/system/proxy-public-key"
PROXY_KEY_URL="$PULSE_URL/api/system/proxy-public-key"
TEMPERATURE_PROXY_KEY=$(curl -s -f "$PROXY_KEY_URL" 2>/dev/null || echo "")
if [ -n "$TEMPERATURE_PROXY_KEY" ] && [[ "$TEMPERATURE_PROXY_KEY" =~ ^ssh-(rsa|ed25519) ]]; then
# Proxy is available - use its key instead of container's key
@@ -4080,7 +4083,7 @@ PULSE_CTID=""
PULSE_IS_CONTAINERIZED=false
if command -v pct >/dev/null 2>&1; then
# Extract Pulse IP from URL
PULSE_IP=$(echo "%s" | sed -E 's|^https?://([^:/]+).*|\1|')
PULSE_IP=$(echo "$PULSE_URL" | sed -E 's|^https?://([^:/]+).*|\1|')
# Find container with this IP
if [[ "$PULSE_IP" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
@@ -4199,7 +4202,7 @@ if [ "$TEMP_MONITORING_AVAILABLE" = true ] && [ "$PULSE_IS_CONTAINERIZED" = true
if true; then
# Download installer script from Pulse server
PROXY_INSTALLER="/tmp/install-sensor-proxy-$$.sh"
INSTALLER_URL="%s/api/install/install-sensor-proxy.sh"
INSTALLER_URL="$PULSE_URL/api/install/install-sensor-proxy.sh"
echo "Installing pulse-sensor-proxy..."
if curl --fail --silent --location \
@@ -4208,7 +4211,7 @@ if [ "$TEMP_MONITORING_AVAILABLE" = true ] && [ "$PULSE_IS_CONTAINERIZED" = true
chmod +x "$PROXY_INSTALLER"
# Run installer with Pulse server as fallback
INSTALL_OUTPUT=$("$PROXY_INSTALLER" --ctid "$PULSE_CTID" --pulse-server "%s" 2>&1)
INSTALL_OUTPUT=$("$PROXY_INSTALLER" --ctid "$PULSE_CTID" --pulse-server "$PULSE_URL" 2>&1)
INSTALL_STATUS=$?
if [ -n "$INSTALL_OUTPUT" ]; then
@@ -4311,7 +4314,7 @@ if [ "$SKIP_TEMPERATURE_PROMPT" = true ]; then
# Download and run installer to refresh config
PROXY_INSTALLER="/tmp/install-sensor-proxy-repair-$$.sh"
INSTALLER_URL="%s/api/install/install-sensor-proxy.sh"
INSTALLER_URL="$PULSE_URL/api/install/install-sensor-proxy.sh"
if curl --fail --silent --location "$INSTALLER_URL" -o "$PROXY_INSTALLER" 2>/dev/null; then
chmod +x "$PROXY_INSTALLER"
@@ -4331,10 +4334,10 @@ if [ "$SKIP_TEMPERATURE_PROMPT" = true ]; then
if [ -n "$DETECTED_CTID" ]; then
# Was deployed for containerized Pulse - use --ctid mode
INSTALLER_ARGS="--ctid $DETECTED_CTID --pulse-server %s"
INSTALLER_ARGS="--ctid $DETECTED_CTID --pulse-server $PULSE_URL"
elif [ "$IS_STANDALONE_NODE" = true ]; then
# Standalone node - use --standalone --http-mode
INSTALLER_ARGS="--standalone --http-mode --pulse-server %s"
INSTALLER_ARGS="--standalone --http-mode --pulse-server $PULSE_URL"
else
# Cannot determine deployment type - bail out
echo ""
@@ -4342,10 +4345,10 @@ if [ "$SKIP_TEMPERATURE_PROMPT" = true ]; then
echo " Manual repair required. Run one of:"
echo ""
echo " • For container:"
echo " curl -fsSL %s/api/install/install-sensor-proxy.sh | bash -s -- --ctid <CTID> --pulse-server %s"
echo " curl -fsSL $PULSE_URL/api/install/install-sensor-proxy.sh | bash -s -- --ctid <CTID> --pulse-server $PULSE_URL"
echo ""
echo " • For standalone:"
echo " curl -fsSL %s/api/install/install-sensor-proxy.sh | bash -s -- --standalone --http-mode --pulse-server %s"
echo " curl -fsSL $PULSE_URL/api/install/install-sensor-proxy.sh | bash -s -- --standalone --http-mode --pulse-server $PULSE_URL"
echo ""
echo " Keeping existing proxy configuration"
rm -f "$PROXY_INSTALLER"
@@ -4353,7 +4356,15 @@ if [ "$SKIP_TEMPERATURE_PROMPT" = true ]; then
fi
if [ -n "$INSTALLER_ARGS" ]; then
# Run installer and capture output for diagnostics
# Check if service is already running
if systemctl is-active --quiet pulse-sensor-proxy 2>/dev/null; then
echo "✓ pulse-sensor-proxy service is already running"
echo " Refreshing configuration and token..."
echo ""
fi
# Run installer to refresh config and restart service
# The installer handles stopping/restarting on its own
INSTALL_OUTPUT=$("$PROXY_INSTALLER" $INSTALLER_ARGS 2>&1)
REPAIR_STATUS=$?
@@ -4486,7 +4497,7 @@ elif [ "$TEMP_MONITORING_AVAILABLE" = true ]; then
# SECURITY: Block SSH-based temperature monitoring for containerized Pulse (unless dev mode)
if [ "$PULSE_IS_CONTAINERIZED" = true ]; then
# Check for dev mode override (from Pulse server environment)
DEV_MODE_RESPONSE=$(curl -s "%s/api/health" 2>/dev/null | grep -o '"devModeSSH"[[:space:]]*:[[:space:]]*true' || echo "")
DEV_MODE_RESPONSE=$(curl -s "$PULSE_URL/api/health" 2>/dev/null | grep -o '"devModeSSH"[[:space:]]*:[[:space:]]*true' || echo "")
if [ -n "$DEV_MODE_RESPONSE" ]; then
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@@ -4743,7 +4754,7 @@ Host ${NODE}
# Write SSH config to Pulse container
# This will be written to /home/pulse/.ssh/config inside the container
echo "$SSH_CONFIG" | curl -s -X POST "%s/api/system/ssh-config" \
echo "$SSH_CONFIG" | curl -s -X POST "$PULSE_URL/api/system/ssh-config" \
-H "Content-Type: text/plain" \
-H "Authorization: Bearer $AUTH_TOKEN" \
--data-binary @- > /dev/null 2>&1
@@ -4932,7 +4943,7 @@ EOF
CONFIGURED_NODES="$(hostname) ${CONFIGURED_NODES}"
fi
VERIFY_RESPONSE=$(curl -s -X POST "%s/api/system/verify-temperature-ssh" \
VERIFY_RESPONSE=$(curl -s -X POST "$PULSE_URL/api/system/verify-temperature-ssh" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AUTH_TOKEN" \
-d "{\"nodes\": \"$CONFIGURED_NODES\"}" 2>/dev/null || echo "")
@@ -4975,7 +4986,7 @@ if [ "$IS_STANDALONE_NODE" = true ] && [ "$TEMPERATURE_ENABLED" = true ] && [ "$
echo ""
# Try to fetch the proxy's public key from Pulse server
PROXY_KEY_URL="%s/api/system/proxy-public-key"
PROXY_KEY_URL="$PULSE_URL/api/system/proxy-public-key"
echo "Fetching temperature proxy public key..."
PROXY_PUBLIC_KEY=$(curl -s -f "$PROXY_KEY_URL" 2>/dev/null || echo "")
@@ -5035,7 +5046,7 @@ echo ""
# Only show manual setup instructions if auto-registration failed
if [ "$AUTO_REG_SUCCESS" != true ]; then
echo "Manual setup instructions:"
echo " Token ID: pulse-monitor@pam!%s"
echo " Token ID: $PULSE_TOKEN_ID"
if [ "$TOKEN_EXISTED" = true ]; then
echo " Token Value: [Use your existing token or create a new one as shown above]"
elif [ -n "$TOKEN_VALUE" ]; then
@@ -5047,16 +5058,11 @@ if [ "$AUTO_REG_SUCCESS" != true ]; then
echo ""
fi
`, serverName, time.Now().Format("2006-01-02 15:04:05"),
tokenName, pulseURL, pulseURL,
pulseURL, serverHost, pulseURL,
pulseURL, serverHost, pulseURL,
tokenName, pulseURL, pulseURL,
pulseURL, pulseURL,
pulseURL, serverHost, tokenName,
pulseIP,
tokenName, tokenName, tokenName, tokenName, tokenName, tokenName,
authToken, pulseURL, serverHost, tokenName, tokenName, storagePerms,
sshKeys.ProxyPublicKey, sshKeys.SensorsPublicKey, minProxyReadyVersion,
pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, pulseURL, tokenName)
authToken,
storagePerms,
sshKeys.ProxyPublicKey, sshKeys.SensorsPublicKey, minProxyReadyVersion)
} else { // PBS
script = fmt.Sprintf(`#!/bin/bash

View File

@@ -69,6 +69,7 @@ func TestPVESetupScriptArgumentAlignment(t *testing.T) {
script := rr.Body.String()
// Critical alignment checks to prevent fmt.Sprintf argument mismatch bugs
// After refactor: script uses bash variables ($PULSE_URL, $TOKEN_NAME) instead of fmt.Sprintf substitutions
tests := []struct {
name string
contains string
@@ -76,13 +77,13 @@ func TestPVESetupScriptArgumentAlignment(t *testing.T) {
}{
{
name: "repair_installer_url",
contains: `INSTALLER_URL="http://SENTINEL_URL:7656/api/install/install-sensor-proxy.sh"`,
desc: "Repair block INSTALLER_URL should get pulseURL, not authToken",
contains: `INSTALLER_URL="$PULSE_URL/api/install/install-sensor-proxy.sh"`,
desc: "Repair block INSTALLER_URL should use $PULSE_URL bash variable",
},
{
name: "repair_ctid_pulse_server",
contains: `--pulse-server http://SENTINEL_URL:7656`,
desc: "Repair --ctid --pulse-server should get pulseURL, not authToken",
contains: `--pulse-server $PULSE_URL`,
desc: "Repair --ctid --pulse-server should use $PULSE_URL bash variable",
},
{
name: "runtime_auth_token_ssh_config",
@@ -91,8 +92,18 @@ func TestPVESetupScriptArgumentAlignment(t *testing.T) {
},
{
name: "token_id_uses_tokenname",
contains: `Token ID: pulse-monitor@pam!pulse-`,
desc: "Token ID should use tokenName (pulse-*), not pulseURL or authToken",
contains: `Token ID: $PULSE_TOKEN_ID`,
desc: "Token ID should use $PULSE_TOKEN_ID bash variable",
},
{
name: "bash_variables_defined",
contains: `PULSE_URL="http://SENTINEL_URL:7656"`,
desc: "Bash variable PULSE_URL should be defined at top of script",
},
{
name: "token_name_variable_defined",
contains: `TOKEN_NAME="pulse-SENTINEL_URL-`,
desc: "Bash variable TOKEN_NAME should be defined with correct format",
},
}

View File

@@ -173,7 +173,7 @@ func (r *Router) setupRoutes() {
updateHandlers := NewUpdateHandlers(r.updateManager, r.updateHistory)
r.dockerAgentHandlers = NewDockerAgentHandlers(r.monitor, r.wsHub)
r.hostAgentHandlers = NewHostAgentHandlers(r.monitor, r.wsHub)
r.temperatureProxyHandlers = NewTemperatureProxyHandlers(r.persistence)
r.temperatureProxyHandlers = NewTemperatureProxyHandlers(r.config, r.persistence, r.reloadFunc)
// API routes
r.mux.HandleFunc("/api/health", r.handleHealth)
@@ -1208,6 +1208,9 @@ func (r *Router) SetConfig(cfg *config.Config) {
if r.systemSettingsHandler != nil {
r.systemSettingsHandler.SetConfig(r.config)
}
if r.temperatureProxyHandlers != nil {
r.temperatureProxyHandlers.SetConfig(r.config)
}
}
// reloadSystemSettings loads system settings from disk and caches them

View File

@@ -22,7 +22,9 @@ import (
// TemperatureProxyHandlers manages temperature proxy registration
type TemperatureProxyHandlers struct {
config *config.Config
persistence *config.ConfigPersistence
reloadFunc func() error
syncMu sync.RWMutex
syncStatus map[string]proxySyncState
}
@@ -41,13 +43,22 @@ type authorizedNode struct {
}
// NewTemperatureProxyHandlers constructs a new handler set for temperature proxy
func NewTemperatureProxyHandlers(persistence *config.ConfigPersistence) *TemperatureProxyHandlers {
func NewTemperatureProxyHandlers(cfg *config.Config, persistence *config.ConfigPersistence, reloadFunc func() error) *TemperatureProxyHandlers {
return &TemperatureProxyHandlers{
config: cfg,
persistence: persistence,
reloadFunc: reloadFunc,
syncStatus: make(map[string]proxySyncState),
}
}
// SetConfig updates the configuration reference used by the handler.
func (h *TemperatureProxyHandlers) SetConfig(cfg *config.Config) {
if h != nil {
h.config = cfg
}
}
func (h *TemperatureProxyHandlers) recordSync(instance string, refreshSeconds int) {
if h == nil {
return
@@ -278,11 +289,28 @@ func (h *TemperatureProxyHandlers) HandleRegister(w http.ResponseWriter, r *http
nodesConfig.PVEInstances[matchedIndex].TemperatureProxyControlToken = ctrlToken
// Save updated configuration
log.Debug().
Int("matchedIndex", matchedIndex).
Str("saving_url", nodesConfig.PVEInstances[matchedIndex].TemperatureProxyURL).
Bool("saving_has_token", nodesConfig.PVEInstances[matchedIndex].TemperatureProxyToken != "").
Str("instance_name", nodesConfig.PVEInstances[matchedIndex].Name).
Msg("About to save nodes config with proxy registration")
if err := h.persistence.SaveNodesConfig(nodesConfig.PVEInstances, nodesConfig.PBSInstances, nodesConfig.PMGInstances); err != nil {
writeErrorResponse(w, http.StatusInternalServerError, "config_save_failed", "Failed to save configuration", map[string]string{"error": err.Error()})
return
}
// Reload the entire config to ensure all components (router, monitor, handlers) get the fresh config
// This prevents the monitor from later overwriting nodes.enc with stale data
if h.reloadFunc != nil {
if err := h.reloadFunc(); err != nil {
log.Error().Err(err).Msg("Failed to reload config after temperature proxy registration")
// Don't fail the request - the save succeeded, reload is best-effort
} else {
log.Info().Str("instance", matchedInstance.Name).Msg("Config reloaded after temperature proxy registration")
}
}
log.Info().
Str("hostname", hostname).
Str("proxy_url", proxyURL).

View File

@@ -1738,17 +1738,35 @@ if [[ "$HTTP_MODE" == true ]]; then
# Check if port is already in use
PORT_NUMBER="${HTTP_ADDR#:}"
if ss -ltn | grep -q ":${PORT_NUMBER} "; then
print_error "Port ${PORT_NUMBER} is already in use"
print_error ""
print_error "Currently using port ${PORT_NUMBER}:"
ss -ltnp | grep ":${PORT_NUMBER} " || true
print_error ""
print_error "Options:"
print_error " 1. Stop the conflicting service"
print_error " 2. Use a different port: --http-addr :PORT"
print_error " 3. If this is a previous sensor-proxy, uninstall first:"
print_error " $0 --uninstall"
exit 1
# Port is in use - check if it's our own service (refresh scenario)
if systemctl is-active --quiet pulse-sensor-proxy 2>/dev/null; then
# Check if the process using the port is pulse-sensor-proxy
PORT_OWNER=$(ss -ltnp | grep ":${PORT_NUMBER} " | grep -o 'pulse-sensor-pr' || true)
if [[ -n "$PORT_OWNER" ]]; then
# Our service is using the port - this is a refresh, continue
print_info "Existing pulse-sensor-proxy detected on port ${PORT_NUMBER} - will refresh configuration"
else
# Service is active but something else is using the port
print_error "Port ${PORT_NUMBER} is already in use by another process"
print_error ""
print_error "Currently using port ${PORT_NUMBER}:"
ss -ltnp | grep ":${PORT_NUMBER} " || true
exit 1
fi
else
# Service not active, port conflict with something else
print_error "Port ${PORT_NUMBER} is already in use"
print_error ""
print_error "Currently using port ${PORT_NUMBER}:"
ss -ltnp | grep ":${PORT_NUMBER} " || true
print_error ""
print_error "Options:"
print_error " 1. Stop the conflicting service"
print_error " 2. Use a different port: --http-addr :PORT"
print_error " 3. If this is a previous sensor-proxy, uninstall first:"
print_error " $0 --uninstall"
exit 1
fi
fi
# Setup TLS certificates
@@ -1814,12 +1832,19 @@ if [[ "$HTTP_MODE" == true ]]; then
chmod 600 /etc/pulse-sensor-proxy/.http-auth-token
chown pulse-sensor-proxy:pulse-sensor-proxy /etc/pulse-sensor-proxy/.http-auth-token
# Backup config before modifying
# Backup config and token files before modifying
if [[ -f /etc/pulse-sensor-proxy/config.yaml ]]; then
BACKUP_CONFIG="/etc/pulse-sensor-proxy/config.yaml.backup.$(date +%s)"
BACKUP_TIMESTAMP="$(date +%s)"
BACKUP_CONFIG="/etc/pulse-sensor-proxy/config.yaml.backup.$BACKUP_TIMESTAMP"
cp /etc/pulse-sensor-proxy/config.yaml "$BACKUP_CONFIG"
print_info "Config backed up to: $BACKUP_CONFIG"
# Also backup token files so rollback restores matching secrets
if [[ -f /etc/pulse-sensor-proxy/.pulse-control-token ]]; then
BACKUP_CONTROL_TOKEN="/etc/pulse-sensor-proxy/.pulse-control-token.backup.$BACKUP_TIMESTAMP"
cp /etc/pulse-sensor-proxy/.pulse-control-token "$BACKUP_CONTROL_TOKEN"
fi
# Remove any existing HTTP configuration to prevent duplicates
if grep -q "^# HTTP Mode Configuration" /etc/pulse-sensor-proxy/config.yaml; then
print_info "Removing existing HTTP configuration..."
@@ -1841,9 +1866,15 @@ if [[ "$HTTP_MODE" == true ]]; then
print_info "Pulse server detected at: $PULSE_IP"
# Append HTTP configuration to config.yaml
# Configure HTTP mode - check if already configured to avoid duplicates
print_info "Configuring HTTP mode..."
cat >> /etc/pulse-sensor-proxy/config.yaml << EOF
if grep -q "^http_enabled:" /etc/pulse-sensor-proxy/config.yaml 2>/dev/null; then
# HTTP mode already configured - only update the token (avoid duplicates)
sed -i "s|^http_auth_token:.*|http_auth_token: $HTTP_AUTH_TOKEN|" /etc/pulse-sensor-proxy/config.yaml
print_info "Updated HTTP auth token (existing HTTP mode configuration kept)"
else
# Fresh HTTP mode configuration - append to file
cat >> /etc/pulse-sensor-proxy/config.yaml << EOF
# HTTP Mode Configuration (External PVE Host)
http_enabled: true
@@ -1857,6 +1888,7 @@ allowed_source_subnets:
- $PULSE_IP/32
- 127.0.0.1/32
EOF
fi
chown pulse-sensor-proxy:pulse-sensor-proxy /etc/pulse-sensor-proxy/config.yaml
chmod 0644 /etc/pulse-sensor-proxy/config.yaml
@@ -1876,7 +1908,10 @@ fi
# Stop existing service if running (for upgrades)
if systemctl is-active --quiet pulse-sensor-proxy 2>/dev/null; then
print_info "Stopping existing service for upgrade..."
systemctl stop pulse-sensor-proxy
# Tolerate timeout from slow HTTPS shutdown (can take 30s)
systemctl stop pulse-sensor-proxy || true
# Clear any failed state from the stop
systemctl reset-failed pulse-sensor-proxy 2>/dev/null || true
fi
# Install hardened systemd service
@@ -2031,7 +2066,7 @@ if ! systemctl enable pulse-sensor-proxy.service; then
exit 1
fi
if ! systemctl restart pulse-sensor-proxy.service; then
if ! systemctl start pulse-sensor-proxy.service; then
print_error "Failed to start pulse-sensor-proxy service"
print_error ""
@@ -2040,7 +2075,14 @@ if ! systemctl restart pulse-sensor-proxy.service; then
print_warn "Attempting to rollback to previous configuration..."
if cp "$BACKUP_CONFIG" /etc/pulse-sensor-proxy/config.yaml; then
print_info "Config restored from backup"
if systemctl restart pulse-sensor-proxy.service; then
# Also restore token files to match the old config
if [[ -n "$BACKUP_CONTROL_TOKEN" && -f "$BACKUP_CONTROL_TOKEN" ]]; then
cp "$BACKUP_CONTROL_TOKEN" /etc/pulse-sensor-proxy/.pulse-control-token
print_info "Control plane token restored from backup"
fi
# Clear failed state before attempting rollback start
systemctl reset-failed pulse-sensor-proxy 2>/dev/null || true
if systemctl start pulse-sensor-proxy.service; then
print_success "Service restarted with previous configuration"
print_error ""
print_error "HTTP mode installation failed but previous config restored"