Architecture FR - Kheopsian/Hydranos GitHub Wiki

🇬🇧 English · 🇫🇷 Français

Architecture

S'applique à Hydranos 4.4.

Pour qui veut savoir comment Hydranos est construit : ce qui tourne dans le processus, dans quel ordre il démarre, et où chaque octet d'état est stocké sur le disque. Pour le modèle mental en bref, lisez d'abord Concepts & glossaire. Vous venez de la 3.x ? Voir Mettre à jour depuis la 3.x.

Binaires

Binaire Ce que c'est Livré dans
hydranos Le démon : interface web, API REST native, shim qBittorrent, serveur MCP et tous les moteurs BitTorrent, dans un seul processus. Image Docker, archive tar Linux, zip Windows
hydranos-update L'outil de mise à jour automatique. C'est un binaire séparé parce que Windows ne peut pas remplacer un exécutable en cours d'exécution. Il remplace uniquement les binaires, jamais votre configuration ni vos données. Archive tar Linux, zip Windows (pas l'image Docker)

Les versions publiées ne livrent plus l'ancien binaire hydranos-engine.

hydranos accepte --config <path> (par défaut /config/default.toml ; sous Windows, default.toml à côté de hydranos.exe), --console (Windows : ouvre une fenêtre de console), --version (affiche hydranos et la version) et --help, plus deux commandes, hydranos reset-password <password> [config] et hydranos hash-password <password>. Tout autre argument est nommé dans un avertissement sur stderr (ignoring unknown argument …; starting anyway), et les options 3.x --agent-* / --front-* reçoivent un avertissement qui renvoie vers les nœuds ; ni l'un ni l'autre n'empêche le démarrage. Liste complète avec les variables d'environnement et les signaux : Config : environnement, CLI & signaux.

Ce qui tourne dans le processus

