Dolphin pour RomM
RomM — Emulator Streaming avec Dolphin sur Unraid (GPU NVIDIA)
Ce tutoriel explique comment ajouter un conteneur Dolphin (GameCube/Wii) à une instance RomM 5.1.0+ existante pour utiliser la fonctionnalité Emulator Streaming : lancer un jeu depuis l'interface RomM et y jouer dans le navigateur, avec rendu et encodage sur le GPU NVIDIA.
Architecture : RomM ne pilote pas Dolphin directement. Un Docker Mod (maintenu par LoneAngelFayt) injecte dans le conteneur Dolphin un broker HTTP (port 8000) que RomM contacte pour lancer/piloter les jeux. L'image et le son sont diffusés par Selkies (le bureau web intégré aux images LinuxServer), en H.264 NVENC.
⚠️ Testé avec : Unraid 7, RTX 3060, driver NVIDIA 610.x,
lscr.io/linuxserver/dolphin:latest(base Selkies/Wayland), RomM 5.1.0.
1. Prérequis Unraid
1.1 Plugin Nvidia Driver
- Installer le plugin Nvidia Driver (Community Applications).
- Driver propriétaire 580 ou supérieur requis. LinuxServer recommande la branche Production pour Unraid.
- Le GPU ne doit pas être réservé au VFIO (il doit être disponible pour Docker).
- Sur un serveur headless (sans écran), la doc LinuxServer indique qu'un dummy plug HDMI/DP branché sur la carte est requis pour que DRM s'initialise correctement.
1.2 Paramètres noyau (Syslinux)
nvidia-drm.modeset=1 nvidia_drm.fbdev=1
Redémarrer le serveur, puis vérifier :
cat /proc/cmdline # les 2 paramètres doivent apparaître
cat /sys/module/nvidia_drm/parameters/modeset # doit renvoyer Y
nvidia-smi -L # liste le(s) GPU + UUID
Notez l'UUID du GPU (GPU-xxxxxxxx-...), il servira dans le template.
1.3 Limite inotify (optionnel mais recommandé)
Les images Selkies consomment beaucoup d'instances inotify. Pour éviter l'avertissement « Too many open files » :
sysctl -w fs.inotify.max_user_instances=1024
echo 'sysctl -w fs.inotify.max_user_instances=1024' >> /boot/config/go
2. ⚠️ Correctif indispensable : composant NVIDIA egl-x11
C'est le point qui fait échouer la plupart des installations (symptôme : interface Dolphin visible, mais zone de jeu noire avec le son, ou jeu qui rame énormément en rendu logiciel).
Le runtime NVIDIA d'Unraid injecte dans les conteneurs les plateformes EGL wayland, wayland2 et gbm, mais pas les deux plateformes X11 (xlib/xcb) — pourtant livrées par le driver et indispensables à Dolphin, qui crée son contexte OpenGL via EGL sur X11. Sans elles, l'EGL NVIDIA ne peut pas créer de surface et Dolphin retombe en rendu logiciel (ou écran noir via Zink : MESA: error: zink: could not create swapchain).
Vérifier que le driver de l'hôte fournit bien les fichiers :
ls /var/local/overlay/usr/lib64/ | grep egl-x
ls /var/local/overlay/usr/share/egl/egl_external_platform.d/ | grep -E "xlib|xcb"
Vous devez voir libnvidia-egl-xlib.so.1.X.X, libnvidia-egl-xcb.so.1.X.X, 20_nvidia_xlib.json et 20_nvidia_xcb.json. Notez le numéro de version exact des .so (ex. 1.0.5) : il est utilisé dans les montages ci-dessous, et il change à chaque mise à jour du driver (voir §7).
Le correctif consiste en 4 montages en lecture seule + 1 variable, intégrés au template Dolphin de la section suivante.
3. Conteneur Dolphin
Ajouter un conteneur avec l'image lscr.io/linuxserver/dolphin et la configuration suivante.
3.1 Générer un secret partagé
Ce secret authentifie les échanges RomM ↔ broker. Générez-le une fois :
openssl rand -hex 32
3.2 Ports (host:container)
| Port hôte | Port conteneur | Rôle |
|---|---|---|
| 3000 | Selkies HTTP (peu utile) | |
| 3001 | Selkies HTTPS (le flux de jeu) | |
| 8000 | 8000 | Broker RomM |
Adaptez les ports hôte s'ils sont déjà pris.pris par un autre conteneur (dans ce cas, reportez le port choisi dans le bloc streaming du §4.2).
3.3 Variables d'environnement
| Variable | Valeur | Remarque |
|---|---|---|
DOCKER_MODS |
ghcr.io/loneangelfayt/dolphin-romm-integration-mod:latest |
installe le broker |
ROM_ROOT |
/romm/library |
racine de la bibliothèque vue par le broker |
BROKER_SECRET |
(votre secret) | même valeur que côté RomM |
NVIDIA_VISIBLE_DEVICES |
(UUID du GPU) | ou all si un seul GPU |
NVIDIA_DRIVER_CAPABILITIES |
all |
|
DRINODE |
/dev/dri/renderD128 |
GPU de rendu (vérifier avec ls -l /dev/dri/by-path/ que c'est bien la carte NVIDIA) |
DRI_NODE |
/dev/dri/renderD128 |
GPU d'encodage — identique = mode Zero-Copy |
SELKIES_MANUAL_WIDTH |
1920 |
bride la résolution du flux |
SELKIES_MANUAL_HEIGHT |
1080 |
sinon elle suit la fenêtre du navigateur (coûteux) |
__EGL_VENDOR_LIBRARY_FILENAMES |
/usr/share/glvnd/egl_vendor.d/10_nvidia.json |
force l'EGL NVIDIA (fait partie du correctif §2) |
PUID / PGID |
99 / 100 |
standard Unraid |
3.4 Extra Parameters
--gpus all --runtime nvidia --shm-size=1gb
3.5 Volumes
| Host Path | Container Path | Mode |
|---|---|---|
| (votre dossier de ROMs — le même que celui monté dans RomM) | /romm/library |
ro |
(votre appdata, ex. /mnt/user/appdata/dolphin) |
/config |
rw |
/var/local/overlay/usr/lib64/libnvidia-egl-xlib.so.1.X.X |
/usr/lib64/libnvidia-egl-xlib.so.1 |
ro |
/var/local/overlay/usr/lib64/libnvidia-egl-xcb.so.1.X.X |
/usr/lib64/libnvidia-egl-xcb.so.1 |
ro |
/var/local/overlay/usr/share/egl/egl_external_platform.d/20_nvidia_xlib.json |
/usr/share/egl/egl_external_platform.d/20_nvidia_xlib.json |
ro |
/var/local/overlay/usr/share/egl/egl_external_platform.d/20_nvidia_xcb.json |
/usr/share/egl/egl_external_platform.d/20_nvidia_xcb.json |
ro |
Remplacez
1.X.Xpar la version relevée au §2. Le Container Path des libs est volontairement le nom court.so.1: c'est celui que le loader EGL recherche (déclaré dans les JSON), ce qui évite d'avoir à créer des symlinks.
💡 Important : le chemin de la bibliothèque doit être identique dans RomM et dans Dolphin (
/romm/librarydes deux côtés), sinon le broker ne retrouvera pas les fichiers que RomM lui demande de lancer.
3.6 Vérifications après démarrage
docker logs dolphin 2>&1 | grep -iE "broker|NVENC|Zero-Copy"
Attendu : ROM broker listening on port 8000, Shared secret auth enabled, NVENC ... Initialized successfully, Decision: Zero-Copy path active.
curl -s http://localhost:8000/health # → {"status":"ok"}
docker exec dolphin sh -c 'ldconfig -p | grep egl-x' # → les 2 libs xlib/xcb
4. Côté RomM
4.1 Variable d'environnement
Ajouter au conteneur RomM :
| Variable | Valeur |
|---|---|
STREAMING_BROKER_SECRET |
(le même secret qu'au §3.1) |
4.2 config.yml
Dans le config.yml de RomM (dossier config), ajouter le bloc streaming (adapter l'IP du serveur et les ports choisis) :
streaming:
enabled: true
containers:
- platform: ngc
host: https://IP_DU_SERVEUR:37013001
broker_host: http://IP_DU_SERVEUR:8000
label: Dolphin
memory_card_sync: true
- platform: wii
host: https://IP_DU_SERVEUR:37013001
broker_host: http://IP_DU_SERVEUR:8000
label: Dolphin
Redémarrer RomM après modification.
4.3 Structure de la bibliothèque
- Le dossier de plateforme doit correspondre au fs_slug de RomM :
ngcpour la GameCube,wiipour la Wii (pasgc, pasgamecube) — sinon prévoir un mappage dansconfig.yml. - Les ROMs doivent être des fichiers directs (
.rvz,.iso) — pas d'archives.zip/.7z, Dolphin ne peut pas les lancer via le broker. - ⚠️ RomM supporte deux structures (
library/roms/<plateforme>/oulibrary/<plateforme>/roms/) mais la simple présence d'un dossierlibrary/roms/fait basculer toute la bibliothèque sur la première : ne mélangez pas les deux, ou toutes vos autres plateformes deviendront invisibles au scan.
Rescanner la plateforme dans RomM après tout changement.
5. Premier lancement
- Ouvrir une première fois
https://IP_DU_SERVEUR:et accepter le certificat auto-signé (sinon le flux ne se chargera pas dans RomM).37013001 - Dans RomM, ouvrir la fiche d'un jeu GameCube → bouton Play on Dolphin.
- Le jeu doit s'afficher, fluide, avec le son.
Vérifier que le GPU est bien utilisé (pendant qu'un jeu tourne) :
docker exec -u abc dolphin sh -c 'for p in /proc/[0-9]*; do ls -l $p/fd 2>/dev/null | grep -q nvidia && echo "$(basename $p) $(tr "\0" " " < $p/cmdline | cut -c1-60)"; done'
dolphin-emu doit apparaître dans la liste. S'il n'y a que selkies, labwc et Xwayland, Dolphin est en rendu logiciel → revoir le §2.
Note : lancez bien ce test avec
-u abc— en root, la lecture de/proc/<pid>/fddes processus de l'utilisateurabcéchoue silencieusement.
6. Réglages Dolphin utiles
Le fichier de configuration est <appdata>/. config/dolphin-emu/Dolphin.ini. Toujours éditer conteneur arrêté (Dolphin réécrit ses fichiers en se fermant), et savoir que le mod réimpose GFXBackend = OpenGL à chaque recréation du conteneur — c'est le bon backend ici (c'est le chemin EGL corrigé au §2), ne pas chercher à le changer.
Réglage recommandé (section [Core]) :
CPUThread = True
C'est le mode « Dual Core » de Dolphin ; selon les versions il peut être désactivé par défaut, et son absence coûte très cher en performances.
7. Maintenance et limites connues
- À chaque mise à jour du driver NVIDIA de l'hôte, le nom des libs (
libnvidia-egl-*.so.1.X.X) change : mettre à jour les 2 Host Path correspondants dans le template Dolphin, sinon écran noir / rendu logiciel au retour. - Une seule session à la fois par conteneur : un conteneur = une instance Dolphin = un flux. Pour du multi-joueurs simultané, dupliquer le conteneur (autres ports, autre secret possible) et ajouter une entrée dans
streaming.containers. - Sessions fantômes : fermer l'onglet du navigateur ne tue pas Dolphin ; la session peut rester occupée. En attendant mieux :
docker exec dolphin pkill dolphin-emu. - Les paquets installés à la main dans le conteneur (
apt-get) ne survivent pas à une recréation. Pour des outils de diagnostic permanents, chaîner le moduniversal-package-install:DOCKER_MODS=ghcr.io/loneangelfayt/dolphin-romm-integration-mod:latest|linuxserver/mods:universal-package-install+INSTALL_PACKAGES=vulkan-tools|mesa-utils|x11-utils.
8. Dépannage rapide
| Symptôme | Cause probable | Solution |
|---|---|---|
| « ROMs not found » au scan | Nom de dossier ≠ fs_slug, ou structures mélangées | §4.3 |
| Pas de bouton « Play on Dolphin » | Bloc streaming absent/invalide, ou secret différent |
§4.1–4.2 |
| Flux ne se charge pas dans RomM | Certificat auto-signé jamais accepté | §5.1 |
Jeu très lent, dolphin-emu absent du test des fd |
Rendu logiciel (egl-x11 manquant) | §2 |
| Zone de jeu noire, interface et son OK | Idem — Zink sans présentation possible | §2 (et retirer d'éventuelles variables MESA_LOADER_DRIVER_OVERRIDE/GALLIUM_DRIVER) |
| Écran noir après une mise à jour du driver | Version des libs changée | §7 |
| « Failed to initialize video backend » | Variables graphiques parasites ou backend forcé à Vulkan | Revenir à la config §3, GFXBackend = OpenGL |