From 546481bc158a59841bab4f011912cda9f7db2a64 Mon Sep 17 00:00:00 2001 From: Dorian Date: Fri, 27 Mar 2026 11:12:31 +0000 Subject: [PATCH] fix: bundle FileBrowser, auto-login tty1, boot/auth debug logging - ISO build: configure insecure registry for root podman so FileBrowser image can be pulled during build (was failing with HTTPS error) - Auto-login on tty1 so no password prompt on console - RootRedirect: persistent debug logging to sessionStorage (view in DevTools > Application > Session Storage > archipelago_boot_log) - Logs: health check, onboarding state, routing decisions, 401 handling Co-Authored-By: Claude Opus 4.6 (1M context) --- image-recipe/build-auto-installer-iso.sh | 18 +++++++++ neode-ui/src/views/RootRedirect.vue | 48 +++++++++++++++--------- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/image-recipe/build-auto-installer-iso.sh b/image-recipe/build-auto-installer-iso.sh index 3ad95385..f008afd5 100755 --- a/image-recipe/build-auto-installer-iso.sh +++ b/image-recipe/build-auto-installer-iso.sh @@ -179,6 +179,16 @@ check_tools() { fi echo "Using container runtime: $CONTAINER_CMD" + + # Ensure insecure registry config for Archipelago app registry (HTTP) + if [ "$CONTAINER_CMD" = "podman" ]; then + mkdir -p /etc/containers/registries.conf.d + cat > /etc/containers/registries.conf.d/archipelago.conf <<'REGCONF' +[[registry]] +location = "80.71.235.15:3000" +insecure = true +REGCONF + fi } check_tools @@ -1938,6 +1948,14 @@ chroot /mnt/target systemctl enable archipelago-load-images.service 2>/dev/null chroot /mnt/target systemctl enable archipelago-setup-tor.service 2>/dev/null || true chroot /mnt/target systemctl enable archipelago-first-boot-containers.service 2>/dev/null || true chroot /mnt/target systemctl enable archipelago-kiosk.service 2>/dev/null || true + +# Auto-login on tty1 — no password prompt on console +mkdir -p /mnt/target/etc/systemd/system/getty@tty1.service.d +cat > /mnt/target/etc/systemd/system/getty@tty1.service.d/autologin.conf <<'AUTOLOGIN' +[Service] +ExecStart= +ExecStart=-/sbin/agetty --autologin archipelago --noclear %I $TERM +AUTOLOGIN chroot /mnt/target systemctl enable archipelago-diagnostics.service 2>/dev/null || true # Install first-boot diagnostic script — runs once after first boot and logs system state diff --git a/neode-ui/src/views/RootRedirect.vue b/neode-ui/src/views/RootRedirect.vue index 12cec31d..2cdc9c43 100644 --- a/neode-ui/src/views/RootRedirect.vue +++ b/neode-ui/src/views/RootRedirect.vue @@ -21,6 +21,14 @@ import BootScreen from '@/components/BootScreen.vue' const router = useRouter() const showBootScreen = ref(false) +function log(msg: string, data?: unknown) { + const ts = new Date().toISOString() + const entry = `[RootRedirect ${ts}] ${msg}` + (data !== undefined ? ` ${JSON.stringify(data)}` : '') + console.log(entry) + const prev = sessionStorage.getItem('archipelago_boot_log') || '' + sessionStorage.setItem('archipelago_boot_log', prev + entry + '\n') +} + async function quickHealthCheck(): Promise { try { const ac = new AbortController() @@ -32,8 +40,11 @@ async function quickHealthCheck(): Promise { signal: ac.signal, }) clearTimeout(t) - return res.status !== 502 && res.status !== 503 - } catch { + const ok = res.status !== 502 && res.status !== 503 + log('healthCheck', { status: res.status, ok }) + return ok + } catch (e) { + log('healthCheck FAILED', { error: String(e) }) return false } } @@ -44,24 +55,27 @@ async function checkOnboarded(): Promise { isOnboardingComplete(), new Promise((resolve) => setTimeout(() => resolve(false), 3000)), ]) + log('checkOnboarded', { result }) return result - } catch { - // Backend unreachable — fall back to localStorage only as last resort - return localStorage.getItem('neode_onboarding_complete') === '1' + } catch (e) { + const fallback = localStorage.getItem('neode_onboarding_complete') === '1' + log('checkOnboarded ERROR, localStorage fallback', { error: String(e), fallback }) + return fallback } } async function proceedToApp() { const devMode = import.meta.env.VITE_DEV_MODE if (devMode === 'setup' || devMode === 'existing') { + log('proceedToApp devMode', { devMode }) router.replace('/login').catch(() => {}) return } - // Always check backend for authoritative onboarding state - // (localStorage can be stale from a previous install on the same IP) const onboarded = await checkOnboarded() - router.replace(onboarded ? '/login' : '/onboarding/intro').catch(() => {}) + const dest = onboarded ? '/login' : '/onboarding/intro' + log('proceedToApp navigating', { onboarded, dest }) + router.replace(dest).catch(() => {}) } function onServerReady() { @@ -74,44 +88,42 @@ function onServerReady() { onMounted(async () => { const devMode = import.meta.env.VITE_DEV_MODE + log('mounted', { devMode, from_boot: sessionStorage.getItem('archipelago_from_boot'), from_splash: sessionStorage.getItem('archipelago_from_splash') }) - // Coming back from boot screen — let App.vue's SplashScreen take over if (sessionStorage.getItem('archipelago_from_boot') === '1') { + log('from_boot=1, deferring to SplashScreen') return } - // Splash already completed this session — go to app if (sessionStorage.getItem('archipelago_from_splash') === '1') { + log('from_splash=1, proceedToApp') proceedToApp() return } - // Standard dev modes if (devMode === 'setup' || devMode === 'existing') { + log('devMode shortcut', { devMode }) proceedToApp() return } - // Boot dev mode — always show boot screen (first load only) if (devMode === 'boot') { + log('devMode=boot, showing boot screen') showBootScreen.value = true return } - // Production: check server health const isUp = await quickHealthCheck() + log('production flow', { isUp }) if (isUp) { - // Server is up — check if onboarding is complete const onboarded = await checkOnboarded() if (onboarded) { - // Returning user, server is up — go straight to login + log('server up + onboarded → proceedToApp') proceedToApp() return } - // First boot: server is up but onboarding not done yet. - // Show boot animation anyway — it lets services fully warm up - // (containers, DID resolver, etc.) before onboarding starts. + log('server up + NOT onboarded → boot screen') } // Server not ready OR first boot — show boot screen