Aller au contenu

Installation

Romule est un seul processus Python sans aucune dépendance d'exécution. Quelle que soit la voie choisie, il n'y a ni base de données à préparer, ni file de messages, ni étape de compilation.

Voie Pour qui
Docker Compose presque tout le monde — NAS, mini-PC, serveur domestique
Docker run un essai rapide, ou un orchestrateur déjà en place
Depuis les sources développement, ou machine sans moteur de conteneurs
En paquet Python une installation système avec pipx

Docker Compose (recommandé)

Rien à cloner. Mets ceci dans un docker-compose.yml, change l'unique ligne de volumes: qui désigne tes jeux, et démarre :

services:
  romule:
    image: ghcr.io/romule-app/romule:latest
    container_name: romule
    restart: unless-stopped
    ports:
      - "8787:8787"
    environment:
      ROMULE_ROOT: /data
      ROMULE_BASES: /library
    volumes:
      - romule-donnees:/data
      - /chemin/vers/tes/jeux:/library    # ← la seule ligne à changer

volumes:
  romule-donnees:
docker compose up -d
docker compose logs romule      # affiche l'adresse à ouvrir

Ouvre-la et réponds à l'assistant : un compte, ou aucun mot de passe. Tant que tu n'as pas répondu, l'installation répond à tout le monde — c'est ce qui rend cet écran atteignable depuis ton téléphone et pas seulement depuis la machine qui fait tourner le conteneur. L'image embarque adb, nsz, unar et 7z : il n'y a rien d'autre à installer.

Le même fichier, avec toutes les options

Celui du dessus est le minimum. Voici le même avec tout ce que tu peux vouloir régler, commenté — le dépôt le livre sous le nom docker-compose.yml, avec build: . à la place d'image: parce que qui a cloné le dépôt veut faire tourner ce qu'il vient de lire.

services:
  romule:
    image: ghcr.io/romule-app/romule:latest    # ou, depuis un clone : build: .
    container_name: romule
    restart: unless-stopped

    ports:
      - "8787:8787"

    environment:
      # L'état du service, dans le conteneur. Ne pas changer.
      ROMULE_ROOT: /data
      # Où l'interface a le droit de chercher des jeux. Le dossier exact se
      # choisit depuis l'interface au premier lancement — monte le parent et
      # sélectionne à l'intérieur.
      ROMULE_BASES: /library
      ROMULE_WEB_PORT: "8787"
      TZ: Europe/Paris

      # Rien d'autre n'est nécessaire. Au premier démarrage, l'installation
      # n'est revendiquée par personne : elle répond à tout le monde et s'ouvre
      # sur son assistant, dont l'étape « Ton accès » tranche la question.
      # Depuis le terminal :
      #     docker compose exec romule python3 -m romule access status
      #     docker compose exec romule python3 -m romule user create toi@ex.fr
      #
      # Tu préfères un secret partagé plutôt qu'un compte ?
      #
      # Pour imposer le tien plutôt que celui engendré :
      #     python3 -c "import secrets; print(secrets.token_urlsafe(32))"
      # ROMULE_TOKEN: ""
      #
      # Réseau de confiance et personne d'autre dessus ? On peut se passer de
      # jeton — mais alors tout appareil du réseau a tous les droits.
      # ROMULE_LAN: "1"

    volumes:
      - romule-donnees:/data      # volume nommé : réglages, comptes, jaquettes
      - ./library:/library        # ← tes jeux
      - ./keys:/keys:ro           # ← le dossier contenant prod.keys (facultatif)

    # L'image tourne déjà sous l'utilisateur 1000. Si le tien porte un autre
    # identifiant (`id -u`), pose-le ici pour que les fichiers déposés
    # t'appartiennent, et non à root.
    # user: "1000:1000"

volumes:
  romule-donnees:

Ce qu'il faut monter

