Déploiement serveur
Faire tourner un nœud, un relai et la passerelle sur un serveur (NixOS).
Contenu généré par IA. Cette page a été rédigée avec l’aide d’une IA et n’a pas encore été entièrement relue — elle peut comporter des imprécisions.
Cette page décrit un déploiement serveur complet à
partir du flake Nix du dépôt : l’indexeur
(trame-noded), le relai
(trame-relay), la passerelle HTTP
(trame-gateway, optionnelle), et le service des ressources
statiques (le bundle web et ce site). Pour simplement
installer un pod clé en main, voir plutôt Serveur.
Les composants
| Composant | Rôle | Exposé sur |
|---|---|---|
trame-noded |
nœud p2p : stocke et indexe la donnée, se synchronise via iroh | rien en entrée (sort en UDP/QUIC) |
trame-relay |
relai iroh pour les clients sans UDP direct (navigateur web, NAT strict) | HTTP(S)/WebSocket |
trame-gateway |
passerelle HTTP : sert un bloc par CID
(/ipfs/<cid>), permaliens inspectables sans charger
l’app ; découplée (store propre, résout les CID absents
via le ticket du nœud) |
HTTP |
| bundle web + ce site | fichiers statiques | HTTP(S) |
Le flake expose tout : packages.trame-noded /
trame-relay / trame-gateway, les images OCI
(oci-image, relay-oci-image,
gateway-oci-image), packages.site, et les
modules NixOS nixosModules.trame-noded /
trame-relay / trame-gateway.
Prérequis (flake)
Ajoutez le dépôt comme entrée de votre configuration NixOS :
{
inputs.trame.url = "git+https://git.duniter.org/HugoTrentesaux/datapod";
# ... puis dans les modules de l'hôte :
imports = [
inputs.trame.nixosModules.trame-noded
inputs.trame.nixosModules.trame-relay
];
}Nœud indexeur
(trame-noded)
services.trame-noded = {
enable = true;
# dataDir : état du nœud (blocs + index). Défaut /var/lib/trame-noded.
network = "g1"; # étiquette de réseau gossip (topic des annonces)
wan = true; # profil complet (relais + découverte iroh)
admin = "<clé-publique-admin>"; # gouvernance : la seule clé de confiance à l'amorçage
stateCar = "/chemin/genesis.car"; # état de référence initial (optionnel)
follow = [ "<ticket-de-pair>" ]; # pairs à suivre (resync périodique)
relay = "https://relay.exemple.org"; # se rend joignable via CE relais (clients web)
ticketFile = "/run/trame-noded/node.ticket"; # publie son ticket (pour la passerelle / le build web)
# listenPort = 4001; openFirewall = true; # pour un port UDP fixe reproductible
};Le nœud n’expose aucun port entrant à ouvrir : il
sort en UDP/QUIC et passe par les relais iroh en wan.
Options complètes : voir nix/trame-noded-module.nix.
Amorcer avec des données :
stateCar ou
carDir/importCars
Deux mécanismes distincts pour démarrer peuplé — ne pas les confondre :
| Option | Drapeau | Effet |
|---|---|---|
stateCar |
--state |
Adopte un CAR verbatim : son root
devient le root du nœud (O(1), sans re-dérivation).
C’est l’arbre entier initial — données + éventuelle
charte d’admission signée déjà incluses → nœud conforme dès le
boot. Le CAR doit être une racine de nœud
(geopod-base). |
carDir / importCars |
--car-dir / --import-car |
Fusionne des CAR de données brutes
par-dessus l’état courant (chargement forcé, sans re-validation).
N’apporte pas de charte — variante « données seules ».
Accepte aussi un arbre d’index nu (geopod-index). |
Règle simple : stateCar = état de référence
complet (une seule racine adoptée), carDir
= ajouter des données par-dessus. stateCar est
appliqué avant les fusions. Voir aussi la génération de ces
CAR.
Relai
(trame-relay) — deux montages
Le relai parle HTTP/WebSocket. Deux cas :
A. Le serveur dédie 80/443 au relai (TLS natif)
Le relai gère lui-même le certificat :
services.trame-relay = {
enable = true;
hostname = "relay.exemple.org";
tlsCert = "/var/lib/acme/relay.exemple.org/fullchain.pem";
tlsKey = "/var/lib/acme/relay.exemple.org/key.pem";
openFirewall = true; # ouvre 80/443
};B. Un reverse-proxy occupe déjà 80/443 (recommandé ici) — sous-domaine dédié
C’est le cas quand Caddy (ou nginx) tient déjà 80/443 sur l’hôte. Un sous-domaine dédié au relai règle le conflit : le relai tourne en plaintext sur un port local, et le reverse-proxy termine le TLS et relaie le WebSocket.
services.trame-relay = {
enable = true;
httpBind = "127.0.0.1:8090"; # plaintext, local uniquement
# pas de tlsCert/tlsKey, pas d'openFirewall : c'est Caddy qui expose
};Caddy (le sous-domaine relay.exemple.org → relai local)
:
relay.exemple.org {
reverse_proxy 127.0.0.1:8090
}
Caddy obtient le certificat automatiquement et transmet le
WebSocket de façon transparente ; les clients (navigateur) se
connectent en wss://relay.exemple.org. C’est cette URL
qu’on met dans le TRAME_RELAY de la flavor de l’app
web.
Passerelle HTTP
(trame-gateway, optionnelle)
Utile pour des permaliens inspectables
https://…/ipfs/<cid> sans charger l’app (le modèle
par défaut étant que le navigateur fait tourner un nœud WASM).
Modèle découplé (ne PAS partager le répertoire du
nœud). La passerelle ouvre son propre
répertoire de données, qu’elle doit pouvoir écrire : à
l’ouverture, elle y pose ses schémas d’amorçage et son fichier
root. Un montage/dossier en lecture seule
échoue (Read-only file system, puis
Permission denied) — c’est le piège à éviter. Elle ne lit
pas le store du nœud : pour servir un CID qu’elle n’a
pas, elle le résout via iroh en suivant le ticket du
nœud (peers / peerFile), rapatrie le
bloc dans son propre store, puis le sert. Nœud et passerelle sont donc
deux services indépendants reliés par le réseau, pas
par un dossier.
Course au démarrage.
peerFilen’est lu qu’une fois, au boot. Démarrez la passerelle après que le nœud a écrit son ticket : pointezservices.trame-noded.ticketFileetservices.trame-gateway.peerFilesur le même chemin, et ordonnancez l’unité passerelle après le nœud (after). Sinon la résolution réseau reste désactivée jusqu’au prochain redémarrage.
Module NixOS (nixosModules.trame-gateway), derrière
Caddy :
services.trame-noded.ticketFile = "/run/trame-noded/node.ticket"; # le nœud publie son ticket
services.trame-gateway = {
enable = true;
# dataDir : store PROPRE, inscriptible. Défaut /var/lib/trame-gateway (géré).
peerFile = "/run/trame-noded/node.ticket"; # suit le ticket du nœud pour résoudre les CID
bind = "127.0.0.1"; # local ; Caddy expose
publicHost = "ipfs.exemple.org"; # isolation par sous-domaine <cid>.ipfs.<host>
};
# Démarrer après le nœud (le ticket doit exister quand la passerelle boote) :
systemd.services.trame-gateway = {
after = [ "trame-noded.service" ];
wants = [ "trame-noded.service" ];
};ipfs.exemple.org {
reverse_proxy 127.0.0.1:8480
}
Image OCI équivalente : gateway-oci-image (monter un
/data inscriptible, passer le ticket du
nœud en --peer/--peer-file, publier le port
8480).
Servir le bundle web et ce site (statiques)
Les deux sont des fichiers statiques :
- Ce site :
nix build .#site→ un dossier HTML à servir tel quel. - Bundle web : l’asset
geopod-web.tar.gzde la release (récupérable par hash), à décompresser et servir statiquement.
exemple.org {
root * /var/www/site # nix build .#site
file_server
}
app.exemple.org {
root * /var/www/web # geopod-web.tar.gz décompressé
file_server
try_files {path} /index.html
}
Le build web (
nix run .#build-web) est actuellement impur (toolchain nightly + réseau, hors sandbox Nix) : côté infra, s’appuyer sur l’assetgeopod-web.tar.gzde la release (fetché par hash) plutôt que sur une dérivation. Une dérivation pure est prévue.
Chaîne bout-en-bout : navigateur → relai → nœud
Un navigateur n’a pas d’UDP direct : pour qu’une app web rejoigne un nœud, le relai sert de point de rendez-vous WebSocket. Les trois briques se câblent ainsi :
- Le nœud s’annonce via le relai.
services.trame-noded.relay = "https://relay.exemple.org": le nœud se rend joignable par ce relai. Il publie aussi son ticket (ticketFile). - Le relai termine le TLS derrière Caddy. Il tourne
en plaintext local (
httpBind = "127.0.0.1:8090"), Caddy exposewss://relay.exemple.org(section Relai B). - L’app web est buildée avec le relai + le ticket du
nœud. Le bundle statique fige
GC_SYNC=wss://relay.exemple.org|<ticket-du-nœud>(ou l’équivalent flavorTRAME_RELAY+TRAME_BOOTSTRAP), cf. Démo web. Le ticket est celui écrit par le nœud dansticketFile.
navigateur (app web, nœud WASM)
│ wss://relay.exemple.org (GC_SYNC = relais | ticket, figé au build)
▼
Caddy ──► trame-relay (127.0.0.1:8090, plaintext)
│ relaie le canal iroh
▼
trame-noded (relay = https://relay.exemple.org, joignable via le relai)
Résultat : l’app web démarre peuplée (sync initiale via le relai) et se met à jour, sans qu’aucun port UDP ne soit exposé.
Récapitulatif DNS
| Nom | Cible | Sert |
|---|---|---|
exemple.org |
Caddy → .#site |
le site de présentation |
app.exemple.org |
Caddy → bundle web | l’app web (nœud WASM) |
relay.exemple.org |
Caddy → 127.0.0.1:8090 |
le relai iroh (wss) |
ipfs.exemple.org |
Caddy → 127.0.0.1:8480 |
la passerelle (permaliens par CID, optionnel) |
Le nœud indexeur, lui, n’a pas besoin d’entrée DNS entrante.