Synchronize Slot B
First complete verification. This procedure is selected by boot layout, not by Pod generation.
Advanced and high risk.
This procedure is strictly limited to boards running on the verified Slot A eMMC boot path (/dev/mmcblk0p5, rootfs_a) described in the root access guide. Do not run this on SD-card installations (such as Pod 3 with an SD card), systems booted from Slot B, or unknown partition layouts.
Weighing Slot B synchronization:
- Leaving Slot B untouched: If Slot B retains its original factory installation, a hardware factory reset boots that factory environment. If stock update services are active and the hub has internet access, it may then install newer firmware. The root-access procedure has not been verified against every resulting firmware version.
- Synchronizing Slot B: Copying SSH keys, configurations, and subsystem binaries to Slot B is intended to preserve access and the verified subsystem combination after failover. It does not guarantee access: this script does not disable Slot B’s stock update services, and a later OTA may replace the copied files. Synchronizing Slot B also modifies the factory backup.
Only synchronize Slot B if you are completely confident in your installation and want to prevent a firmware mismatch or loss of SSH access if the hardware ever fails over to Slot B.
If you choose to synchronize Slot B:
ssh -p 8822 root@POD_IP "
set -e
trap 'umount /mnt/slot_b 2>/dev/null || true' EXIT
# 1. Verify board variant and active boot slot (Slot A eMMC layout only)
ACTIVE_ROOT=\"\$(findmnt -n -o SOURCE / 2>/dev/null || awk '\$2==\"/\" {print \$1}' /proc/mounts)\"
CMDLINE=\"\$(cat /proc/cmdline 2>/dev/null || true)\"
case \"\$CMDLINE \$ACTIVE_ROOT\" in
*rootfs_a*|*mmcblk0p5*) ;;
*)
echo 'Error: Active system is not on the verified Slot A eMMC boot path (/dev/mmcblk0p5).' >&2
exit 1
;;
esac
TARGET_DEV='/dev/mmcblk0p7'
if [ ! -b \"\$TARGET_DEV\" ]; then
echo \"Error: Inactive Slot B partition \$TARGET_DEV does not exist.\" >&2
exit 1
fi
if [ \"\$ACTIVE_ROOT\" = \"\$TARGET_DEV\" ]; then
echo \"Error: Target partition \$TARGET_DEV is currently active as root!\" >&2
exit 1
fi
# 2. Mount Slot B and verify mount target
mkdir -p /mnt/slot_b
mount -o rw \"\$TARGET_DEV\" /mnt/slot_b
MOUNTED_DEV=\"\$(findmnt -n -o SOURCE /mnt/slot_b 2>/dev/null || awk '\$2==\"/mnt/slot_b\" {print \$1}' /proc/mounts)\"
if [ \"\$MOUNTED_DEV\" != \"\$TARGET_DEV\" ]; then
echo \"Error: Mount mismatch: /mnt/slot_b is \$MOUNTED_DEV, expected \$TARGET_DEV.\" >&2
exit 1
fi
# 3. Resolve effective authorized_keys path used by sshd for root on Slot A
ROOT_HOME=\"\$(awk -F: '\$1==\"root\" {print \$6}' /etc/passwd 2>/dev/null || true)\"
ROOT_HOME=\"\${ROOT_HOME:-/home/root}\"
KEY_PATH=''
ENTRIES=\"\$(sshd -T -C 'user=root,host=localhost,addr=127.0.0.1' 2>/dev/null | awk 'tolower(\$1)==\"authorizedkeysfile\" {\$1=\"\"; print \$0}')\"
for entry in \$ENTRIES; do
case \"\$entry\" in
*%h*) cand=\"\${entry//%h/\$ROOT_HOME}\" ;;
/*) cand=\"\$entry\" ;;
*) cand=\"\$ROOT_HOME/\$entry\" ;;
esac
if [ -s \"\$cand\" ]; then
KEY_PATH=\"\$cand\"
break
fi
done
if [ -z \"\$KEY_PATH\" ]; then
for cand in \"\$ROOT_HOME/.ssh/authorized_keys\" \"\$ROOT_HOME/ssh/authorized_keys\" /etc/ssh/authorized_keys; do
if [ -s \"\$cand\" ]; then KEY_PATH=\"\$cand\"; break; fi
done
fi
if [ ! -s \"\$KEY_PATH\" ]; then
echo 'Error: No valid root authorized_keys file found on Slot A.' >&2
exit 1
fi
# 4. Copy authorized_keys to effective Slot B path and verify write
DEST_KEY=\"/mnt/slot_b\$KEY_PATH\"
mkdir -p \"\$(dirname \"\$DEST_KEY\")\"
cp -a \"\$KEY_PATH\" \"\$DEST_KEY\"
chmod 600 \"\$DEST_KEY\"
# Verify destination copy succeeded and content matches before proceeding
if [ ! -s \"\$DEST_KEY\" ] || ! cmp -s \"\$KEY_PATH\" \"\$DEST_KEY\"; then
echo \"Error: Failed to verify authorized_keys write at \$DEST_KEY.\" >&2
exit 1
fi
# Also populate root's home key locations on Slot B for recovery resilience
for dir in \"/mnt/slot_b\$ROOT_HOME/.ssh\" \"/mnt/slot_b\$ROOT_HOME/ssh\"; do
mkdir -p \"\$dir\"
cp -a \"\$KEY_PATH\" \"\$dir/authorized_keys\"
chmod 700 \"\$dir\"
chmod 600 \"\$dir/authorized_keys\"
done
# Stock sshd_config_readonly reads /etc/ssh/authorized_keys as the login user (rewt),
# so append root's keys there instead of overwriting, and leave /etc/ssh at its stock mode.
mkdir -p /mnt/slot_b/etc/ssh
touch /mnt/slot_b/etc/ssh/authorized_keys
while IFS= read -r key || [ -n \"\$key\" ]; do
[ -n \"\$key\" ] || continue
grep -qxF -- \"\$key\" /mnt/slot_b/etc/ssh/authorized_keys || echo \"\$key\" >> /mnt/slot_b/etc/ssh/authorized_keys
done < \"\$KEY_PATH\"
# Stock Slot B ships 'AllowUsers rewt', which refuses root even with a valid key.
# Allow key-only root login and add root to AllowUsers in both sshd configs.
for cfg in /mnt/slot_b/etc/ssh/sshd_config /mnt/slot_b/etc/ssh/sshd_config_readonly; do
[ -f \"\$cfg\" ] || continue
sed -i -E 's/^#?[[:space:]]*PermitRootLogin[[:space:]]+.*/PermitRootLogin prohibit-password/' \"\$cfg\"
if grep -qE '^[[:space:]]*AllowUsers[[:space:]]' \"\$cfg\" && ! grep -qE '^[[:space:]]*AllowUsers([[:space:]].*)?[[:space:]]root([[:space:]]|\$)' \"\$cfg\"; then
sed -i -E 's/^([[:space:]]*AllowUsers[[:space:]].*)\$/\1 root/' \"\$cfg\"
fi
done
# 5. Sync updated binaries, configurations, and NATS service
mkdir -p /mnt/slot_b/opt/eight/bin /mnt/slot_b/opt/eight/lib/subsystem_updates /mnt/slot_b/opt/eight/config /mnt/slot_b/usr/lib64 /mnt/slot_b/usr/bin /mnt/slot_b/etc/systemd/system/multi-user.target.wants
cp -a /opt/eight/bin/frankenfirmware /mnt/slot_b/opt/eight/bin/frankenfirmware
cp -a /opt/eight/lib/subsystem_updates/* /mnt/slot_b/opt/eight/lib/subsystem_updates/
if [ -f /opt/eight/config/machine.json ]; then
cp -a /opt/eight/config/machine.json /mnt/slot_b/opt/eight/config/machine.json
else
rm -f /mnt/slot_b/opt/eight/config/machine.json
fi
cp -a /usr/lib64/libnats.so.3.11* /mnt/slot_b/usr/lib64/
cp -a /usr/bin/nats* /mnt/slot_b/usr/bin/
cp -a /etc/nats.conf /mnt/slot_b/etc/nats.conf
cp -a /etc/systemd/system/nats-server.service /mnt/slot_b/etc/systemd/system/nats-server.service
ln -sf /etc/systemd/system/nats-server.service /mnt/slot_b/etc/systemd/system/multi-user.target.wants/nats-server.service
if [ -d /etc/systemd/system/frank.service.d ]; then
cp -a /etc/systemd/system/frank.service.d /mnt/slot_b/etc/systemd/system/
fi
# 6. Flush changes and safely unmount
sync
trap - EXIT
umount /mnt/slot_b
"Last updated on