diff --git a/copy_and_run.sh b/copy_and_run.sh new file mode 100755 index 0000000..1463137 --- /dev/null +++ b/copy_and_run.sh @@ -0,0 +1,8 @@ +cd / +if [ -d /tmp/pulse-copy ]; then + rm -rf /tmp/pulse-copy +fi +mkdir -p /tmp/pulse-copy +cp -R /opt/pulse /tmp/pulse-copy/repo +cd /tmp/pulse-copy/repo +GOCACHE=/tmp/go-cache HOME=/tmp/pulse-copy/repo go test ./... diff --git a/frontend-modern/src/components/FirstRunSetup.tsx b/frontend-modern/src/components/FirstRunSetup.tsx index 7ad0e67..6a4cfe6 100644 --- a/frontend-modern/src/components/FirstRunSetup.tsx +++ b/frontend-modern/src/components/FirstRunSetup.tsx @@ -26,6 +26,9 @@ export const FirstRunSetup: Component<{ force?: boolean; showLegacyBanner?: bool const [isUnlocked, setIsUnlocked] = createSignal(false); const [bootstrapTokenPath, setBootstrapTokenPath] = createSignal(''); const [isDocker, setIsDocker] = createSignal(false); + const [inContainer, setInContainer] = createSignal(false); + const [lxcCtid, setLxcCtid] = createSignal(''); + const [showAlternatives, setShowAlternatives] = createSignal(false); const applyTheme = (mode: 'system' | 'light' | 'dark') => { if (mode === 'light') { @@ -72,6 +75,8 @@ export const FirstRunSetup: Component<{ force?: boolean; showLegacyBanner?: bool if (data.bootstrapTokenPath) { setBootstrapTokenPath(data.bootstrapTokenPath); setIsDocker(data.isDocker || false); + setInContainer(data.inContainer || false); + setLxcCtid(data.lxcCtid || ''); } } } catch (error) { @@ -317,26 +322,68 @@ IMPORTANT: Keep these credentials secure! } > + {/* Show most relevant command based on detected environment */}
- -
# From Docker host:
- docker exec <container-name> cat {bootstrapTokenPath()} -
# For Kubernetes:
- kubectl exec <pod-name> -- cat {bootstrapTokenPath()} -
# For Proxmox LXC running Docker:
- pct exec <ctid> -- docker exec <container-name> cat {bootstrapTokenPath()} -
# Or enter the LXC container first:
- pct enter <ctid> -
# Then inside LXC:
+ {/* LXC with detected CTID */} + +
# Run from Proxmox host:
+ pct exec {lxcCtid()} -- cat {bootstrapTokenPath()}
- -
# For Proxmox LXC, run from Proxmox host:
- pct enter <ctid> -
# Or directly retrieve:
+ + {/* LXC without CTID */} + +
# Run from Proxmox host:
pct exec <ctid> -- cat {bootstrapTokenPath()} -
# Or from inside the LXC container:
- cat {bootstrapTokenPath()} + + {/* Docker (generic) */} + +
# From Docker host:
+ docker exec <container-name> cat {bootstrapTokenPath()} +
+ + {/* Bare metal / inside container */} + +
# On this host:
+ cat {bootstrapTokenPath()} +
+
+ + {/* Collapsible alternatives */} +
+ + +
+ +
+
# For Kubernetes:
+ kubectl exec <pod-name> -- cat {bootstrapTokenPath()} +
+
+
# For Proxmox LXC running Docker:
+ pct exec <ctid> -- docker exec <container-name> cat {bootstrapTokenPath()} +
+
+ +
+
# Enter container then run:
+ pct enter {lxcCtid() || ''} +
+ cat {bootstrapTokenPath()} +
+
+
+
# Direct file access:
+ cat {bootstrapTokenPath()} +
+
+
diff --git a/internal/api/router.go b/internal/api/router.go index 707fbaf..27c0bf8 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -28,6 +28,7 @@ import ( "github.com/rcourtman/pulse-go-rewrite/internal/dockeragent" "github.com/rcourtman/pulse-go-rewrite/internal/models" "github.com/rcourtman/pulse-go-rewrite/internal/monitoring" + "github.com/rcourtman/pulse-go-rewrite/internal/system" "github.com/rcourtman/pulse-go-rewrite/internal/tempproxy" "github.com/rcourtman/pulse-go-rewrite/internal/updates" "github.com/rcourtman/pulse-go-rewrite/internal/utils" @@ -485,6 +486,10 @@ func (r *Router) setupRoutes() { if r.bootstrapTokenHash != "" { status["bootstrapTokenPath"] = r.bootstrapTokenPath status["isDocker"] = os.Getenv("PULSE_DOCKER") == "true" + status["inContainer"] = system.InContainer() + if ctid := system.DetectLXCCTID(); ctid != "" { + status["lxcCtid"] = ctid + } } if r.config.DisableAuthEnvDetected { diff --git a/internal/system/container.go b/internal/system/container.go index 23ff3f1..cf1a644 100644 --- a/internal/system/container.go +++ b/internal/system/container.go @@ -56,6 +56,58 @@ func InContainer() bool { return false } +// DetectLXCCTID attempts to detect the Proxmox LXC container ID. +// Returns empty string if not in an LXC container or CTID cannot be determined. +func DetectLXCCTID() string { + // Method 1: Parse /proc/1/cgroup for LXC container ID + if data, err := os.ReadFile("/proc/1/cgroup"); err == nil { + lines := strings.Split(string(data), "\n") + for _, line := range lines { + // Look for patterns like: 0::/lxc/123 or 0::/lxc.payload.123 + if strings.Contains(line, "/lxc") || strings.Contains(line, "lxc.payload") { + // Extract digits after lxc/ or lxc.payload. + parts := strings.Split(line, "/") + for _, part := range parts { + part = strings.TrimPrefix(part, "lxc.payload.") + part = strings.TrimPrefix(part, "lxc.") + if isNumeric(part) { + return part + } + } + } + // Also check for machine-lxc-NNN pattern + if strings.Contains(line, "machine-lxc") { + fields := strings.Split(line, "-") + for _, field := range fields { + if isNumeric(field) { + return field + } + } + } + } + } + + // Method 2: Check hostname (some LXC containers use CTID as hostname) + if hostname, err := os.Hostname(); err == nil && isNumeric(hostname) { + return hostname + } + + return "" +} + +func isNumeric(s string) bool { + s = strings.TrimSpace(s) + if s == "" { + return false + } + for _, c := range s { + if c < '0' || c > '9' { + return false + } + } + return true +} + func isTruthy(value string) bool { switch strings.ToLower(strings.TrimSpace(value)) { case "1", "true", "t", "yes", "y", "on": diff --git a/work.sh b/work.sh new file mode 100644 index 0000000..4e331a1 --- /dev/null +++ b/work.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd /opt/pulse +git checkout cleanup-auto-uninstall