Mount Batocera ROM shares from a NAS at boot
Problem
Batocera reads games from folders under /userdata/roms/<system>, but the ROMs live on a NAS. Without a mount, the emulators see empty folders after every reboot. The NAS shares have to be mounted over SMB (CIFS) each time the appliance boots, and unmounted cleanly at shutdown.
Two things make a naive boot script fail silently: the target folders may not exist yet, and start can run before the network is up, so every mount fails and nothing is mounted.
Fix
Batocera runs executable scripts in /userdata/system/services/ with start at boot and stop at shutdown. Save the script below as /userdata/system/services/nas-mounts, make it executable, and enable it:
chmod +x /userdata/system/services/nas-mounts
batocera-services enable nas-mounts
batocera-services listIf you prefer not to use a service, the same start and stop logic also works from /userdata/system/custom.sh, which Batocera calls with the same arguments.
The SMB password does not go in the script. The credentials= option points at a file on the appliance, /userdata/system/.smbcredentials, which holds the NAS username and password. Create it yourself and make it readable by root only:
chmod 600 /userdata/system/.smbcredentialsThe script creates each mount point, waits up to about 60 seconds for the NAS to answer, then mounts one share per system folder. Shares that are already mounted are skipped.
#!/bin/bash
# Mount NAS ROM shares on boot, unmount them on shutdown.
NAS="<nas-ip>"
CREDS="/userdata/system/.smbcredentials"
OPTS="rw,credentials=${CREDS},vers=3.0"
# "<share folder on NAS>:<folder under /userdata/roms>"
SHARES="
xbox:xbox
3do:3do
mugen:mugen
tg16cd:pcenginecd
segacd:segacd
saturn:saturn
dreamcast:dreamcast
gamecube:gamecube
wii:wii
wiiu:wiiu
switch:switch
ps2:ps2
ps3:ps3
"
wait_for_nas() {
for _ in $(seq 1 30); do
ping -c 1 -W 2 "$NAS" >/dev/null 2>&1 && return 0
sleep 2
done
return 1
}
case "$1" in
start)
if ! wait_for_nas; then
echo "nas-mounts: $NAS not reachable, nothing mounted"
exit 1
fi
for entry in $SHARES; do
src="${entry%%:*}"
dst="/userdata/roms/${entry##*:}"
mkdir -p "$dst"
mountpoint -q "$dst" && continue
mount -t cifs -o "$OPTS" "//${NAS}/Emulation/roms/${src}" "$dst" \
|| echo "nas-mounts: failed to mount $src"
done
;;
stop)
for entry in $SHARES; do
dst="/userdata/roms/${entry##*:}"
mountpoint -q "$dst" && umount "$dst"
done
;;
*)
echo "Usage: $0 {start|stop}"
;;
esac
exit 0Why this shape
mkdir -pguarantees the mount point exists, so a fresh install or a wipedromsfolder does not break the mount.- The ping loop gives the network and the NAS time to come up. Without it,
startcan run first and every mount fails with no visible error. stopunmounts only the folders this script mounted. A blanketumount -a -t cifs,nfswould also drop any other CIFS or NFS mounts on the box.mountpoint -qmakesstartsafe to run twice.
Adapting it
- Replace
<nas-ip>with the NAS address (IP address or hostname). - Change
Emulation/romsin themountline if your NAS share path differs. - Edit the
SHARESlist: onenas-folder:batocera-folderpair per line. Drop systems you do not have. - Create the credentials file at the path given in
CREDS. It needsusername=andpassword=lines. Do not put those values in the script or in notes. - Test without rebooting:
/userdata/system/services/nas-mounts start, thenmount | grep cifs.