From d26599e505fd3671c2b0dc70fed4ed9e8b92f996 Mon Sep 17 00:00:00 2001 From: Pulse Monitor Date: Mon, 18 Aug 2025 21:57:40 +0000 Subject: [PATCH] chore: reorganize repository structure for better maintainability - Move development scripts to scripts/ directory (dev.sh, hot-dev.sh, build.sh, etc.) - Move UPGRADE_NOTICE to docs/ directory - Remove empty 2025-08-14 file - Update all references to moved scripts in documentation --- 2025-08-14 | 0 README.md | 2 +- .../UPGRADE_NOTICE_v4.3.9.md | 0 internal/api/auth.go | 43 +++++++++++++++++++ internal/monitoring/monitor.go | 42 +++++------------- build-release.sh => scripts/build-release.sh | 0 build.sh => scripts/build.sh | 0 dev-proxy.sh => scripts/dev-proxy.sh | 0 dev.sh => scripts/dev.sh | 0 hot-dev.sh => scripts/hot-dev.sh | 0 10 files changed, 55 insertions(+), 32 deletions(-) delete mode 100644 2025-08-14 rename UPGRADE_NOTICE_v4.3.9.md => docs/UPGRADE_NOTICE_v4.3.9.md (100%) rename build-release.sh => scripts/build-release.sh (100%) rename build.sh => scripts/build.sh (100%) rename dev-proxy.sh => scripts/dev-proxy.sh (100%) rename dev.sh => scripts/dev.sh (100%) rename hot-dev.sh => scripts/hot-dev.sh (100%) diff --git a/2025-08-14 b/2025-08-14 deleted file mode 100644 index e69de29bb..000000000 diff --git a/README.md b/README.md index 058ef44f3..e2474150d 100644 --- a/README.md +++ b/README.md @@ -404,7 +404,7 @@ journalctl -u pulse -f ### Quick Start - Hot Reload (Recommended) ```bash # Best development experience with instant frontend updates -./hot-dev.sh +./scripts/hot-dev.sh # Frontend: http://localhost:5173 (hot reload) # Backend: http://localhost:7655 ``` diff --git a/UPGRADE_NOTICE_v4.3.9.md b/docs/UPGRADE_NOTICE_v4.3.9.md similarity index 100% rename from UPGRADE_NOTICE_v4.3.9.md rename to docs/UPGRADE_NOTICE_v4.3.9.md diff --git a/internal/api/auth.go b/internal/api/auth.go index c8f3cb8ef..51638d5b9 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -46,6 +46,18 @@ func getCookieSettings(r *http.Request) (secure bool, sameSite http.SameSite) { isProxied := detectProxy(r) isSecure := isConnectionSecure(r) + // Debug logging for Cloudflare tunnel issues + if isProxied { + log.Debug(). + Bool("proxied", isProxied). + Bool("secure", isSecure). + Str("cf_ray", r.Header.Get("CF-Ray")). + Str("cf_connecting_ip", r.Header.Get("CF-Connecting-IP")). + Str("x_forwarded_for", r.Header.Get("X-Forwarded-For")). + Str("x_forwarded_proto", r.Header.Get("X-Forwarded-Proto")). + Msg("Proxy/tunnel detected - adjusting cookie settings") + } + // Default to Lax for better compatibility sameSitePolicy := http.SameSiteLaxMode @@ -209,7 +221,20 @@ func CheckAuth(cfg *config.Config, w http.ResponseWriter, r *http.Request) bool if cookie, err := r.Cookie("pulse_session"); err == nil && cookie.Value != "" { if ValidateSession(cookie.Value) { return true + } else { + // Debug logging for failed session validation + log.Debug(). + Str("session_token", cookie.Value[:8]+"..."). + Str("path", r.URL.Path). + Msg("Session validation failed - token not found or expired") } + } else if err != nil { + // Debug logging when no session cookie found + log.Debug(). + Err(err). + Str("path", r.URL.Path). + Bool("has_cf_headers", r.Header.Get("CF-Ray") != ""). + Msg("No session cookie found") } // Check basic auth @@ -298,6 +323,24 @@ func CheckAuth(cfg *config.Config, w http.ResponseWriter, r *http.Request) bool // Get appropriate cookie settings based on proxy detection isSecure, sameSitePolicy := getCookieSettings(r) + // Debug logging for Cloudflare tunnel issues + sameSiteName := "Default" + switch sameSitePolicy { + case http.SameSiteNoneMode: + sameSiteName = "None" + case http.SameSiteLaxMode: + sameSiteName = "Lax" + case http.SameSiteStrictMode: + sameSiteName = "Strict" + } + + log.Debug(). + Bool("secure", isSecure). + Str("same_site", sameSiteName). + Str("token", token[:8]+"..."). + Str("remote_addr", r.RemoteAddr). + Msg("Setting session cookie after successful login") + // Set session cookie http.SetCookie(w, &http.Cookie{ Name: "pulse_session", diff --git a/internal/monitoring/monitor.go b/internal/monitoring/monitor.go index ced354b94..5ff4b75a8 100644 --- a/internal/monitoring/monitor.go +++ b/internal/monitoring/monitor.go @@ -796,9 +796,16 @@ func (m *Monitor) pollPVEInstance(ctx context.Context, instanceName string, clie case <-ctx.Done(): return default: - // Try to use efficient cluster/resources endpoint - if !m.pollVMsAndContainersEfficient(ctx, instanceName, client) { - // Fall back to old method if cluster/resources fails + // Only try cluster endpoints if this is configured as a cluster + // This prevents syslog spam on non-clustered nodes from certificate checks + useClusterEndpoint := false + if instanceCfg.IsCluster { + // Try to use efficient cluster/resources endpoint + useClusterEndpoint = m.pollVMsAndContainersEfficient(ctx, instanceName, client) + } + + if !useClusterEndpoint { + // Use traditional polling for non-clusters or if cluster endpoint fails // Use WithNodes versions to avoid duplicate GetNodes calls if instanceCfg.MonitorVMs { m.pollVMsWithNodes(ctx, instanceName, client, nodes) @@ -855,35 +862,8 @@ func (m *Monitor) pollPVEInstance(ctx context.Context, instanceName string, clie } // pollVMsAndContainersEfficient uses the cluster/resources endpoint to get all VMs and containers in one call +// This should only be called for instances configured as clusters func (m *Monitor) pollVMsAndContainersEfficient(ctx context.Context, instanceName string, client PVEClientInterface) bool { - // Get instance config to check if this is configured as a cluster - var instanceCfg *config.PVEInstance - for _, cfg := range m.config.PVEInstances { - if cfg.Name == instanceName { - instanceCfg = &cfg - break - } - } - - // If not configured as a cluster, don't even try cluster endpoints - if instanceCfg == nil || !instanceCfg.IsCluster { - log.Debug().Str("instance", instanceName).Bool("isCluster", instanceCfg != nil && instanceCfg.IsCluster).Msg("Instance not configured as cluster, using traditional polling") - return false - } - - // For cluster configurations, verify it's still a cluster - // This check is cached in the configuration, so we avoid repeated API calls - isCluster, err := client.IsClusterMember(ctx) - if err != nil { - log.Debug().Err(err).Str("instance", instanceName).Msg("Could not verify cluster membership, falling back to traditional polling") - return false - } - - if !isCluster { - log.Debug().Str("instance", instanceName).Msg("Configured as cluster but node reports not in a cluster, using traditional polling") - return false - } - log.Info().Str("instance", instanceName).Msg("Polling VMs and containers using cluster/resources") // Get all resources in a single API call diff --git a/build-release.sh b/scripts/build-release.sh similarity index 100% rename from build-release.sh rename to scripts/build-release.sh diff --git a/build.sh b/scripts/build.sh similarity index 100% rename from build.sh rename to scripts/build.sh diff --git a/dev-proxy.sh b/scripts/dev-proxy.sh similarity index 100% rename from dev-proxy.sh rename to scripts/dev-proxy.sh diff --git a/dev.sh b/scripts/dev.sh similarity index 100% rename from dev.sh rename to scripts/dev.sh diff --git a/hot-dev.sh b/scripts/hot-dev.sh similarity index 100% rename from hot-dev.sh rename to scripts/hot-dev.sh