Chemin dans le conteneur Ce qu'on y met
/data L'état du service : réglages, comptes, jaquettes, journaux. Un volume nommé — ces fichiers ne sont pas les tiens au même titre que tes jeux, et ils n'ont rien à faire au milieu d'eux.
/library Tes jeux. Romule n'y écrit que _import/ et _corbeille/.
/keys Le dossier contenant prod.keys, en lecture seule. Facultatif — utile seulement pour les .nsz / .xcz.

Tu n'es pas obligé de monter exactement le dossier des jeux. Monte ce qui le contient — un disque entier, un partage, un dossier parent — et choisis le bon depuis l'interface. C'est ce que veut dire ROMULE_BASES: /library : parcourir n'importe où sous le montage, et nulle part ailleurs.

    environment:
      ROMULE_BASES: /library
    volumes:
      - /mnt/nas:/library      # puis choisir /library/switch dans l'interface

Pour figer le dossier et interdire d'en changer depuis l'interface, pose ROMULE_LIBRARY: /library.

Réseau

Le fichier par défaut utilise un réseau bridge ordinaire avec un port publié. Cela marche partout, y compris sous Docker Desktop sur macOS et Windows. adb par Wi-Fi fonctionne dans ce mode : le conteneur atteint ton réseau local, et tu saisis l'adresse de la console une fois.

ports:
  - "8787:8787"

Nécessaire uniquement pour que la console soit découverte toute seule par mDNS.

network_mode: host

Cela affaiblit l'isolation du conteneur. À activer en connaissance de cause.

devices:
  - /dev/bus/usb:/dev/bus/usb

À qui appartiennent les fichiers

L'image tourne sous l'uid 1000, le premier compte sur la plupart des distributions : les fichiers t'appartiennent donc plutôt qu'à root. Si ton uid diffère (id -u), pose user: "<uid>:<gid>".


Docker run

La même chose sans fichier compose :

docker run -d --name romule --restart unless-stopped \
  -p 8787:8787 \
  -e ROMULE_ROOT=/data \
  -e ROMULE_BASES=/library \
  -v romule-donnees:/data \
  -v /mnt/jeux:/library \
  ghcr.io/romule-app/romule:latest

docker logs romule              # l'adresse à ouvrir

Les étiquettes disponibles

latest suit la dernière version publiée. 0.4.0 fige une version exacte et 0.3 en suit les correctifs — épingle l'une des deux si tu préfères choisir quand tu montes de version. L'image est multi-architecture (amd64 et arm64) et ne demande aucune authentification.

docker pull ghcr.io/romule-app/romule:0.4.0

Tu peux aussi la construire toi-même : docker compose up -d --build rend la même image depuis les sources, et c'est la réponse honnête si tu préfères ne pas exécuter un binaire que tu n'as pas construit.


Depuis les sources

Python 3.10 ou plus récent. Aucune étape d'installation, aucun environnement virtuel, aucune compilation.

git clone https://github.com/romule-app/romule
cd romule
ROMULE_ROOT=/chemin/vers/romule-data python3 -m romule

Romule refuse de démarrer sur une racine manifestement fausse — la racine du disque, ton dossier personnel, un dépôt de code — parce qu'il y déplace des fichiers et y crée des dossiers.

En faire un service

/etc/systemd/system/romule.service :

[Unit]
Description=Romule
After=network-online.target

[Service]
Type=simple
User=romule
Environment=ROMULE_ROOT=/var/lib/romule
Environment=ROMULE_LIBRARY=/srv/jeux
Environment=ROMULE_BIND=127.0.0.1
ExecStart=/usr/bin/python3 -m romule serve --no-browser
WorkingDirectory=/opt/romule
Restart=on-failure

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now romule
journalctl -u romule -f

