From 639635a84b6cf0985ab531fd7afaa8c22c1b20e5 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Sat, 15 Nov 2025 10:45:00 +0000 Subject: [PATCH] Add Docker container name auto-detection to bootstrap UI - Added DetectDockerContainerName() to detect container name from hostname - Extended /api/security/status to expose dockerContainerName field - Updated FirstRunSetup to show actual container name when detected: * Before: 'docker exec cat /data/.bootstrap_token' * After: 'docker exec pulse cat /data/.bootstrap_token' This reduces friction for users - no need to look up the container name. Works when Docker container is named (--name flag), falls back to placeholder for auto-generated container IDs. --- .../src/components/FirstRunSetup.tsx | 6 ++-- internal/api/router.go | 3 ++ internal/system/container.go | 31 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/frontend-modern/src/components/FirstRunSetup.tsx b/frontend-modern/src/components/FirstRunSetup.tsx index 6a4cfe6..93b0a8a 100644 --- a/frontend-modern/src/components/FirstRunSetup.tsx +++ b/frontend-modern/src/components/FirstRunSetup.tsx @@ -28,6 +28,7 @@ export const FirstRunSetup: Component<{ force?: boolean; showLegacyBanner?: bool const [isDocker, setIsDocker] = createSignal(false); const [inContainer, setInContainer] = createSignal(false); const [lxcCtid, setLxcCtid] = createSignal(''); + const [dockerContainerName, setDockerContainerName] = createSignal(''); const [showAlternatives, setShowAlternatives] = createSignal(false); const applyTheme = (mode: 'system' | 'light' | 'dark') => { @@ -77,6 +78,7 @@ export const FirstRunSetup: Component<{ force?: boolean; showLegacyBanner?: bool setIsDocker(data.isDocker || false); setInContainer(data.inContainer || false); setLxcCtid(data.lxcCtid || ''); + setDockerContainerName(data.dockerContainerName || ''); } } } catch (error) { @@ -336,10 +338,10 @@ IMPORTANT: Keep these credentials secure! pct exec <ctid> -- cat {bootstrapTokenPath()} - {/* Docker (generic) */} + {/* Docker (with detected name or placeholder) */}
# From Docker host:
- docker exec <container-name> cat {bootstrapTokenPath()} + docker exec {dockerContainerName() || ''} cat {bootstrapTokenPath()}
{/* Bare metal / inside container */} diff --git a/internal/api/router.go b/internal/api/router.go index 27c0bf8..db07f3c 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -490,6 +490,9 @@ func (r *Router) setupRoutes() { if ctid := system.DetectLXCCTID(); ctid != "" { status["lxcCtid"] = ctid } + if containerName := system.DetectDockerContainerName(); containerName != "" { + status["dockerContainerName"] = containerName + } } if r.config.DisableAuthEnvDetected { diff --git a/internal/system/container.go b/internal/system/container.go index cf1a644..96bd681 100644 --- a/internal/system/container.go +++ b/internal/system/container.go @@ -56,6 +56,37 @@ func InContainer() bool { return false } +// DetectDockerContainerName attempts to detect the Docker container name. +// Returns empty string if not in Docker or name cannot be determined. +func DetectDockerContainerName() string { + // Method 1: Check hostname (Docker uses container ID or name as hostname) + if hostname, err := os.Hostname(); err == nil && hostname != "" { + // Docker hostnames are either short container ID (12 chars) or custom name + // If it looks like a container ID (hex), skip it - user needs to use name + if !isHexString(hostname) || len(hostname) > 12 { + return hostname + } + } + + // Method 2: Try reading from /proc/self/cgroup + if data, err := os.ReadFile("/proc/self/cgroup"); err == nil { + // Look for patterns like: 0::/docker/ + // But we can't get name from cgroup, only ID + _ = data // placeholder for future enhancement + } + + return "" +} + +func isHexString(s string) bool { + for _, c := range s { + if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { + return false + } + } + return true +} + // 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 {