Tout tient dans un seul processus : aucun processus enfant, aucun second programme à superviser. Un gestionnaire HTTP lit directement en mémoire la table des torrents d'un moteur.

  • Écoute HTTP sur api_host:api_port (par défaut 0.0.0.0, port 8199). Elle s'ouvre en premier, derrière une barrière de démarrage qui sert l'écran de démarrage et ses fichiers /static/*, /health, /metrics, /api/startup et GET /api/setup, et répond 503 à tout autre chemin (une autre méthode sur l'un de ces chemins, comme POST /api/setup, n'est pas routée et est refusée) jusqu'à ce que le catalogue soit chargé (voir Séquence de démarrage). Ensuite, un seul routeur sert :
    • / et /static/* : l'interface web. Son HTML, son JavaScript et ses traductions sont compilés dans le binaire ; il n'y a aucun dossier web à installer.
    • /api/* : l'API REST native (y compris /api/events, le flux de mises à jour en direct qu'écoute l'interface).
    • /api/v2/* : le shim compatible qBittorrent.
    • /mcp : le serveur MCP pour les clients IA.
    • /health et /metrics : test de vie et page texte Prometheus (ce qu'elles rapportent : Supervision & journaux, Métriques Prometheus).
    • /install.sh : le script d'enrôlement des nœuds (voir Nœuds & plusieurs machines).
  • Hôte des moteurs : détient la liste des moteurs construits au démarrage (race, hoard, puis les éventuels moteurs supplémentaires), et les tunnels WireGuard gérés qu'il a montés pour eux. Les moteurs ne sont jamais ajoutés ni retirés en cours de fonctionnement : un changement exige un redémarrage.
  • Client de sortie du démon : l'unique client HTTP des requêtes qui n'appartiennent à aucun moteur (listes de trackers et du filtre IP, vérification de mise à jour, webhooks, URL de .torrent, sonde d'IP de sortie du processus), routé par [daemon] egress et remplacé sans redémarrage quand la configuration change (voir VPN & sortie réseau).
  • Moteurs : une session BitTorrent chacun (section suivante).
  • Tâches d'arrière-plan, toutes lancées par hydranos lui-même :
Tâche Portée Ce qu'elle fait
Planificateur d'annonces une par moteur Annonce chaque torrent de ce moteur ; le comportement suit le rôle du moteur (voir Trackers & annonces). Il fait aussi un scrape des torrents pour lesquels aucun tracker n'a encore répondu : premier passage 90 s après le démarrage, puis toutes les 300 s, 5000 torrents au plus par passage.
Balayage de reprise une par moteur Toutes les 300 s, écrit les lignes modifiées du state.db du moteur.
Démarrage échelonné une par moteur, au démarrage Démarre les torrents non arrêtés par lots de 2000, avec des pauses de 100 ms.
Gestionnaire de file une par moteur Premier passage 60 s après le démarrage, puis toutes les 30 s, sur la configuration en direct : active_downloads, et avec queueing = true, active_seeds / active_limit ; torrents lents (voir File, limites de partage & de débit).
Limites de partage une par moteur Premier passage 90 s après le démarrage, puis toutes les 120 s : arrête ou supprime les seeds qui ont dépassé leur limite de ratio ou de temps de seed, 500 actions au plus par passage.
Choker une par moteur Toutes les 10 s ; ne fait rien sauf si choking = true.
LSD une par moteur où enable_lsd est actif Découverte de pairs locale (BEP 14), épinglée comme les autres sockets du moteur (voir Réseau : ports & redirection).
Suiveurs de port une par moteur dans un tunnel WireGuard géré avec NAT-PMP, ou avec gluetun_port_forward Conservent le port accordé par la passerelle du tunnel (NAT-PMP) ou détenu par gluetun, et déplacent le port que le moteur annonce quand il change (derrière gluetun, son écoute aussi).
Synchronisation du temps de seed une par moteur Copie le temps de seed du moteur dans le store une fois par jour (premier passage une heure après le démarrage).
Drain race une par moteur de rôle race Libère les volumes race (voir Drain race & graduation).
Balayage de transit une par moteur Toutes les 300 s (premier passage 90 s après le démarrage), supprime, avec leurs fichiers, les torrents dont l'obligation de seed est remplie, dans les catégories marquées Transit area et désignées aussi comme Passer vers (catégorie Hoard) (Graduate to (hoard category)) d'une autre catégorie.
Exécuteur de jobs processus Exécute les jobs persistants de l'onglet Jobs, un à la fois. Un surveillant distinct vérifie toutes les 30 s les déplacements vers un nœud qui attendent que le nœud détienne une copie complète.
Exécuteur de workflows processus Workflows à minuterie, plus les workflows déclenchés par les torrents terminés et ajoutés.
RSS processus Toutes les 30 s (aussitôt quand un flux ou une règle change), récupère les flux arrivés à échéance, 4 à la fois, et applique les règles de téléchargement (voir Flux RSS & téléchargements automatiques).
Résolveur de magnets processus Récupère les métadonnées des magnets en attente, y compris ceux qu'un redémarrage a interrompus.
Dossiers surveillés processus Interroge régulièrement des dossiers à la recherche de fichiers .torrent / .magnet.
Filtre IP processus Tient à jour les listes de blocage et les bannissements.
Test de ligne processus Seulement quand [vpn_speedtest] interval_secs est supérieur à 0 : un test toutes les tant de secondes, 300 au moins.
Redirection de port une par moteur sur le réseau NAT-PMP, puis UPnP, quand auto_port_forward vaut true (valeur par défaut). Pas pour un moteur bloqué, dans un tunnel géré, derrière gluetun ou un proxy SOCKS5, ou épinglé à une autre interface que celle de la route par défaut.
Sonde d'IP de sortie processus Toutes les 180 s, mesure l'adresse publique des requêtes propres du démon (via [daemon] egress), et de chaque moteur qui a un bind_interface et n'est pas bloqué.
Réconciliation du store processus Toutes les 5 minutes, retire du store les lignes des torrents que leur moteur ne détient plus (avec des garde-fous).
Détection d'anomalies processus Premier passage 2 minutes après le démarrage, puis toutes les 5 minutes ; sert /api/health/anomalies et l'outil MCP health (voir Supervision & journaux).
Scanner de liens, échantillonneur de benchmark, enregistreur d'événements race processus Alimentent les colonnes de liens physiques, l'onglet Performances (Benchmark) et l'historique race.
Icône de la zone de notification Windows uniquement Open Hydranos, Check for updates, Quit Hydranos.
  • Runtime Tokio : un seul runtime multithread pour tout le processus. Nombre de threads de travail = HYDRANOS_WORKER_THREADS s'il est défini et supérieur à 0, sinon le nombre de cœurs CPU, plafonné à 32.

Carte du processus

flowchart TB
    clients["Navigateur, Sonarr, Radarr, autobrr, scripts, clients MCP"]
    peers["Pairs, trackers, nœuds DHT"]
    net_daemon["Listes de trackers et du filtre IP, vérification de mise à jour,<br/>webhooks, URL de .torrent"]

    subgraph proc["processus hydranos - un seul runtime Tokio"]
        http["Écoute HTTP<br/>0.0.0.0:8199 par défaut<br/>barrière de démarrage jusqu'à ce qu'il soit prêt"]
        ui["/ et /static/*<br/>interface web, compilée dans le binaire"]
        api["/api/*<br/>API REST et /api/events"]
        qbit["/api/v2/*<br/>shim qBittorrent"]
        mcp["/mcp<br/>serveur MCP"]
        mon["/health et /metrics"]
        core["État partagé<br/>config en direct, accès au store, hôte des moteurs"]
        workers["Tâches d'arrière-plan<br/>file, limites de partage, drain, balayage de transit,<br/>jobs, workflows, RSS, magnets, dossiers surveillés,<br/>filtre IP, redirection de port, sonde d'IP de sortie,<br/>réconciliation, détection d'anomalies"]
        egress["Client de sortie du démon<br/>route depuis daemon.egress"]

        subgraph eng_race["moteur race - rôle race"]
            race_tm["Table des torrents et E/S disque"]
            race_net["Écoute 16171 TCP et uTP,<br/>file de connexions, DHT, LSD"]
            race_ann["Planificateur d'annonces, mode Race,<br/>et scrape"]
        end

        subgraph eng_hoard["moteur hoard - rôle hoard"]
            hoard_tm["Table des torrents et E/S disque"]
            hoard_net["Écoute 16172 TCP et uTP,<br/>file de connexions, DHT, LSD"]
            hoard_ann["Planificateur d'annonces, mode Hoard,<br/>et scrape"]
        end

        subgraph eng_extra["moteur supplémentaire, par ex. vpn1"]
            extra_tm["Table des torrents et E/S disque"]
            extra_net["Sa propre écoute, file de connexions, DHT, LSD"]
            extra_ann["Planificateur d'annonces, mode selon son rôle,<br/>et scrape"]
        end
    end

    way_race["sortie de race<br/>route par défaut, bind_interface, tunnel ou proxy"]
    way_hoard["sortie de hoard"]
    way_extra["sortie de vpn1, par ex. wg-vpn1"]
    store[("data_dir/hydra.db<br/>le store")]
    race_sdb[("race/state.db")]
    hoard_sdb[("hoard/state.db")]
    extra_sdb[("vpn1/state.db")]

    clients --> http
    http --> ui
    http --> api
    http --> qbit
    http --> mcp
    http --> mon
    api --> core
    qbit --> core
    mcp --> core
    mon --> core
    workers --> core
    workers -->|"listes, webhooks, vérification de mise à jour"| egress
    egress --> net_daemon
    core -->|"écritures du catalogue"| store
    core --> race_tm
    core --> hoard_tm
    core --> extra_tm

    race_tm -->|"metainfo, lecture seule"| store
    hoard_tm -->|"metainfo, lecture seule"| store
    extra_tm -->|"metainfo, lecture seule"| store
    race_tm -->|"lignes de reprise"| race_sdb
    hoard_tm -->|"lignes de reprise"| hoard_sdb
    extra_tm -->|"lignes de reprise"| extra_sdb

    race_tm --- race_net
    race_tm --- race_ann
    hoard_tm --- hoard_net
    hoard_tm --- hoard_ann
    extra_tm --- extra_net
    extra_tm --- extra_ann
    race_net --> way_race
    race_ann --> way_race
    hoard_net --> way_hoard
    hoard_ann --> way_hoard
    extra_net --> way_extra
    extra_ann --> way_extra
    way_race --> peers
    way_hoard --> peers
    way_extra --> peers
Loading

Les connexions sortantes, annonces, scrapes, DHT et LSD de chaque moteur sortent par la sortie propre à ce moteur ; les pairs trouvés par ses annonces, sa DHT, PEX ou LSD vont dans sa propre file de connexions. Un moteur bloqué par le kill switch n'a aucun des cadres réseau ci-dessus : il conserve son catalogue et répond à l'API.

Moteurs

Un moteur est une session BitTorrent à l'intérieur du processus. Toute instance a race et hoard ; les moteurs supplémentaires viennent de blocs engine dans le fichier de configuration (voir Moteurs : race & hoard). Chaque moteur possède :

  • un port d'écoute : écoute TCP des pairs plus une socket uTP sur le même port UDP (16171 pour race et 16172 pour hoard dans le default.toml livré ; une clé absente signifie 16171 pour le rôle race et 16172 pour le rôle hoard, et un port qu'un autre moteur détient déjà est remplacé au démarrage par un port libre, avec un avertissement : définissez-le explicitement pour chaque moteur supplémentaire) ;
  • sa propre file de connexions sortantes, avec sa propre attache, son peer id, sa socket uTP et ses limites de connexions ;
  • un épinglage d'interface facultatif (bind_interface, Linux uniquement) qui porte toutes les sockets du moteur : écoute, uTP, connexions sortantes, annonces HTTP et UDP, scrapes, DHT, LSD, webseeds. Hors Linux, un moteur avec bind_interface reste hors du réseau ;
  • un nœud DHT, sauf si enable_dht = false pour ce moteur (absent signifie actif), attaché à l'interface du moteur quand il en a une (désactivé derrière un proxy SOCKS5) ;
  • LSD (découverte de pairs locale), si enable_lsd est actif pour lui (absent : actif pour le rôle race, inactif sinon) ;
  • un planificateur d'annonces, en mode Race si le rôle du moteur est race, sinon en mode Hoard, avec ses propres clients tracker sur la sortie du moteur ;
  • son propre peer id (-HY, la version, -, puis 12 caractères aléatoires, tirés à nouveau à chaque démarrage), dans ses annonces et dans chaque handshake ;
  • sa propre base de reprise, <config dir>/<engine id>/state.db ;
  • son propre cache de lecture ; le cache des descripteurs de fichiers est partagé par tous les moteurs.

Depuis la 4.4, rien de ce qu'envoie un moteur ne passe par l'attache d'un autre moteur : chacun est une identité réseau distincte. Ce qui sort en dehors des moteurs (les requêtes propres du démon, les noms de trackers résolus par l'hôte pour une interface qu'Hydranos n'a pas créée) est listé sur VPN & sortie réseau.

Si l'écoute d'un moteur ne peut pas s'attacher (par exemple parce que son bind_interface n'est pas actif), le moteur conserve quand même son catalogue et répond à l'API ; /api/engines le signale comme n'étant pas en écoute. Un moteur que le kill switch bloque (armé, comme il l'est par défaut dans tous les modes sauf Direct, sans tunnel, interface, proxy ni allow_direct qui lui soient propres) n'est jamais mis sur le réseau : ni écoute, ni connexion sortante, ni annonce, ni DHT, ni LSD, ni redirection de port.

Séquence de démarrage

Voici l'ordre suivi par le code. Deux points surprennent : les moteurs se mettent sur le réseau avant l'ouverture de l'accès partagé au store et la vérification de son schéma, et le port HTTP s'ouvre en premier mais ne sert qu'un écran de démarrage jusqu'à la toute fin. Jusque-là, l'interface affiche une barre de progression et toutes les API répondent 503 avec Retry-After: 5 (détails : Exploiter Hydranos).

  1. Construire le runtime Tokio ; sous Linux/macOS, lancer les diagnostics de l'allocateur.
  2. Lire la ligne de commande (reset-password et hash-password s'exécutent et quittent ici ; les arguments inconnus font l'objet d'un avertissement). Si le fichier de configuration n'existe pas, en écrire un à partir du modèle intégré, avec data_dir réglé sur <config dir>/data.
  3. Démarrer la journalisation : stderr, l'anneau en mémoire que lit l'onglet Journaux (Logs) (2000 lignes), et <config dir>/hydranos.log.
  4. Lire HYDRANOS_STOP_TIMEOUT. Charger la configuration. Si [daemon] api_key est vide ou vaut encore la valeur d'exemple publiée, générer une clé et l'écrire dans le fichier. Nommer les clés du fichier que rien ne lit (config: … is ignored). Fixer la route des requêtes propres du démon ([daemon] egress, kill switch).
  5. Créer data_dir s'il manque.
  6. Attacher l'écoute HTTP sur api_host:api_port, derrière la barrière de démarrage. Le journal affiche hydra API listening (starting). Un port déjà pris échoue ici, dans la première seconde. SIGTERM et Ctrl+C sont entendus à partir de ce moment.
  7. Charger chaque moteur, dans l'ordre race, hoard, puis les moteurs supplémentaires : pour chacun, ouvrir hydra.db en lecture seule pour les métadonnées et en lecture-écriture pour importer tout uploads/<info_hash>.torrent dont le blob manque (s'exécute à chaque démarrage, ne trouve plus rien une fois la migration faite), et charger les lignes de reprise depuis son state.db. Aucune socket n'est encore ouverte.
  8. En mode WireGuard, managed by Hydranos, monter d'abord les tunnels wg-<engine>. Puis décider quels moteurs le kill switch garde hors du réseau : chacun est journalisé kill switch: BLOCKED, kept off the network … et sauté. Puis, dans le même ordre, mettre chaque autre moteur sur le réseau : pour un tunnel NAT-PMP, demander le port à sa passerelle ; DHT, LSD, uTP, écoute TCP, file de connexions, choker ; planificateur d'annonces (avec son scrape), suiveur de port gluetun ou de tunnel ; démarrage échelonné, limitation des vérifications. Un moteur avec start_paused = true retient ses connexions sortantes et ses annonces jusqu'à ce qu'il soit libéré. Un arrêt demandé pendant le chargement se termine ici : écriture de la reprise, tunnels démontés, sortie.
  9. Ouvrir l'accès partagé à hydra.db en lecture-écriture et vérifier son schéma. En cas d'échec, Hydranos passe en mode de secours (ci-dessous) et ne va pas plus loin.
  10. Journaliser ce que couvre le kill switch (kill switch: …, une ligne par moteur et une pour le démon) et les champs de catégorie 3.x ignorés. Lancer la redirection de port pour chaque moteur sur le réseau qui peut être redirigé sur le routeur de la maison (si auto_port_forward).
  11. Ouvrir bench.db (une base absente ou cassée est tolérée) et lancer l'enregistreur d'événements race.
  12. En mode WAL, ouvrir une seconde connexion en lecture seule au store et lancer le checkpointer à 1 s ; lancer la réconciliation du store et le remplissage rétroactif de l'index de contenu.
  13. Réappliquer l'état d'arrêt que vous avez défini sur les torrents (depuis le store), sans envoyer aux trackers d'événement stopped ; lancer pour chaque moteur la synchronisation du temps de seed.
  14. Migration ponctuelle pour les configurations qui contiennent encore [announce_clients] (voir Mettre à jour depuis la 3.x).
  15. Lancer l'échantillonneur de benchmark, la sonde d'IP de sortie et les compteurs journaliers ; restaurer depuis le store les plafonds de débit globaux du client.
  16. Lancer le drain race sur chaque moteur de rôle race, puis sur tous les moteurs le balayage de transit, le gestionnaire de file et la tâche des limites de partage.
  17. Lancer l'exécuteur de jobs et le surveillant des transferts vers les nœuds, les workflows, le résolveur de magnets, le test de ligne, le filtre IP, les dossiers surveillés, le RSS, le scanner de liens et la détection d'anomalies.
  18. Windows : écouter la demande d'arrêt de l'outil de mise à jour et afficher l'icône de la zone de notification.
  19. Passer le vrai routeur à l'écoute. Le journal affiche hydra API ready. L'interface et toutes les API répondent à partir de ce moment.
sequenceDiagram
    participant M as hydranos main
    participant C as default.toml
    participant H as Écoute HTTP
    participant E as Hôte des moteurs
    participant S as store hydra.db
    participant N as Réseau

    M->>C: créé depuis le modèle intégré si absent
    M->>M: journalisation vers stderr, anneau Logs, hydranos.log
    M->>C: chargement, écrit une api_key générée si vide ou valeur d'exemple
    M->>M: nomme les clés ignorées, fixe la route de sortie du démon
    M->>M: création de data_dir
    M->>H: attache api_host et api_port - écran de démarrage, 503 ailleurs
    loop chaque moteur - race, hoard, supplémentaires
        E->>S: ouverture en lecture seule, pour les metainfo
        E->>S: ouverture en lecture-écriture, import des blobs uploads/ manquants
        E->>E: chargement des lignes de reprise depuis son state.db
    end
    E->>N: tunnels WireGuard gérés montés, dans ce mode
    loop chaque moteur non bloqué par le kill switch
        E->>N: DHT, LSD, écoute uTP et TCP, file de connexions
        E->>N: planificateur d'annonces et scrape, suiveur de port, démarrage échelonné
    end
    M->>S: ouverture en lecture-écriture, vérification du schéma
    alt le store ne s'ouvre pas ou la vérification du schéma échoue
        M->>H: routes de secours sur la même écoute
    else store ouvert
        M->>N: NAT-PMP ou UPnP par moteur qui peut être redirigé
        M->>M: bench.db, checkpointer, réconciliation, remplissage rétroactif
        M->>E: réapplique les torrents arrêtés depuis le store
        M->>M: synchro du temps de seed, drain, balayage de transit, file, limites de partage
        M->>M: jobs, workflows, RSS, magnets, filtre IP, dossiers surveillés, détection d'anomalies
        M->>H: passe le routeur - interface et API joignables
    end
Loading

Mode de secours

Si hydra.db ne peut pas être ouvert, ou si sa table torrents n'a pas les colonnes attendues, Hydranos sert une surface de secours minimale sur l'écoute qu'il a déjà ouverte (votre api_host et votre api_port) et rien d'autre. Il ne sert aucune interface web : / répond par un message texte d'une ligne, et les seules autres routes sont un test de santé, les routes de diagnostic et de réparation du store, et un redémarrage. Les moteurs ont déjà été mis sur le réseau à l'étape 8 et continuent de tourner. Les routes, la réparation et leur mode d'emploi sont sur Exploiter Hydranos.

État persistant

Hydranos tient deux sortes de bases SQLite que vous devez sauvegarder (le store et l'état de reprise de chaque moteur), plus un fichier SQLite de télémétrie (bench.db), un fichier journal et, en mode WireGuard géré, les fichiers du fournisseur dans <data_dir>/wireguard (WireGuard géré). Cette séparation est voulue : le store détient ce que vous avez décidé (quels torrents existent, leurs métadonnées, catégorie, tags, intention d'arrêt, épinglages), l'état de reprise de chaque moteur détient ce que le moteur a mesuré (progression, octets transférés, temps de seed).

Le store (hydra.db)

<data_dir>/hydra.db est le catalogue. Il contient :

Table Contenu
torrents Une ligne par torrent et par moteur, clé (info_hash, session) où session est l'identifiant du moteur : les octets du .torrent sous forme de BLOB, chemin de sauvegarde, catégorie, date d'ajout et de fin, octets cumulés, intention d'arrêt (paused), tags, épinglage (téléchargement forcé), temps de seed (copie de secours journalière).
counters Octets cumulés reportés des torrents supprimés, au global et par tracker.
meta Documents JSON : catégories, provenance, politique de drain par volume (seuils, quota, TRIM après le drain).
tag_registry Tags connus.
drain_history Passages du drain race.
jobs La file des jobs.
workflows, workflow_activity, workflow_events Définitions des workflows, leur journal d'activité, événements en attente.
magnets Magnets en attente de métadonnées, avec leurs options d'ajout (ils survivent à un redémarrage).
nodes, enrol_tokens Nœuds déclarés et jetons d'enrôlement à usage unique.
app_settings, ip_bans Réglages écrits par l'interface (filtre IP, dossiers surveillés, les plafonds de débit globaux du client client_rate_limits) et bannissements.
content_index, link_index Détection des données en double et résultats du scan des liens physiques.
share_limits Limites de partage définies sur des torrents isolés (creuse : seulement les torrents qui ont les leurs).
rss_feeds, rss_folders, rss_articles, rss_rules, rss_taken Flux RSS, leurs articles, les règles de téléchargement et les articles déjà pris.

Le store est la seule source de métadonnées. Au démarrage, chaque moteur lit ses lignes de reprise, puis récupère le .torrent de chaque torrent dans hydra.db par son info hash. Il n'y a aucun repli sur des fichiers .torrent présents sur le disque : perdre hydra.db, c'est perdre le catalogue, même si chaque state.db et chaque fichier de contenu sont intacts. Sauvegardez-le (voir Exploiter Hydranos ; il n'y a pas de sauvegarde intégrée).

Mode de journalisation :

  • Sur un système de fichiers local, le store fonctionne en mode WAL (synchronous=NORMAL), avec un thread d'arrière-plan qui fait un checkpoint chaque seconde. Vous verrez hydra.db-wal et hydra.db-shm à côté ; ils font partie du store.
  • Si le dossier qui contient hydra.db est détecté comme un système de fichiers réseau, le store garde un journal de rollback classique. Sous Linux, « réseau » signifie NFS, SMB/CIFS ou FUSE : un store sur un partage mergerfs ou un partage utilisateur Unraid tourne donc sans WAL. Sous Windows, cela signifie un chemin UNC ou un lecteur réseau mappé. Les autres systèmes sont toujours traités comme locaux.
  • synchronous=NORMAL signifie qu'une coupure de courant peut faire perdre les derniers commits ; un plantage du seul démon, non.

Quand le store est ouvert en lecture-écriture, les tables manquantes sont créées ; une ancienne table torrents à clé unique est reconstruite une fois sur (info_hash, session).

État de reprise (/state.db)

Chaque moteur a <config dir>/<engine id>/state.db, avec une ligne par torrent : chemin de sauvegarde, mode seed, indicateur d'arrêt, octets envoyés et reçus, date d'ajout et de fin, le bitfield des pièces vérifiées, la liste des trackers (pour que les modifications de trackers survivent à un redémarrage), les secondes de seed, les plafonds de débit propres au torrent et son ordre de téléchargement (priorités des fichiers, séquentiel). Il est toujours ouvert en mode WAL, quel que soit le système de fichiers : la vérification de système de fichiers réseau qui tient le store hors du WAL ne s'applique pas à lui. Gardez le dossier de configuration sur un disque local (sur Unraid, pas sur un partage utilisateur FUSE).

Il est écrit immédiatement quand un torrent est ajouté, se termine ou change de chemin de sauvegarde, et sinon par le balayage toutes les 300 s, qui n'écrit que les lignes modifiées. Les anciens fichiers par torrent de <config dir>/<engine id>/resume/ sont importés une fois dans un state.db vide et laissés en place. state.db se trouve sous le dossier de configuration, pas sous data_dir.

bench.db

<data_dir>/bench.db contient la télémétrie derrière l'onglet Performances et ses records. Hydranos démarre sans lui s'il ne peut pas l'ouvrir, et rien d'autre n'en dépend.

hydranos.log

<config dir>/hydranos.log, soumis à rotation par Hydranos lui-même à 128 Mio, avec 4 anciens fichiers conservés (hydranos.log.1 à .4). Donner n'importe quelle valeur à HYDRANOS_LOG_STDOUT (même 0) désactive le fichier. Détails : Supervision & journaux.

uploads/ (migration ponctuelle uniquement)

<data_dir>/uploads/ n'est jamais écrit par la 4.4. S'il existe, chaque moteur importe au démarrage les fichiers .torrent qui manquent au store ; ensuite, le dossier n'est plus lu pour quoi que ce soit.

Où se trouvent les données

Le « dossier de configuration » est le dossier qui contient le fichier de configuration ; il contient les dossiers des moteurs (race/, hoard/, un par moteur supplémentaire) et hydranos.log. data_dir vient de [daemon] data_dir et contient hydra.db et bench.db. Le contenu de vos torrents se trouve là où pointent leurs chemins de sauvegarde, jamais dans l'un de ces dossiers.

Installation Fichier de configuration Dossier de configuration (dossiers des moteurs, journal) data_dir (store, bench)
Docker (image d'origine) /config/default.toml /config /config
Linux, packaging/install.sh + systemd /etc/hydranos/default.toml /etc/hydranos /var/lib/hydranos
Binaire lancé sans --config (Linux) /config/default.toml /config /config/data
Zip Windows, sans --config default.toml à côté de hydranos.exe (une installation que la 4.3 a amorcée à \config\default.toml continue de l'utiliser ; voir Windows) le dossier de hydranos.exe <exe folder>\data
  • Docker : le point d'entrée de l'image crée /config/default.toml avec data_dir = "/config" (il suit HYDRANOS_CONFIG_DIR si vous le définissez) : tout se trouve donc dans le volume /config.
  • Binaire : quand hydranos écrit lui-même une configuration de départ, il règle data_dir sur <config dir>/data. Passez --config pour choisir un autre emplacement ; le dossier de configuration et data_dir suivent.
  • Linux empaqueté : les fichiers state.db et le journal se retrouvent sous /etc/hydranos/race/, /etc/hydranos/hoard/ et /etc/hydranos/hydranos.log, à côté de la configuration. Voir Linux (bare metal).
flowchart LR
    subgraph cfgdir["dossier de configuration - dossier de default.toml"]
        toml["default.toml"]
        log["hydranos.log"]
        rdb[("race/state.db")]
        hdb[("hoard/state.db")]
        xdb[("id du moteur supplémentaire/state.db")]
        rjson["id du moteur/resume/<br/>ancien format, importé une fois"]
    end
    subgraph datadir["data_dir - depuis daemon.data_dir"]
        hydra[("hydra.db<br/>plus -wal et -shm en mode WAL")]
        bench[("bench.db")]
        up["uploads/<br/>ancien format, importé une fois"]
        wgdir["wireguard/<br/>fichiers .conf du fournisseur, managed.list"]
    end
    payload["Fichiers de contenu<br/>au chemin de sauvegarde de chaque torrent"]

    toml -->|"data_dir pointe vers"| hydra
    rdb -->|"metainfo recherchées par info hash"| hydra
    hdb -->|"metainfo recherchées par info hash"| hydra
    xdb -->|"metainfo recherchées par info hash"| hydra
    up -.->|"blobs manquants copiés au démarrage"| hydra
    rjson -.->|"importé dans un state.db vide"| rdb
    rdb -->|"chemin de sauvegarde"| payload
    hdb -->|"chemin de sauvegarde"| payload
Loading

Parcours des requêtes

Une ligne de liste dans l'onglet Race ou Hoard combine deux sources : l'état en direct (progression, vitesses, pairs, état des trackers) lu dans la mémoire du moteur, et les informations que vous avez définies (catégorie, tags, intention d'arrêt, téléchargement forcé) lues dans le store. Une écriture qui change ce que vous avez décidé va dans le store. Un nouveau torrent (ajout REST, shim, interface, MCP, dossier surveillé, magnet) est écrit dans le store avant que le moteur en soit informé, parce que le moteur lit ses hachages de pièces dans le store. Les copies vers un second moteur et les déplacements par job réutilisent des métadonnées déjà présentes dans le store : ils informent donc d'abord le moteur et écrivent la ligne ensuite.

flowchart LR
    req_list["GET page de liste<br/>API REST ou interface"]
    req_add["Ajout d'un torrent<br/>API REST, shim, interface, MCP, dossier surveillé"]
    check{"Chemin de sauvegarde connu, add-block race<br/>et revendication de chemin franchis ?"}
    req_live["GET /api/events<br/>mises à jour en direct"]
    engmem["Mémoire du moteur<br/>progression, vitesses, pairs"]
    store[("hydra.db")]
    sdb[("state.db du moteur")]
    refuse["Refusé : pas de chemin de sauvegarde, add-block race<br/>ou revendication de chemin réglée sur refus"]

    req_list --> engmem
    req_list --> store
    req_live --> engmem
    req_add --> check
    check -->|"non"| refuse
    check -->|"oui, étape A : ligne avec les octets .torrent"| store
    store -->|"étape B : puis le moteur le reçoit"| engmem
    engmem -->|"étape C : ligne de reprise écrite aussitôt"| sdb
Loading

La revendication de chemin peut aussi ajouter le torrent dans un dossier à lui, ou en pause jusqu'à ce que les fichiers déjà sur le disque soient prouvés, quand un autre torrent nomme les mêmes fichiers. Le pipeline d'ajout complet (catégories, revendication de chemin, données en double, workflows à l'ajout) est sur Ajouter des torrents & données existantes.

Un torrent, plusieurs moteurs

Le même torrent peut vivre dans plus d'un moteur de la même instance : les lignes du store ont pour clé (info_hash, session), donc chaque copie a sa propre ligne (catégorie, tags, intention d'arrêt) et chaque moteur sa propre ligne de reprise. Les octets du .torrent sont recherchés par info hash uniquement : toutes les copies partagent donc les mêmes métadonnées.

  • POST /api/torrents/:info_hash/copy avec {"engine": "<id>"} (Duplicate to engine ›) ajoute le torrent à un second moteur, pointé sur le même chemin de sauvegarde (mêmes fichiers, aucune seconde copie sur le disque), en mode seed. La catégorie et la date d'ajout sont copiées, les tags non.
  • POST /api/torrents/:info_hash/engine avec {"engine": "<id>"} (Move to engine ›) déplace une copie vers un autre moteur de la même instance avec son enregistrement de reprise (pièces, compteurs, modifications de trackers, temps de seed, état d'arrêt) ; les données ne bougent pas.
  • Les routes REST par torrent acceptent ?engine=<id> pour indiquer sur quelle copie elles agissent. Les actions du shim qBittorrent (stop, start…) s'appliquent à toutes les copies.

Dans l'interface web, les deux sont dans le groupe Node du menu contextuel, cibles local-<id> : voir Mettre des torrents sur un moteur supplémentaire sur Moteurs : race & hoard.

Résistance aux plantages

Événement Ce qui est enregistré Ce qui peut être perdu
Arrêt propre : SIGTERM ou SIGINT (Linux), Ctrl+C, Ctrl+Break, fermeture de la console, déconnexion de la session, arrêt du système ou Quit Hydranos depuis la zone de notification (Windows) Le serveur HTTP se vide (5 s au plus), stopped est envoyé aux trackers (5 s au plus), puis l'état de reprise de chaque moteur est écrit en entier, un thread par moteur ; les tunnels gérés sont démontés en dernier. Rien, si l'écriture tient dans HYDRANOS_STOP_TIMEOUT (120 s par défaut ; 120, 60s, 2m ou 1m30s) et que le superviseur attend aussi longtemps. Au-delà de ce budget, Hydranos part avec ce qui est écrit. Windows ne laisse que quelques secondes après une déconnexion ou un arrêt du système : cette écriture peut alors être partielle.
Redémarrage depuis l'interface ou l'API (POST /api/restart, POST /api/settings/restart) Le même arrêt propre, puis le code de sortie 75 (Windows : lance d'abord son successeur). Comme pour un arrêt propre. Un superviseur qui relance en cas d'échec le relance.
kill -9, plantage, arrêt par le Gestionnaire des tâches Tout ce qui est déjà validé : lignes du store, et lignes de reprise écrites à l'ajout, à la fin du téléchargement et au changement de chemin de sauvegarde. Jusqu'à 300 s de progression des pièces, de compteurs d'octets et de temps de seed ; le démarrage suivant revérifie ce qui a été perdu.
Coupure de courant Comme ci-dessus, moins les derniers commits de chaque base WAL. Les dernières secondes d'écritures du store et de reprise, y compris un torrent ajouté pendant ces secondes.

Les torrents ajoutés avant un plantage du démon ou un kill -9 ne sont jamais perdus (une coupure de courant peut encore faire disparaître un torrent ajouté dans ses dernières secondes) : leur ligne de store et leur ligne de reprise sont écrites au moment de l'ajout. Les jobs en cours sont remis en file au démarrage suivant ; les magnets en attente de métadonnées reprennent. Les délais des superviseurs (stop_grace_period, TimeoutStopSec) et le code de sortie du redémarrage sont traités sur Exploiter Hydranos.

Plusieurs machines

Chaque machine fait tourner son propre hydranos complet, avec son store et ses moteurs. Les instances communiquent en HTTP simple, chacune via l'API normale de l'autre, authentifiées avec la clé API de l'autre instance. La seule exception est l'enrôlement : la nouvelle machine s'enregistre une fois auprès du contrôleur avec un jeton à usage unique. Voir Nœuds & plusieurs machines.

⚠️ **GitHub.com Fallback** ⚠️