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) <noreply@anthropic.com>
This commit is contained in:
parent
ab48266353
commit
1ddf90ae50
@ -179,6 +179,16 @@ check_tools() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Using container runtime: $CONTAINER_CMD"
|
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
|
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-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-first-boot-containers.service 2>/dev/null || true
|
||||||
chroot /mnt/target systemctl enable archipelago-kiosk.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
|
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
|
# Install first-boot diagnostic script — runs once after first boot and logs system state
|
||||||
|
|||||||
@ -21,6 +21,14 @@ import BootScreen from '@/components/BootScreen.vue'
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const showBootScreen = ref(false)
|
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<boolean> {
|
async function quickHealthCheck(): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const ac = new AbortController()
|
const ac = new AbortController()
|
||||||
@ -32,8 +40,11 @@ async function quickHealthCheck(): Promise<boolean> {
|
|||||||
signal: ac.signal,
|
signal: ac.signal,
|
||||||
})
|
})
|
||||||
clearTimeout(t)
|
clearTimeout(t)
|
||||||
return res.status !== 502 && res.status !== 503
|
const ok = res.status !== 502 && res.status !== 503
|
||||||
} catch {
|
log('healthCheck', { status: res.status, ok })
|
||||||
|
return ok
|
||||||
|
} catch (e) {
|
||||||
|
log('healthCheck FAILED', { error: String(e) })
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,24 +55,27 @@ async function checkOnboarded(): Promise<boolean> {
|
|||||||
isOnboardingComplete(),
|
isOnboardingComplete(),
|
||||||
new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 3000)),
|
new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 3000)),
|
||||||
])
|
])
|
||||||
|
log('checkOnboarded', { result })
|
||||||
return result
|
return result
|
||||||
} catch {
|
} catch (e) {
|
||||||
// Backend unreachable — fall back to localStorage only as last resort
|
const fallback = localStorage.getItem('neode_onboarding_complete') === '1'
|
||||||
return localStorage.getItem('neode_onboarding_complete') === '1'
|
log('checkOnboarded ERROR, localStorage fallback', { error: String(e), fallback })
|
||||||
|
return fallback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function proceedToApp() {
|
async function proceedToApp() {
|
||||||
const devMode = import.meta.env.VITE_DEV_MODE
|
const devMode = import.meta.env.VITE_DEV_MODE
|
||||||
if (devMode === 'setup' || devMode === 'existing') {
|
if (devMode === 'setup' || devMode === 'existing') {
|
||||||
|
log('proceedToApp devMode', { devMode })
|
||||||
router.replace('/login').catch(() => {})
|
router.replace('/login').catch(() => {})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always check backend for authoritative onboarding state
|
|
||||||
// (localStorage can be stale from a previous install on the same IP)
|
|
||||||
const onboarded = await checkOnboarded()
|
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() {
|
function onServerReady() {
|
||||||
@ -74,44 +88,42 @@ function onServerReady() {
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const devMode = import.meta.env.VITE_DEV_MODE
|
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') {
|
if (sessionStorage.getItem('archipelago_from_boot') === '1') {
|
||||||
|
log('from_boot=1, deferring to SplashScreen')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Splash already completed this session — go to app
|
|
||||||
if (sessionStorage.getItem('archipelago_from_splash') === '1') {
|
if (sessionStorage.getItem('archipelago_from_splash') === '1') {
|
||||||
|
log('from_splash=1, proceedToApp')
|
||||||
proceedToApp()
|
proceedToApp()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standard dev modes
|
|
||||||
if (devMode === 'setup' || devMode === 'existing') {
|
if (devMode === 'setup' || devMode === 'existing') {
|
||||||
|
log('devMode shortcut', { devMode })
|
||||||
proceedToApp()
|
proceedToApp()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boot dev mode — always show boot screen (first load only)
|
|
||||||
if (devMode === 'boot') {
|
if (devMode === 'boot') {
|
||||||
|
log('devMode=boot, showing boot screen')
|
||||||
showBootScreen.value = true
|
showBootScreen.value = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Production: check server health
|
|
||||||
const isUp = await quickHealthCheck()
|
const isUp = await quickHealthCheck()
|
||||||
|
log('production flow', { isUp })
|
||||||
|
|
||||||
if (isUp) {
|
if (isUp) {
|
||||||
// Server is up — check if onboarding is complete
|
|
||||||
const onboarded = await checkOnboarded()
|
const onboarded = await checkOnboarded()
|
||||||
if (onboarded) {
|
if (onboarded) {
|
||||||
// Returning user, server is up — go straight to login
|
log('server up + onboarded → proceedToApp')
|
||||||
proceedToApp()
|
proceedToApp()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// First boot: server is up but onboarding not done yet.
|
log('server up + NOT onboarded → boot screen')
|
||||||
// Show boot animation anyway — it lets services fully warm up
|
|
||||||
// (containers, DID resolver, etc.) before onboarding starts.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server not ready OR first boot — show boot screen
|
// Server not ready OR first boot — show boot screen
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user