~/Library/LaunchAgents/fr.romule.plist, puis launchctl load ~/Library/LaunchAgents/fr.romule.plist :

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0"><dict>
  <key>Label</key><string>fr.romule</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/bin/python3</string><string>-m</string>
    <string>romule</string><string>serve</string><string>--no-browser</string>
  </array>
  <key>EnvironmentVariables</key>
  <dict><key>ROMULE_ROOT</key><string>/Users/moi/Library/romule</string></dict>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
</dict></plist>

Outils externes

Tous facultatifs. L'absence de l'un désactive une fonction ; aucun n'empêche le démarrage. Romule dit ce qui manque et comment l'installer sur ta plateforme.

Outil Sert à Debian/Ubuntu macOS
adb Parler à la console apt install android-tools-adb brew install android-platform-tools
nsz Convertir les .nsz / .xcz pipx install nsz brew install pipx && pipx install nsz
unar Extraire les .rar apt install unar brew install unar
7z Extraire les .7z apt install p7zip-full brew install p7zip

En paquet Python

Romule n'est pas encore sur PyPI : installe-le depuis le dépôt.

pipx install git+https://github.com/romule-app/romule
ROMULE_ROOT=/chemin/vers/romule-data romule serve

Il n'entraîne aucune dépendance — la bibliothèque standard lui suffit.


Derrière un proxy inverse

Romule parle du HTTP en clair. Tout ce qui est joignable depuis internet a besoin d'un proxy qui termine le HTTPS devant lui.

Nomme ton proxy, sinon les en-têtes transmis ne valent rien

Un proxy sur la même machine fait paraître toutes les requêtes comme venant de 127.0.0.1, et Romule accorde tous les droits aux requêtes locales. Il ignore donc X-Forwarded-For tant que tu ne nommes pas le proxy toi-même :

ROMULE_TRUSTED_PROXIES=127.0.0.1,::1

Sans cela, tous les utilisateurs partagent une seule adresse apparente et la limitation de débit se dégrade. Voir Sécurité et exposition.

romule.exemple.fr {
    reverse_proxy 127.0.0.1:8787
}

Une pile complète — Caddy devant, Romule non publié sur l'hôte — est dans exemples/caddy/. L'intégration continue la monte à chaque changement et vérifie qu'un X-Forwarded-For forgé ne mène toujours nulle part.

server {
    server_name romule.exemple.fr;
    client_max_body_size 0;          # les dépôts sont des jeux entiers
    location / {
        proxy_pass http://127.0.0.1:8787;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_request_buffering off;
        proxy_read_timeout 3600s;
    }
}
labels:
  - traefik.enable=true
  - traefik.http.routers.romule.rule=Host(`romule.exemple.fr`)
  - traefik.http.routers.romule.tls.certresolver=le
  - traefik.http.services.romule.loadbalancer.server.port=8787

Quel que soit le proxy, relève la taille de corps autorisée et le délai de lecture : un seul envoi peut peser plusieurs gigaoctets et durer des minutes.


Mettre à jour

docker compose pull       # ou : docker compose build --pull
docker compose up -d
git pull
# puis redémarrer le service

Ton état vit dans le volume /data et survit. Romule te prévient quand une version plus récente existe — une fois par jour, dans l'en-tête, avec les notes de version. Coupe-le dans Réglages → Accès si tu préfères qu'il ne demande jamais rien.

Sauvegarder

Tout ce qui appartient à Romule tient dans un dossier — ROMULE_ROOT, ou le volume /data :

docker run --rm -v romule-donnees:/data -v "$PWD:/out" \
  alpine tar czf /out/romule-data.tgz -C /data .

Romule écrit aussi ses propres instantanés de réglages sous Réglages → Entretien, ce qui suffit à défaire une mauvaise configuration mais n'est pas une sauvegarde de tes jeux.

Désinstaller

docker compose down -v          # -v retire aussi le volume d'état

Tes jeux ne sont pas touchés : ils n'étaient que montés. Rien n'y a été écrit sauf _import/ et _corbeille/, que tu peux supprimer.