Architecture FR - Kheopsian/Hydranos GitHub Wiki
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.
| 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.
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éfaut0.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/startupetGET /api/setup, et répond 503 à tout autre chemin (une autre méthode sur l'un de ces chemins, commePOST /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. -
/healthet/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] egresset 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
hydranoslui-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_THREADSs'il est défini et supérieur à 0, sinon le nombre de cœurs CPU, plafonné à 32.
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
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.
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.tomllivré ; 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 avecbind_interfacereste hors du réseau ; - un nœud DHT, sauf si
enable_dht = falsepour 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_lsdest 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.
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).
- Construire le runtime Tokio ; sous Linux/macOS, lancer les diagnostics de l'allocateur.
- Lire la ligne de commande (
reset-passwordethash-passwords'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é, avecdata_dirréglé sur<config dir>/data. - Démarrer la journalisation : stderr, l'anneau en mémoire que lit l'onglet Journaux (Logs) (2000 lignes), et
<config dir>/hydranos.log. - Lire
HYDRANOS_STOP_TIMEOUT. Charger la configuration. Si[daemon] api_keyest 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). - Créer
data_dirs'il manque. - Attacher l'écoute HTTP sur
api_host:api_port, derrière la barrière de démarrage. Le journal affichehydra 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. - Charger chaque moteur, dans l'ordre
race,hoard, puis les moteurs supplémentaires : pour chacun, ouvrirhydra.dben lecture seule pour les métadonnées et en lecture-écriture pour importer toutuploads/<info_hash>.torrentdont 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 sonstate.db. Aucune socket n'est encore ouverte. - 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 avecstart_paused = trueretient 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. - Ouvrir l'accès partagé à
hydra.dben 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. - 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 (siauto_port_forward). - Ouvrir
bench.db(une base absente ou cassée est tolérée) et lancer l'enregistreur d'événements race. - 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.
- 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. - Migration ponctuelle pour les configurations qui contiennent encore
[announce_clients](voir Mettre à jour depuis la 3.x). - 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.
- 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.
- 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.
- Windows : écouter la demande d'arrêt de l'outil de mise à jour et afficher l'icône de la zone de notification.
- 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
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.
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).
<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 verrezhydra.db-walethydra.db-shmà côté ; ils font partie du store. - Si le dossier qui contient
hydra.dbest 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=NORMALsignifie 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).
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.
<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.
<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.
<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.
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.tomlavecdata_dir = "/config"(il suitHYDRANOS_CONFIG_DIRsi 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ègledata_dirsur<config dir>/data. Passez--configpour choisir un autre emplacement ; le dossier de configuration etdata_dirsuivent. -
Linux empaqueté : les fichiers
state.dbet 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
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
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.
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/copyavec{"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/engineavec{"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.
| É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.
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.