fix: WebSocket race conditions, Vue error handler, remove sudo podman, add container health checks
- F1: Guard connectWebSocket against concurrent calls with isWsConnecting flag - F2: Serialize mesh send operations with sendQueue to prevent fetchMessages races - F3: Add global Vue error handler with toast notification - S1: Replace sudo podman with podman across all scripts (rootless Podman) - S2: Add health-cmd to all 40 container run commands in first-boot-containers.sh Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,7 +38,9 @@ case "$ARCH" in
|
||||
LINUX_IMAGE_PKG="linux-image-amd64"
|
||||
GRUB_EFI_PKG="grub-efi-amd64"
|
||||
GRUB_EFI_SIGNED_PKG="grub-efi-amd64-signed"
|
||||
GRUB_PC_PKG="grub-pc-bin"
|
||||
GRUB_TARGET="x86_64-efi"
|
||||
GRUB_BIOS_TARGET="i386-pc"
|
||||
CONTAINER_PLATFORM="linux/amd64"
|
||||
LIB_DIR="${LIB_DIR}"
|
||||
;;
|
||||
@@ -48,7 +50,9 @@ case "$ARCH" in
|
||||
LINUX_IMAGE_PKG="linux-image-arm64"
|
||||
GRUB_EFI_PKG="grub-efi-arm64"
|
||||
GRUB_EFI_SIGNED_PKG="grub-efi-arm64-signed"
|
||||
GRUB_PC_PKG=""
|
||||
GRUB_TARGET="arm64-efi"
|
||||
GRUB_BIOS_TARGET=""
|
||||
CONTAINER_PLATFORM="linux/arm64"
|
||||
LIB_DIR="aarch64-linux-gnu"
|
||||
;;
|
||||
@@ -179,7 +183,7 @@ RUN apt-get update && apt-get install -y \
|
||||
${LINUX_IMAGE_PKG} \
|
||||
${GRUB_EFI_PKG} \
|
||||
${GRUB_EFI_SIGNED_PKG} \
|
||||
shim-signed \
|
||||
${GRUB_PC_PKG} shim-signed \
|
||||
systemd \
|
||||
systemd-sysv \
|
||||
dbus \
|
||||
@@ -576,7 +580,7 @@ if [ -n "$DEV_SERVER" ] && [ "$DEV_SERVER" != "localhost" ] && [ "$DEV_SERVER" !
|
||||
# Patterns match against `podman images` repository names (not container names)
|
||||
CAPTURE_PATTERNS="bitcoin-ui bitcoinknots lnd lnd-ui electrs-ui filebrowser mempool backend frontend electrs tailscale homeassistant home-assistant btcpayserver nbxplorer postgres alpine-tor nostr-rs-relay strfry fedimintd gatewayd dwn-server grafana uptime-kuma jellyfin vaultwarden searxng mariadb valkey nginx-alpine portainer photoprism nextcloud nginx-proxy-manager immich onlyoffice adguard penpot"
|
||||
REMOTE_TMP="/tmp/archipelago-image-capture-$$"
|
||||
SAVED_LIST=$(ssh "$DEV_SERVER" "mkdir -p $REMOTE_TMP && for p in $CAPTURE_PATTERNS; do img=\$(sudo podman images --format '{{.Repository}}:{{.Tag}}' 2>/dev/null | grep -i \"\$p\" | head -1); [ -n \"\$img\" ] && sudo podman save -o \"$REMOTE_TMP/\$p.tar\" \"\$img\" 2>/dev/null && echo \"\$p\"; done" 2>/dev/null) || true
|
||||
SAVED_LIST=$(ssh "$DEV_SERVER" "mkdir -p $REMOTE_TMP && for p in $CAPTURE_PATTERNS; do img=\$(podman images --format '{{.Repository}}:{{.Tag}}' 2>/dev/null | grep -i \"\$p\" | head -1); [ -n \"\$img\" ] && podman save -o \"$REMOTE_TMP/\$p.tar\" \"\$img\" 2>/dev/null && echo \"\$p\"; done" 2>/dev/null) || true
|
||||
for p in $SAVED_LIST; do
|
||||
if [ -n "$p" ] && scp "$DEV_SERVER:$REMOTE_TMP/$p.tar" "$IMAGES_DIR/$p.tar" 2>/dev/null; then
|
||||
echo " ✅ Captured from server: $p.tar"
|
||||
@@ -899,6 +903,20 @@ cat > "$ARCH_DIR/auto-install.sh" <<'INSTALLER_SCRIPT'
|
||||
|
||||
set -e
|
||||
|
||||
# Detect architecture at install time
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64)
|
||||
ARCH="x86_64"
|
||||
GRUB_TARGET="x86_64-efi"
|
||||
GRUB_BIOS_TARGET="i386-pc"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
ARCH="arm64"
|
||||
GRUB_TARGET="arm64-efi"
|
||||
GRUB_BIOS_TARGET=""
|
||||
;;
|
||||
esac
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
@@ -1032,22 +1050,29 @@ echo ""
|
||||
umount ${TARGET_DISK}* 2>/dev/null || true
|
||||
umount ${TARGET_DISK}p* 2>/dev/null || true
|
||||
|
||||
# Create partition table
|
||||
# Create partition table — dual BIOS+UEFI boot support
|
||||
echo " [1/6] Creating partitions..."
|
||||
parted -s "$TARGET_DISK" mklabel gpt
|
||||
parted -s "$TARGET_DISK" mkpart primary fat32 1MiB 513MiB
|
||||
parted -s "$TARGET_DISK" set 1 esp on
|
||||
parted -s "$TARGET_DISK" mkpart primary ext4 513MiB 100%
|
||||
# Partition 1: 1MB BIOS boot partition (for legacy BIOS GRUB on GPT disks)
|
||||
parted -s "$TARGET_DISK" mkpart bios_boot 1MiB 2MiB
|
||||
parted -s "$TARGET_DISK" set 1 bios_grub on
|
||||
# Partition 2: 512MB EFI System Partition (for UEFI boot)
|
||||
parted -s "$TARGET_DISK" mkpart efi fat32 2MiB 514MiB
|
||||
parted -s "$TARGET_DISK" set 2 esp on
|
||||
# Partition 3: Root filesystem (remaining space)
|
||||
parted -s "$TARGET_DISK" mkpart root ext4 514MiB 100%
|
||||
|
||||
sleep 2
|
||||
|
||||
# Determine partition names
|
||||
if [[ "$TARGET_DISK" == *nvme* ]]; then
|
||||
EFI_PART="${TARGET_DISK}p1"
|
||||
ROOT_PART="${TARGET_DISK}p2"
|
||||
BIOS_PART="${TARGET_DISK}p1"
|
||||
EFI_PART="${TARGET_DISK}p2"
|
||||
ROOT_PART="${TARGET_DISK}p3"
|
||||
else
|
||||
EFI_PART="${TARGET_DISK}1"
|
||||
ROOT_PART="${TARGET_DISK}2"
|
||||
BIOS_PART="${TARGET_DISK}1"
|
||||
EFI_PART="${TARGET_DISK}2"
|
||||
ROOT_PART="${TARGET_DISK}3"
|
||||
fi
|
||||
|
||||
# Format partitions
|
||||
@@ -1157,6 +1182,10 @@ chown -R 1000:1000 /mnt/target/var/lib/archipelago 2>/dev/null || true
|
||||
# Create welcome profile (nginx serves on port 80)
|
||||
cat > /mnt/target/etc/profile.d/archipelago.sh <<'PROFILE'
|
||||
#!/bin/bash
|
||||
# Ensure /sbin and /usr/sbin are in PATH (needed for reboot, shutdown, etc.)
|
||||
case ":$PATH:" in
|
||||
*:/sbin:*) ;; *) export PATH="$PATH:/sbin:/usr/sbin" ;;
|
||||
esac
|
||||
if [ -t 0 ] && [ -z "$ARCHIPELAGO_WELCOMED" ]; then
|
||||
export ARCHIPELAGO_WELCOMED=1
|
||||
IP=$(hostname -I 2>/dev/null | awk '{print $1}')
|
||||
@@ -1322,9 +1351,71 @@ if grep -q "^archipelago:[!*]" /mnt/target/etc/shadow 2>/dev/null; then
|
||||
fi
|
||||
echo " Passwords set for archipelago and root users"
|
||||
|
||||
chroot /mnt/target grub-install --target=${GRUB_TARGET} --efi-directory=/boot/efi --bootloader-id=archipelago --removable 2>/dev/null || \
|
||||
chroot /mnt/target grub-install --target=${GRUB_TARGET} --efi-directory=/boot/efi --bootloader-id=archipelago 2>/dev/null || \
|
||||
echo " Warning: GRUB install had issues, trying alternative..."
|
||||
# UEFI boot: install to fallback path (/EFI/BOOT/BOOTX64.EFI) for maximum compatibility
|
||||
echo " Installing UEFI bootloader..."
|
||||
if chroot /mnt/target grub-install --target=${GRUB_TARGET} --efi-directory=/boot/efi --bootloader-id=archipelago --removable; then
|
||||
echo " ✅ UEFI bootloader installed (removable/fallback path)"
|
||||
else
|
||||
echo " ⚠️ UEFI removable install failed, trying standard..."
|
||||
if chroot /mnt/target grub-install --target=${GRUB_TARGET} --efi-directory=/boot/efi --bootloader-id=archipelago; then
|
||||
echo " ✅ UEFI bootloader installed (standard)"
|
||||
else
|
||||
echo " ❌ UEFI bootloader installation failed"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Secure Boot chain: replace unsigned GRUB with signed shim+grub for Secure Boot compatibility
|
||||
# Framework laptops and other Secure Boot-enabled machines need this chain:
|
||||
# BOOTX64.EFI (shimx64, Microsoft-signed) → grubx64.efi (Debian-signed) → kernel
|
||||
echo " Setting up Secure Boot chain..."
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
SHIM_SRC="/mnt/target/usr/lib/shim/shimx64.efi.signed"
|
||||
GRUB_SIGNED_SRC="/mnt/target/usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed"
|
||||
EFI_BOOT_BINARY="BOOTX64.EFI"
|
||||
GRUB_EFI_BINARY="grubx64.efi"
|
||||
SHIM_EFI_BINARY="shimx64.efi"
|
||||
else
|
||||
SHIM_SRC="/mnt/target/usr/lib/shim/shimaa64.efi.signed"
|
||||
GRUB_SIGNED_SRC="/mnt/target/usr/lib/grub/arm64-efi-signed/grubaa64.efi.signed"
|
||||
EFI_BOOT_BINARY="BOOTAA64.EFI"
|
||||
GRUB_EFI_BINARY="grubaa64.efi"
|
||||
SHIM_EFI_BINARY="shimaa64.efi"
|
||||
fi
|
||||
EFI_BOOT_DIR="/mnt/target/boot/efi/EFI/BOOT"
|
||||
EFI_ARCHY_DIR="/mnt/target/boot/efi/EFI/archipelago"
|
||||
if [ -f "$SHIM_SRC" ] && [ -f "$GRUB_SIGNED_SRC" ]; then
|
||||
# Fallback path — what UEFI firmware checks when no boot entry exists
|
||||
mkdir -p "$EFI_BOOT_DIR"
|
||||
cp "$SHIM_SRC" "$EFI_BOOT_DIR/$EFI_BOOT_BINARY"
|
||||
cp "$GRUB_SIGNED_SRC" "$EFI_BOOT_DIR/$GRUB_EFI_BINARY"
|
||||
# Named entry path — for efibootmgr-registered entries
|
||||
mkdir -p "$EFI_ARCHY_DIR"
|
||||
cp "$SHIM_SRC" "$EFI_ARCHY_DIR/$SHIM_EFI_BINARY"
|
||||
cp "$GRUB_SIGNED_SRC" "$EFI_ARCHY_DIR/$GRUB_EFI_BINARY"
|
||||
echo " ✅ Secure Boot chain installed (shim + signed GRUB)"
|
||||
else
|
||||
echo " ⚠️ Signed shim/GRUB not found — Secure Boot machines must disable Secure Boot"
|
||||
[ ! -f "$SHIM_SRC" ] && echo " Missing: $(basename $SHIM_SRC)"
|
||||
[ ! -f "$GRUB_SIGNED_SRC" ] && echo " Missing: $(basename $GRUB_SIGNED_SRC)"
|
||||
fi
|
||||
|
||||
# Legacy BIOS boot: only install if the installer booted in Legacy BIOS mode
|
||||
# (if /sys/firmware/efi exists, the machine supports UEFI — no need for BIOS fallback)
|
||||
if [ -n "${GRUB_BIOS_TARGET}" ] && [ ! -d /sys/firmware/efi ]; then
|
||||
echo " Installing Legacy BIOS bootloader (machine booted in BIOS mode)..."
|
||||
if chroot /mnt/target grub-install --target=${GRUB_BIOS_TARGET} "${TARGET_DISK}"; then
|
||||
echo " ✅ Legacy BIOS bootloader installed"
|
||||
else
|
||||
echo " ⚠️ Legacy BIOS bootloader failed (UEFI-only boot)"
|
||||
fi
|
||||
elif [ -n "${GRUB_BIOS_TARGET}" ]; then
|
||||
echo " Skipping Legacy BIOS bootloader (machine supports UEFI)"
|
||||
fi
|
||||
|
||||
# Regenerate initramfs — the one from Docker export is corrupt/incomplete
|
||||
# (Docker builds have limited /proc, /sys, /dev so initramfs generation fails silently)
|
||||
echo " Regenerating initramfs..."
|
||||
chroot /mnt/target update-initramfs -u -k all
|
||||
|
||||
chroot /mnt/target update-grub
|
||||
|
||||
|
||||
Reference in New Issue
Block a user