feat: container orchestration, branding overhaul, onboarding logging
Container orchestration: - Health monitor with crash recovery and auto-restart - Doctor service (periodic health checks via systemd timer) - Reconcile service (desired-state convergence) - Stack-aware install/uninstall with dependency tracking Branding: - Custom GRUB background (designer artwork, 1024x768) - ISOLINUX boot menu: centered, orange accents, clean labels - Terminal banners: adaptive width, basic ANSI colors, fits 80-col - Removed auto-generated splash scripts (designer provides assets) - GRUB theme: lowercase branding Frontend: - 401 handler clears localStorage immediately (prevents cascade) Backend: - Onboarding/auth logging ([onboarding] tag in journalctl) - Cookie Secure flag logging for debugging HTTP/HTTPS issues ISO fixes: - Install log saved before unmount (was silently failing) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -324,6 +324,10 @@ RUN mkdir -p /etc/archipelago/ssl && \
|
||||
COPY archipelago.service /etc/systemd/system/archipelago.service
|
||||
COPY archipelago-update.service /etc/systemd/system/archipelago-update.service
|
||||
COPY archipelago-update.timer /etc/systemd/system/archipelago-update.timer
|
||||
COPY archipelago-doctor.service /etc/systemd/system/archipelago-doctor.service
|
||||
COPY archipelago-doctor.timer /etc/systemd/system/archipelago-doctor.timer
|
||||
COPY archipelago-reconcile.service /etc/systemd/system/archipelago-reconcile.service
|
||||
COPY archipelago-reconcile.timer /etc/systemd/system/archipelago-reconcile.timer
|
||||
|
||||
# Enable services
|
||||
RUN systemctl enable NetworkManager || true && \
|
||||
@@ -333,7 +337,9 @@ RUN systemctl enable NetworkManager || true && \
|
||||
systemctl enable tor || true && \
|
||||
systemctl enable tailscaled || true && \
|
||||
systemctl enable chrony || true && \
|
||||
systemctl enable archipelago-update.timer || true
|
||||
systemctl enable archipelago-update.timer || true && \
|
||||
systemctl enable archipelago-doctor.timer || true && \
|
||||
systemctl enable archipelago-reconcile.timer || true
|
||||
|
||||
# Remove policy-rc.d so services can start on first boot
|
||||
RUN rm -f /usr/sbin/policy-rc.d
|
||||
@@ -393,6 +399,15 @@ NGINXCONF
|
||||
echo " Using archipelago-update.service + timer from configs/"
|
||||
fi
|
||||
|
||||
# Copy container doctor and reconciliation timers
|
||||
if [ -f "$SCRIPT_DIR/configs/archipelago-doctor.service" ]; then
|
||||
cp "$SCRIPT_DIR/configs/archipelago-doctor.service" "$WORK_DIR/archipelago-doctor.service"
|
||||
cp "$SCRIPT_DIR/configs/archipelago-doctor.timer" "$WORK_DIR/archipelago-doctor.timer"
|
||||
cp "$SCRIPT_DIR/configs/archipelago-reconcile.service" "$WORK_DIR/archipelago-reconcile.service"
|
||||
cp "$SCRIPT_DIR/configs/archipelago-reconcile.timer" "$WORK_DIR/archipelago-reconcile.timer"
|
||||
echo " Using container doctor + reconcile timers from configs/"
|
||||
fi
|
||||
|
||||
# Use archipelago.service from configs/ (User=root for Podman container access)
|
||||
if [ -f "$SCRIPT_DIR/configs/archipelago.service" ]; then
|
||||
cp "$SCRIPT_DIR/configs/archipelago.service" "$WORK_DIR/archipelago.service"
|
||||
@@ -519,11 +534,23 @@ if [ -n "\$INSTALLER_STARTED" ]; then
|
||||
fi
|
||||
export INSTALLER_STARTED=1
|
||||
|
||||
# Colors
|
||||
O=\$'\\033[1;33m' # Bold yellow (orange accent)
|
||||
W=\$'\\033[1;37m' # Bold white
|
||||
D=\$'\\033[37m' # Dim
|
||||
N=\$'\\033[0m' # Reset
|
||||
|
||||
# Center-print
|
||||
TW=\$(tput cols 2>/dev/null || echo 60)
|
||||
[ "\$TW" -gt 120 ] && TW=120
|
||||
cc() { local s=\$(echo -e "\$1" | sed 's/\\x1b\\[[0-9;]*m//g'); local p=\$(( (TW - \${#s}) / 2 )); [ \$p -lt 0 ] && p=0; printf "%*s" "\$p" ""; echo -e "\$1"; }
|
||||
|
||||
sleep 1
|
||||
clear
|
||||
echo ""
|
||||
echo " ARCHIPELAGO BITCOIN NODE OS"
|
||||
echo " Automatic Installer"
|
||||
cc "\${W}a r c h i p e l a g o\${N}"
|
||||
cc "\${O}━━━━━━━━━━━━━━━━━━━━━\${N}"
|
||||
cc "\${D}Automatic Installer\${N}"
|
||||
echo ""
|
||||
|
||||
BOOT_MEDIA=""
|
||||
@@ -535,17 +562,14 @@ for dev in /run/live/medium /lib/live/mount/medium /run/archiso /cdrom /media/cd
|
||||
done
|
||||
|
||||
if [ -n "\$BOOT_MEDIA" ]; then
|
||||
echo " Found installer at: \$BOOT_MEDIA"
|
||||
cc "\${D}Found installer at: \$BOOT_MEDIA\${N}"
|
||||
echo ""
|
||||
echo " Press Enter to start installation, or Ctrl+C for shell..."
|
||||
read
|
||||
cc "Press Enter to install | \${W}Ctrl+C\${N} for shell"
|
||||
read -s
|
||||
bash "\$BOOT_MEDIA/archipelago/auto-install.sh"
|
||||
else
|
||||
echo " Installer not found on boot media."
|
||||
echo " Checked: /run/live/medium, /run/archiso, /cdrom, /media/cdrom"
|
||||
echo ""
|
||||
echo " You can try manually:"
|
||||
echo " sudo bash /path/to/archipelago/auto-install.sh"
|
||||
cc "\${D}Installer not found on boot media.\${N}"
|
||||
cc "\${D}Try: sudo bash /path/to/archipelago/auto-install.sh\${N}"
|
||||
echo ""
|
||||
fi
|
||||
PROFILE
|
||||
@@ -1349,26 +1373,62 @@ case "$(uname -m)" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Colors (use $'...' syntax for reliable escape code interpretation)
|
||||
RED=$'\033[0;31m'
|
||||
GREEN=$'\033[0;32m'
|
||||
# Colors (basic ANSI — works on bare-metal Linux console)
|
||||
RED=$'\033[31m'
|
||||
GREEN=$'\033[32m'
|
||||
YELLOW=$'\033[1;33m'
|
||||
BLUE=$'\033[0;34m'
|
||||
ORANGE=$'\033[1;33m'
|
||||
DIM=$'\033[37m'
|
||||
CYAN=$'\033[36m'
|
||||
WHITE=$'\033[1;37m'
|
||||
NC=$'\033[0m'
|
||||
|
||||
# Adaptive centering
|
||||
TW=$(tput cols 2>/dev/null || echo 60)
|
||||
[ "$TW" -gt 120 ] && TW=120
|
||||
cc() { local s=$(echo -e "$1" | sed 's/\x1b\[[0-9;]*m//g'); local p=$(( (TW - ${#s}) / 2 )); [ $p -lt 0 ] && p=0; printf "%*s" "$p" ""; echo -e "$1"; }
|
||||
hrule() { local len=$((TW > 50 ? 50 : TW - 4)); local hr=""; for i in $(seq 1 $len); do hr="${hr}─"; done; cc "${DIM}${hr}${NC}"; }
|
||||
|
||||
box() {
|
||||
local bw=$((TW > 52 ? 52 : TW - 4))
|
||||
local inner=$((bw - 2))
|
||||
local top="╭"; local bot="╰"
|
||||
for i in $(seq 1 $inner); do top="${top}─"; bot="${bot}─"; done
|
||||
top="${top}╮"; bot="${bot}╯"
|
||||
cc "${DIM}${top}${NC}"
|
||||
}
|
||||
boxend() {
|
||||
local bw=$((TW > 52 ? 52 : TW - 4))
|
||||
local inner=$((bw - 2))
|
||||
local bot="╰"
|
||||
for i in $(seq 1 $inner); do bot="${bot}─"; done
|
||||
bot="${bot}╯"
|
||||
cc "${DIM}${bot}${NC}"
|
||||
}
|
||||
boxline() {
|
||||
local bw=$((TW > 52 ? 52 : TW - 4))
|
||||
local inner=$((bw - 2))
|
||||
local stripped=$(echo -e "$1" | sed 's/\x1b\[[0-9;]*m//g')
|
||||
local pad=$((inner - ${#stripped}))
|
||||
[ $pad -lt 0 ] && pad=0
|
||||
local right=""
|
||||
for i in $(seq 1 $pad); do right="${right} "; done
|
||||
cc "${DIM}│${NC} $1${right}${DIM}│${NC}"
|
||||
}
|
||||
|
||||
clear
|
||||
echo ""
|
||||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ ║${NC}"
|
||||
echo -e "${BLUE}║ ${GREEN}🏝️ ARCHIPELAGO BITCOIN NODE OS${BLUE} ║${NC}"
|
||||
echo -e "${BLUE}║ ║${NC}"
|
||||
echo -e "${BLUE}║ ${NC}Automatic Installation${BLUE} ║${NC}"
|
||||
echo -e "${BLUE}║ ║${NC}"
|
||||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════════╝${NC}"
|
||||
box
|
||||
boxline ""
|
||||
boxline "${WHITE}A R C H I P E L A G O${NC}"
|
||||
boxline "${ORANGE}━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
boxline "${DIM}Automatic Installation${NC}"
|
||||
boxline ""
|
||||
boxend
|
||||
echo ""
|
||||
|
||||
# Check required tools are present (should be bundled in ISO)
|
||||
echo -e "${YELLOW}🔧 Checking installer tools...${NC}"
|
||||
cc "${DIM}Checking installer tools...${NC}"
|
||||
MISSING=""
|
||||
command -v parted >/dev/null 2>&1 || MISSING="parted $MISSING"
|
||||
command -v mkfs.vfat >/dev/null 2>&1 || MISSING="mkfs.vfat $MISSING"
|
||||
@@ -1467,15 +1527,15 @@ if [ -z "$TARGET_DISK" ]; then
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✅ Target disk: $TARGET_DISK ($TARGET_SIZE)${NC}"
|
||||
cc "${GREEN}target: ${WHITE}$TARGET_DISK ($TARGET_SIZE)${NC}"
|
||||
echo ""
|
||||
echo -e "${RED}⚠️ WARNING: ALL DATA ON $TARGET_DISK WILL BE ERASED${NC}"
|
||||
cc "${RED}all data on $TARGET_DISK will be erased${NC}"
|
||||
echo ""
|
||||
echo "Press Enter to install Archipelago, or Ctrl+C to cancel..."
|
||||
read
|
||||
cc "${DIM}Press Enter to install | Ctrl+C to cancel${NC}"
|
||||
read -s
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}🔧 Installing Archipelago...${NC}"
|
||||
cc "${DIM}Installing Archipelago...${NC}"
|
||||
echo ""
|
||||
|
||||
# Unmount any existing partitions
|
||||
@@ -2402,6 +2462,9 @@ date=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
||||
type=unbundled
|
||||
BUILDINFO
|
||||
|
||||
# Save install log BEFORE unmounting target
|
||||
cp "$INSTALL_LOG" /mnt/target/var/log/archipelago-install.log 2>/dev/null || true
|
||||
|
||||
# Cleanup
|
||||
sync
|
||||
umount /mnt/target/run 2>/dev/null || true
|
||||
@@ -2415,63 +2478,34 @@ cryptsetup close archipelago-data 2>/dev/null || true
|
||||
umount /mnt/target 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN} _${NC}"
|
||||
echo -e "${GREEN} ,--.\\\`-. __${NC}"
|
||||
echo -e "${GREEN} _,.\\\`. \\:/,\" \\\`-._${NC}"
|
||||
echo -e "${GREEN} ,-*\" _,.-;-*\\\`-.+\"*._ )${NC}"
|
||||
echo -e "${GREEN} ( ,.\"* ,-\" / \\\`. \\\\. \\\`.${NC}"
|
||||
echo -e "${GREEN} ,\" ,;\" ,\"\\../\\ \\: \\${NC}"
|
||||
echo -e "${GREEN} ( ,\"/ / \\\\.,' : )) /${NC}"
|
||||
echo -e "${GREEN} \\ |/ / \\\\.,' / // ,'${NC}"
|
||||
echo -e "${GREEN} \\_)\\ ,' \\\\.,' ( / )/${NC}"
|
||||
echo -e "${GREEN} \\\` \\._,' \\\`\"${NC}"
|
||||
echo -e "${GREEN} \\../${NC}"
|
||||
echo -e "${GREEN} \\../${NC}"
|
||||
echo -e "${GREEN} ~ ~\\../ ~~ ~~${NC}"
|
||||
echo -e "${GREEN} ~~ ~~ \\../ ~~ ~ ~~${NC}"
|
||||
echo -e "${GREEN} ~~ ~ ~~ __...---\\../-...__ ~~~ ~~${NC}"
|
||||
echo -e "${GREEN} ~~~~ ~_,--' \\../ \\\`--.__ ~~ ~~${NC}"
|
||||
echo -e "${GREEN} ~~~ __,--' \\\`\" \\\`--.__ ~~~${NC}"
|
||||
echo -e "${GREEN}~~ ,--' \\\`--.${NC}"
|
||||
echo -e "${GREEN} '------......______ ______......------\\\` ~~${NC}"
|
||||
echo -e "${GREEN} ~~~ ~ ~~ ~ \\\`\\\`\\\`\\\`\\\`---\"\"\"\"\" ~~ ~ ~~${NC}"
|
||||
echo -e "${GREEN} ~~~~ ~~ ~~~~ ~~~~~~ ~ ~~ ~~ ~~~ ~${NC}"
|
||||
echo ""
|
||||
echo -e "${GREEN} █████╗ ██████╗ ██████╗██╗ ██╗██╗██████╗ ███████╗██╗ █████╗ ██████╗ ██████╗ ${NC}"
|
||||
echo -e "${GREEN} ██╔══██╗██╔══██╗██╔════╝██║ ██║██║██╔══██╗██╔════╝██║ ██╔══██╗██╔════╝ ██╔═══██╗${NC}"
|
||||
echo -e "${GREEN} ███████║██████╔╝██║ ███████║██║██████╔╝█████╗ ██║ ███████║██║ ███╗██║ ██║${NC}"
|
||||
echo -e "${GREEN} ██╔══██║██╔══██╗██║ ██╔══██║██║██╔═══╝ ██╔══╝ ██║ ██╔══██║██║ ██║██║ ██║${NC}"
|
||||
echo -e "${GREEN} ██║ ██║██║ ██║╚██████╗██║ ██║██║██║ ███████╗███████╗██║ ██║╚██████╔╝╚██████╔╝${NC}"
|
||||
echo -e "${GREEN} ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ${NC}"
|
||||
box
|
||||
boxline ""
|
||||
boxline "${WHITE}A R C H I P E L A G O${NC}"
|
||||
boxline "${GREEN}━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
boxline "${GREEN}Installation Complete${NC}"
|
||||
boxline ""
|
||||
boxend
|
||||
echo ""
|
||||
echo -e "${GREEN} 🏝️ BITCOIN NODE OS 🏝️${NC}"
|
||||
cc "${DIM}After reboot, open the Web UI from any device on your network.${NC}"
|
||||
echo ""
|
||||
echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ ✅ INSTALLATION COMPLETE! ║${NC}"
|
||||
echo -e "${GREEN}║ ║${NC}"
|
||||
echo -e "${GREEN}║ Remove the USB drive and press Enter to reboot. ║${NC}"
|
||||
echo -e "${GREEN}║ ║${NC}"
|
||||
echo -e "${GREEN}║ After reboot: ║${NC}"
|
||||
echo -e "${GREEN}║ • Web UI: http://<IP> ║${NC}"
|
||||
echo -e "${GREEN}║ • SSH: ssh archipelago@<IP> ║${NC}"
|
||||
echo -e "${GREEN}║ • SSH Password: archipelago ║${NC}"
|
||||
echo -e "${GREEN}║ • Web Password: password123 ║${NC}"
|
||||
echo -e "${GREEN}║ ║${NC}"
|
||||
echo -e "${GREEN}║ Pre-loaded apps (ready to start via Web UI): ║${NC}"
|
||||
echo -e "${GREEN}║ • Bitcoin Knots • LND • Home Assistant ║${NC}"
|
||||
echo -e "${GREEN}║ • BTCPay Server • Mempool • Nostr Relays ║${NC}"
|
||||
echo -e "${GREEN}║ ║${NC}"
|
||||
echo -e "${GREEN}║ Validate: bash /opt/archipelago/scripts/run-e2e-tests.sh ║${NC}"
|
||||
echo -e "${GREEN}║ ║${NC}"
|
||||
echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════════╝${NC}"
|
||||
cc "${DIM}Web UI:${NC} ${WHITE}http://<this machine's IP>${NC}"
|
||||
cc "${DIM}SSH:${NC} ${DIM}ssh archipelago@<IP>${NC}"
|
||||
cc "${DIM}Password:${NC} ${DIM}archipelago${NC}"
|
||||
cc "${DIM}Web Login:${NC} ${DIM}password123${NC}"
|
||||
echo ""
|
||||
cc "${DIM}Pre-loaded apps (start via Web UI):${NC}"
|
||||
cc "${DIM}Bitcoin Knots, LND, Home Assistant,${NC}"
|
||||
cc "${DIM}BTCPay Server, Mempool, Nostr Relay${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW} >>> REMOVE THE USB DRIVE NOW <<<${NC}"
|
||||
hrule
|
||||
echo ""
|
||||
# Save install log to target disk for post-install debugging
|
||||
cp "$INSTALL_LOG" /mnt/target/var/log/archipelago-install.log 2>/dev/null || true
|
||||
cc "${YELLOW}>>> REMOVE THE USB DRIVE NOW <<<${NC}"
|
||||
echo ""
|
||||
# Install log already saved before unmount (above)
|
||||
|
||||
read -p "Press Enter to reboot (make sure USB is removed)..."
|
||||
cc "${DIM}Press Enter to reboot${NC}"
|
||||
read -s
|
||||
|
||||
# Suppress all error output during cleanup and reboot
|
||||
exec 2>/dev/null
|
||||
@@ -2590,22 +2624,25 @@ UI vesamenu.c32
|
||||
PROMPT 0
|
||||
TIMEOUT 0
|
||||
|
||||
MENU TITLE ARCHIPELAGO - Bitcoin Node OS
|
||||
MENU TITLE Bitcoin Node OS
|
||||
MENU BACKGROUND splash.png
|
||||
MENU RESOLUTION 1024 768
|
||||
MENU VSHIFT 14
|
||||
MENU HSHIFT 6
|
||||
MENU WIDTH 40
|
||||
MENU VSHIFT 15
|
||||
MENU HSHIFT 28
|
||||
MENU WIDTH 26
|
||||
MENU MARGIN 2
|
||||
MENU ROWS 5
|
||||
MENU TABMSG Press TAB to edit | https://archipelago.sh
|
||||
MENU COLOR screen 37;40 #00000000 #00000000 none
|
||||
MENU COLOR border 30;40 #00000000 #00000000 none
|
||||
MENU COLOR title 1;37;40 #fffb923c #00000000 none
|
||||
MENU COLOR sel 7;37;40 #ffffffff #80333333 std
|
||||
MENU COLOR unsel 37;40 #ff999999 #00000000 none
|
||||
MENU COLOR title 1;37;40 #80888888 #00000000 none
|
||||
MENU COLOR sel 7;37;40 #ffffffff #c0181818 std
|
||||
MENU COLOR unsel 37;40 #ffaaaaaa #00000000 none
|
||||
MENU COLOR hotkey 1;37;40 #fffb923c #00000000 none
|
||||
MENU COLOR hotsel 1;37;40 #fffb923c #80333333 std
|
||||
MENU COLOR timeout_msg 37;40 #ff666666 #00000000 none
|
||||
MENU COLOR hotsel 1;37;40 #fffb923c #c0181818 std
|
||||
MENU COLOR timeout_msg 37;40 #ff555555 #00000000 none
|
||||
MENU COLOR timeout 1;37;40 #fffb923c #00000000 none
|
||||
MENU COLOR tabmsg 37;40 #ff666666 #00000000 none
|
||||
MENU COLOR tabmsg 37;40 #ff444444 #00000000 none
|
||||
MENU COLOR cmdmark 37;40 #00000000 #00000000 none
|
||||
MENU COLOR cmdline 37;40 #00000000 #00000000 none
|
||||
|
||||
@@ -2618,7 +2655,7 @@ LABEL install
|
||||
MENU DEFAULT
|
||||
|
||||
LABEL install-verbose
|
||||
MENU LABEL Install Archipelago (verbose)
|
||||
MENU LABEL Install (verbose output)
|
||||
KERNEL /live/vmlinuz
|
||||
APPEND initrd=/live/initrd.img boot=live components
|
||||
|
||||
|
||||
Reference in New Issue
Block a user