← Retour au site Chargement…

rescriptum

Référence

Guide

Généré le 30 août 2026

Référence

Référence

La contrepartie exhaustive du reste du guide. Tables et contrats, une page par surface :

Vous cherchez le récit plutôt ? Commencez par ce qu’est rescriptum.

Configuration

Configuration

Des variables d’environnement — et, en option, un fichier d’où les lire, dans l’une de deux formes. Il n’y a pas de ligne de commande à se tromper, et les variables sont toute la configuration : les deux formats de fichier règlent exactement les mêmes choses sous exactement les mêmes règles, donc rien de ce qu’on écrit dans un fichier ne peut signifier quelque chose que l’environnement ne dirait pas.

Les variables

VariableDéfautSignification
RESCRIPTUM_CONFIGnon définiLire les valeurs par défaut depuis ce fichier TOML — voir plus bas
RESCRIPTUM_ENV_FILEnon définiLire les valeurs par défaut depuis ce fichier CLÉ=valeur — voir plus bas
RESCRIPTUM_STOREfilesfiles (un répertoire) ou sqlite (une base)
RESCRIPTUM_ANSWERS_DIR/srv/answersRépertoire des documents de réponse
RESCRIPTUM_DB_PATH/srv/answers.dbChemin de la base, quand RESCRIPTUM_STORE=sqlite
RESCRIPTUM_LISTEN_ADDR0.0.0.0:8000Adresse d’écoute. :0 choisit un port libre, et celui qui est bindé est affiché
RESCRIPTUM_WORKERSnombre de CPUThreads du runtime asynchrone. Pas une limite de concurrence
RESCRIPTUM_MAX_CONNECTIONS2048Connexions en vol avant délestage en 503
RESCRIPTUM_TIMEOUT_SECS10Délai de lecture des en-têtes et échéance de la connexion entière
RESCRIPTUM_ANSWER_TOKENnon définiJeton exigé par l’endpoint de réponse. Non défini = ouvert
RESCRIPTUM_ADMIN_ADDRnon définiListener de l’API d’administration. Non défini = API désactivée
RESCRIPTUM_ADMIN_TOKENnon définiJeton d’administration, 16+ caractères. Obligatoire avec RESCRIPTUM_ADMIN_ADDR
RESCRIPTUM_CAPTURE_DIRnon définiEnregistre les corps de requête ici. Non défini = pas de capture
RESCRIPTUM_LOGallall, problems ou off — voir plus bas
RESCRIPTUM_LOG_FILEnon définiUn fichier où ajouter, ou stdout / stderr. Non défini = stderr
RESCRIPTUM_MEDIA_DIRnon définiImages d’installation. Non défini = pas de média et pas de listener média
RESCRIPTUM_MEDIA_ADDR0.0.0.0:8001Le listener média, quand un répertoire de médias existe
RESCRIPTUM_MEDIA_TIMEOUT_SECS600Échéance du transfert entier. Volontairement pas les 10 s du point de réponse
RESCRIPTUM_MEDIA_MAX_CONNECTIONS16Transferts simultanés. Bas exprès : chacun retient son jeton des minutes durant
RESCRIPTUM_PUBLIC_HOSTdéduitL’hôte que nomment les URL générées. Un hôte, jamais une URL
RESCRIPTUM_BOOT_ALLOWnon définiCIDR clients autorisés à récupérer les médias. Non défini = quiconque atteint le port
RESCRIPTUM_BOOT_DIRnon définiChargeurs et menus, distribués en TFTP. Non défini = pas de TFTP du tout
RESCRIPTUM_TFTP_ADDR0.0.0.0:69Le listener TFTP, ou off pour aucun. Le port 69 est privilégié ; voir RESCRIPTUM_USER
RESCRIPTUM_TFTP_PORT_RANGEnon définiLes ports depuis lesquels un transfert répond, en premier-dernier. Un transfert TFTP quitte le port 69 aussitôt — le serveur répond depuis un port neuf et le client acquitte vers celui-là — donc un pare-feu n’autorisant que 69 jette l’acquittement, et la machine semble s’être désintéressée. Épinglez la plage pour pouvoir l’ouvrir. Non définie, le noyau choisit
RESCRIPTUM_TFTP_BLKSIZE1468Le plus grand bloc TFTP accepté. 1468 remplit exactement un chemin de 1500 octets — 1468 de charge, 4 TFTP, 8 UDP, 20 IP — donc un tag VLAN ou un tunnel rend la trame trop grande et une ROM PXE s’arrête en général sans rien dire. À baisser (1400, ou 512) quand un démarrage cale au premier bloc
RESCRIPTUM_BOOT_TIMEOUT_SECS15Secondes avant que le menu ne retombe sur le disque local
RESCRIPTUM_BOOT_UNCLAIMEDmenuCe que reçoit une machine qu’aucune réponse ne revendique. local la rend à son firmware, ce qui inverse le sens d’un fichier de réponse : présent veut dire installe celle-ci plutôt que laisse celle-ci tranquille
RESCRIPTUM_INSTALLED_TOKENnon définiLe jeton du [post-installation-webhook] de Proxmox. Défini, POST /installed existe et retire la revendication d’installation d’une machine quand elle signale sa réussite. Non défini, il n’y a pas d’endpoint
RESCRIPTUM_BOOT_LOGOintégréUn PNG à afficher derrière le menu
RESCRIPTUM_BOOT_TITLEintégréLa barre de titre du menu
RESCRIPTUM_USER / _GROUPnon définiBasculer dessus après avoir lié. L’ordre inverse échoue au déploiement

/srv est l’endroit où la norme de hiérarchie des fichiers range les données servies par le système, ce qu’est précisément un répertoire de réponses. Les deux valeurs par défaut y vivent, pour qu’un rescriptum lancé sans rien fasse quelque chose de plausible sur n’importe quel hôte Linux. Rien ne crée le répertoire pour vous, et le serveur le signale au démarrage s’il manque.

Journalisation

Une ligne par événement, sur stderr par défaut. Deux réglages, parce que les deux questions sont différentes.

QuoiRESCRIPTUM_LOG :

ValeurGarde
all (défaut)chaque requête, plus le démarrage, les avertissements et les erreurs
problemsdémarrage, avertissements, erreurs, et seulement les requêtes qui n’ont pas abouti
off / nonerien du tout

Une réponse réussie fait une ligne, et à treize mille requêtes par seconde c’est la seule chose ici qui ait du volume. problems est ce que vous voulez quand un déploiement devient routinier et que le disque, lui, ne l’est pas. Tout le reste est peu volumineux et diagnostique, donc conservé dans les deux cas.

Une requête qui n’a jamais atteint de statut — une connexion expirée en plein corps — compte comme un problème. Une valeur non reconnue retombe sur all avec un avertissement : une faute de frappe ne doit pas être la raison pour laquelle personne ne voit pourquoi un déploiement a échoué. Le niveau est nommé dans la ligne de démarrage (log=problems), donc un log vide s’explique lui-même.

RESCRIPTUM_LOG_FILE :

ValeurVa vers
non définie, ou stderrstderr, ce que lit un superviseur
stdoutstdout
toute autre valeurce fichier, en ajout ; les répertoires parents sont créés

Un fichier impossible à ouvrir est une erreur de démarrage, pas un repli sur stderr — ce serait une surprise silencieuse découverte bien plus tard. Une écriture qui échoue une fois le serveur lancé est abandonnée : un serveur de provisioning qui mourrait parce que son disque de logs est plein ferait échouer toutes les installations en cours pour signaler qu’il ne peut pas signaler quelque chose.

La rotation vous incombe. Sous systemd il n’y a rien à faire, le log part dans le journal ; avec un fichier, pointez logrotate dessus avec copytruncate.

Le fichier TOML

RESCRIPTUM_CONFIG nomme un fichier en TOML qui règle les mêmes variables, dans une forme faite pour être lue. C’est celui vers lequel se tourner quand une personne édite le fichier à la main — sur un NAS, dans File Station ou via SMB — c’est-à-dire exactement là où RESCRIPTUM_ANSWERS_DIR=… sur chaque ligne se lit mal, et où le mot « environnement » envoie chercher un shell qui n’existe pas.

# /etc/rescriptum.toml   (chmod 600, appartenant à root)
answers_dir = "/srv/answers"
listen_addr = "0.0.0.0:8000"
log         = "problems"          # all | problems | off

[store]
kind    = "sqlite"
db_path = "/srv/answers.db"

[server]
workers         = 2
max_connections = 2048
timeout_secs    = 10

[admin]
addr  = "127.0.0.1:8001"
token = "…"

[answer]
token       = "…"
capture_dir = "/var/lib/rescriptum/captures"
$ RESCRIPTUM_CONFIG=/etc/rescriptum.toml rescriptum
2026-08-29T12:42:02Z - reading configuration defaults from /etc/rescriptum.toml (8 set)

Toutes les règles du fichier d’environnement valent ici aussi : jamais découvert, seulement nommé (il n’y a pas de ./rescriptum.toml) ; l’environnement réel gagne ; et un fichier demandé et illisible est une erreur de démarrage, jamais un avertissement.

Placez-le hors du répertoire de réponses. Tout .toml servable à la racine de ce répertoire est un document réponse, et ce format partage l’extension — un fichier de configuration déposé là est signalé par check comme une réponse mal placée, et migrate propose de le déplacer. /etc est le foyer évident ; sur une installation empaquetée, le paquet en choisit un.

Les noms

Le préfixe disparaît et les tables font le regroupement. Rien d’autre ne change : chaque ligne ci-dessous est la variable du même nom, et rescriptum config affiche les deux orthographes.

Dans le fichierVariable
answers_dirRESCRIPTUM_ANSWERS_DIR
listen_addrRESCRIPTUM_LISTEN_ADDR
log, log_fileRESCRIPTUM_LOG, RESCRIPTUM_LOG_FILE
public_hostRESCRIPTUM_PUBLIC_HOST
user, groupRESCRIPTUM_USER, RESCRIPTUM_GROUP
store.kind, store.db_pathRESCRIPTUM_STORE, RESCRIPTUM_DB_PATH
server.workers, server.max_connections, server.timeout_secsRESCRIPTUM_WORKERS, RESCRIPTUM_MAX_CONNECTIONS, RESCRIPTUM_TIMEOUT_SECS
admin.addr, admin.tokenRESCRIPTUM_ADMIN_ADDR, RESCRIPTUM_ADMIN_TOKEN
answer.token, answer.capture_dirRESCRIPTUM_ANSWER_TOKEN, RESCRIPTUM_CAPTURE_DIR
media.dir, media.addr, media.timeout_secs, media.max_connectionsles quatre RESCRIPTUM_MEDIA_*
boot.dir, boot.allow, boot.unclaimed, boot.timeout_secs, boot.logo, boot.titleles six RESCRIPTUM_BOOT_*
tftp.addr, tftp.port_range, tftp.blksizeles trois RESCRIPTUM_TFTP_*
installed.tokenRESCRIPTUM_INSTALLED_TOKEN

Le format

N’importe quel scalaire TOMLun nombre peut s’écrire en nombre (workers = 2) ou en chaîne ; les deux arrivent au serveur comme le même réglage
Un commentaire #n’importe où, y compris en fin de ligne — contrairement au fichier d’environnement, qui n’a pas d’échappements et ne peut donc pas en avoir
Une valeur avec un #, un guillemet ou une espacesans problème, échappée comme TOML échappe, et relue à l’identique
""non défini — la même règle qu’une variable exportée mais vide, et c’est ce qui permet à config unset de vider une ligne au lieu de supprimer le paragraphe qui la documente
La même clé deux foisrefusée par TOML lui-même, donc le fichier ne se charge pas
Une clé que ce programme ne lit pasun avertissement la nommant : admin.tokenn est attrapé au lieu d’être ignoré
Une liste ou une table là où une valeur est attendueune erreur de démarrage : contrairement à une faute de frappe, elle visait un réglage réel, et servir la valeur par défaut alors que le fichier dit le contraire serait silencieux
Un fichier lisible par d’autresun avertissement avec son mode, parce qu’il peut contenir admin.token

Les avertissements nomment les clés et les chemins, jamais les valeurs.

Les deux fichiers à la fois

Nommer les deux est une transition plutôt qu’un état stable : rien n’est refusé et l’ordre est annoncé au démarrage — l’environnement bat le fichier TOML, qui bat le fichier d’environnement. rescriptum config montre lequel des trois a mis chaque valeur en vigueur, et config set écrit dans le fichier TOML — celui que le serveur lit en premier, pour qu’une écriture ne puisse pas être une modification qui ne change rien en silence.

Le fichier d’environnement

RESCRIPTUM_ENV_FILE nomme un fichier contenant les mêmes variables. Il existe pour les déploiements qui n’ont nulle part où mettre un jeton — au premier chef Synology DSM 7, qui n’a pas de systemd. Sous systemd, EnvironmentFile= fait déjà cela et vous n’en avez pas besoin.

# /etc/rescriptum.env   (chmod 600, appartenant à root)
RESCRIPTUM_STORE=sqlite
RESCRIPTUM_DB_PATH=/srv/answers.db
RESCRIPTUM_ADMIN_ADDR=127.0.0.1:8001
RESCRIPTUM_ADMIN_TOKEN=
$ RESCRIPTUM_ENV_FILE=/etc/rescriptum.env rescriptum
2026-08-24T12:42:02Z - reading configuration defaults from /etc/rescriptum.env (4 set)

Il n’est jamais découvert, seulement nommé. Il n’y a pas de ./.env. Ce binaire tourne en root : s’il ramassait un fichier dans le répertoire d’où il a été lancé, quiconque peut y écrire posséderait RESCRIPTUM_ADMIN_TOKEN — et avec lui le mot de passe root de chaque machine installée ensuite.

L’environnement réel gagne. Le fichier fournit des valeurs par défaut, donc ce qui est exporté délibérément au lancement n’est jamais écrasé en douce. Une variable exportée mais vide compte comme non définie, donc le fichier s’applique quand même.

Un fichier demandé et illisible est une erreur de démarrage, pas un avertissement. C’est tout l’intérêt : l’échec qu’il remplace est un serveur qui démarre sur ses valeurs par défaut — mauvais répertoire de réponses, pas de jeton admin — sans un mot dans le log.

Le format

CLÉ=valeur, une par ligneun export en tête est accepté, pour que le même fichier puisse aussi être sourceé
# en début de ligneun commentaire
# ailleursfait partie de la valeur. Pas de commentaires en fin de ligne : tronquer un jeton sur un # qu’il contient légitimement serait silencieux, alors qu’un commentaire atterrissant dans une valeur est bruyant
"guillemets" ou 'guillemets'les guillemets sont retirés et les espaces internes conservés ; une valeur sans guillemets est trimée
$HOME, ${x}non développés. Ce n’est pas un shell — pas de substitution, pas de lignes de continuation
la même clé deux foisune erreur de démarrage, plutôt qu’une supposition sur celle qui était voulue
une clé que ce programme ne lit pasun avertissement nommant la clé — RESCRIPTUM_ADMIN_TOKENN est donc attrapé au lieu d’être ignoré
un fichier lisible par d’autresun avertissement avec son mode, parce qu’il peut contenir le jeton admin

Les avertissements nomment les clés et les chemins, jamais les valeurs.

Le lire et le modifier

rescriptum config affiche chaque variable, sa valeur, et qui des fichiers ou de l’environnement l’y a mise — la distinction qui compte, puisque les fichiers fournissent des valeurs par défaut et que l’environnement réel l’emporte. config set modifie le fichier comme on voudrait qu’il le soit, dans l’un ou l’autre format : commentaires conservés, réglage commenté décommenté sur place plutôt que dupliqué (fichier d’environnement) ou valeur remplacée là où elle est (TOML), et refus avant toute écriture d’une modification qui laisserait un serveur incapable de démarrer. C’est documenté dans la référence de la ligne de commande, et c’est ce que l’application DSM pilote dessous.

Valeurs invalides

CasCe qui se passe
Exportée mais vide (RESCRIPTUM_LISTEN_ADDR=)traitée comme non définie — une valeur vide est une erreur, pas une instruction
Uniquement des espacespareil, et les valeurs sont trimées
Un nombre nul ou impossible à parserretombe sur la valeur par défaut, plutôt que de démarrer un serveur qui accepte des connexions sans jamais répondre
RESCRIPTUM_STORE avec toute autre valeurun avertissement, et files est utilisé
RESCRIPTUM_ENV_FILE ou RESCRIPTUM_CONFIG nommant un fichier absent, illisible ou malforméune erreur de démarrage
Un réglage TOML recevant une liste ou une tableune erreur de démarrage, contrairement à une clé mal orthographiée, qui avertit
RESCRIPTUM_STORE=sqlite sur un binaire construit sans la featureune erreur au démarrage

Erreurs de démarrage

Celles-ci arrêtent le serveur au lieu d’avertir, parce que démarrer quand même serait pire :

ConditionPourquoi c’est fatal
RESCRIPTUM_ADMIN_ADDR défini avec RESCRIPTUM_STORE autre que sqlitedeux façons de changer la même configuration, en concurrence
RESCRIPTUM_ADMIN_ADDR défini sans RESCRIPTUM_ADMIN_TOKENune API ouverte qui réécrit les identifiants root
RESCRIPTUM_ADMIN_TOKEN de moins de 16 caractèresassez court pour être deviné
L’adresse d’écoute ne peut pas être bindéerien à faire
Le store ne peut pas être ouvertrien à servir
RESCRIPTUM_MEDIA_ADDR défini sans RESCRIPTUM_MEDIA_DIRun listener sans rien à servir
RESCRIPTUM_MEDIA_ADDR égal à l’adresse de réponse ou d’administrationle second bind perd, et lequel dépend de l’ordre de démarrage
RESCRIPTUM_PUBLIC_HOST portant un schéma, un port ou un cheminil est écrit dans les URL de deux listeners ; un port dans la valeur épingle chaque script généré sur l’un d’eux
RESCRIPTUM_TFTP_ADDR défini sans RESCRIPTUM_BOOT_DIRun listener sans chargeur à distribuer
Le répertoire de démarrage ne peut pas être résoluchaque contrôle de chemin s’y compare
RESCRIPTUM_USER nomme un compte inexistantrien à devenir

Avertissements de démarrage

Ceux-ci sont affichés et le serveur continue :

ConditionLigne
Répertoire de réponses absentwarning: … does not exist yet — every request will 404 until it does
Le chemin existe mais n’est pas un répertoirewarning: … is not a directory — every request will 404 until it is
Répertoire de réponses présent mais illisiblewarning: … cannot be read: … — every request will 404 until that is fixed. La cause la plus probable est un serveur tournant sous un utilisateur qui n’est pas le propriétaire du répertoire
API d’administration hors boucle localewarning: the admin API is not bound to loopback — …
RESCRIPTUM_ANSWER_TOKEN de moins de 16 caractèresun avertissement, pas une erreur — refuser de démarrer laisserait un parc incapable de s’installer
Tout problème dans le jeu de réponsesune ligne warning: chacun, le même jeu que signale check
RESCRIPTUM_PUBLIC_HOST non définiLa réponse de la table de routage, ou l’unique adresse d’interface s’il n’y a pas de route par défaut. Journalisé dans les deux cas, en avertissement nommant les autres adresses s’il y en a. Un hôte derrière du NAT se trompe toujours en silence
TFTP ne peut pas se lierwarning: cannot bind TFTP on … le seul listener dont l’échec de liaison n’est pas fatal. Le port 69 est le seul port privilégié de la conception, donc le seul bind qui puisse échouer pour quelque chose que personne n’a configuré ; les réponses sont le produit, et mourir ferait échouer toutes les installations en cours pour signaler qu’un second port n’a pas pu être ouvert. boot check sort en non-zéro et le message nomme les façons d’obtenir le port
Répertoire de médias absent ou illisibleune ligne warning: media: … — un parc ne doit jamais être incapable de s’installer parce qu’une image est bizarre

Options de compilation

FeatureDéfautEffet
sqliteactivéeLe store SQLite et l’API d’administration
bootactivéeLe catalogue de médias, le lecteur ISO et le listener média

Mesuré sur ARMv7 (gnueabihf, plancher glibc 2.17), les quatre d’affilée le 2026-08-29. Remesurez plutôt que de citer ces chiffres : ils ont bougé d’environ 375 Ko quand cette cible est passée de musl à glibc, et le jeu qu’ils remplacent ici avait dérivé d’environ 200 Ko.

BuildOctets
les deux (défaut)2 813 712
sqlite seule2 557 592
boot seule1 649 048
aucune1 392 544

Limites fixes

Non configurables, et délibérément :

LimiteValeur
Corps de requête1 Moendpoint de réponse — un Content-Length invraisemblable est refusé depuis l’en-tête
Taille d’un document256 KoPUT de l’API d’administration
Requêtes capturées1000 capturescomptées depuis le répertoire au démarrage, donc un redémarrage ne repart pas de zéro
Échecs d’administration avant blocage5 en 60 sle blocage double jusqu’à un maximum de 900 s
Adresses suivies par le garde-fou4096pour qu’il ne puisse pas être transformé en fuite mémoire
Filet de rechargement du listing1 sforce une relecture même quand le mtime du répertoire semble inchangé

Surface HTTP

Surface HTTP

Deux listeners, et ils ne partagent jamais un port. L’endpoint de réponse est ce à quoi parlent les installateurs ; l’API d’administration est désactivée sauf configuration.

L’endpoint de réponse

RequêteRéponse
POST n’importe quel cheminla réponse, typée par son format
GET n’importe quel cheminla même chose
GET /health200 OK, corps OK\n — pas de jeton nécessaire, jamais limité en débit
toute autre méthode405

N’importe quel chemin, parce que l’URL est gravée dans une ISO et que ce serveur n’a pas son mot à dire. Le chemin n’est pas ignoré pour autant : les segments nommant un alias de format restreignent les documents pouvant répondre, et le chemin fournit aussi les faits path, file et segment.

Codes de statut

CodeQuand
200une réponse s’est appliquée
400le corps n’a pas pu être lu
401RESCRIPTUM_ANSWER_TOKEN est défini et la requête ne l’a pas présenté
404rien n’a revendiqué la requête et il n’y a pas de default pour le format demandé
405une méthode autre que GET ou POST
413corps de plus de 1 Mo, ou Content-Length en annonçant un
500un document ne parse pas, un groupe manque, un template n’a pas pu être rempli, ou la recherche a paniqué
503à RESCRIPTUM_MAX_CONNECTIONS — écrit immédiatement, puis la connexion se ferme

En-têtes de réponse

En-têteValeur
Content-Typeselon le format de la réponse — voir la table ci-dessous
Content-Lengthtoujours défini
Connectionclose
WWW-AuthenticateBearer, sur un 401
FormatContent-Type
toml, et tous les formats texte (ks, preseed, cfg, seed, ipxe)text/plain; charset=utf-8
yaml, ymltext/yaml; charset=utf-8
json, ignapplication/json
xml, autoyast, unattendapplication/xml; charset=utf-8

Le TOML est servi en text/plain plutôt qu’en application/toml parce que c’est ce qu’attend l’installateur Proxmox.

Limites de traitement des requêtes

Plafond du corps1 Mo. Un Content-Length invraisemblable est refusé depuis l’en-tête, avant toute lecture — plutôt que d’allouer pour lui et de faire sauter une limite plus tard
Délai de lecture des en-têtesRESCRIPTUM_TIMEOUT_SECS, 10 s par défaut
Échéance de la connexion entièrela même valeur. Les deux sont nécessaires : le délai d’en-têtes s’arrête à la fin des en-têtes, donc un client qui promet un corps sans l’envoyer garerait sinon une connexion indéfiniment
ConcurrenceRESCRIPTUM_MAX_CONNECTIONS en vol ; au-delà, un 503 et fermeture plutôt qu’une mise en file
Authentificationseulement quand RESCRIPTUM_ANSWER_TOKEN est défini. Comparée en temps constant. Les échecs sont journalisés et jamais limités en débit

Authentification

Authorization: Bearer <RESCRIPTUM_ANSWER_TOKEN>

Proxmox l’envoie quand son ISO a été préparée avec --answer-auth-token. Rien d’autre ne le peut, ce qui est pourquoi c’est désactivé par défaut. Voir Sécurité.

L’API d’administration

Un listener séparé, RESCRIPTUM_ADMIN_ADDR, en SQLite uniquement. Détails complets sur sa propre page.

RequêteRôle
GET /machines, GET /groupslister les identifiants
GET /machines/{id}, GET /groups/{name}, GET /defaultle document stocké, tel qu’écrit
PUT /machines/{id}, PUT /groups/{name}, PUT /defaultstocker un document
DELETE /machines/{id}, DELETE /groups/{name}, DELETE /defaulten supprimer un
GET /resolve/{id}la réponse fusionnée que cette machine recevrait
GET /checkles problèmes actuels
GET /healthvivacité — pas de jeton, jamais bloqué

Tous les endpoints de document prennent ?format=<ext>, toml par défaut.

CodeQuand
200fait
400document malformé, identifiant invalide, ou corps non-UTF-8
401jeton manquant ou faux
404document ou endpoint inexistant ; rien ne se résout pour cet identifiant
409l’écriture aurait cassé le jeu de réponses (annulée), ou un resolve qui n’a pas pu rendre
413document de plus de 256 Ko
429cette adresse est bloquée ; Retry-After dit pour combien de temps
500le store n’a pas pu être lu ou écrit

Chaque réponse d’administration définit Connection: close. Un GET /resolve réussi définit aussi X-Answer-Source, portant la même description que la ligne de log.

Journalisation

Une ligne par requête, sur stderr par défaut. RESCRIPTUM_LOG choisit ce qui est gardé et RESCRIPTUM_LOG_FILE où cela va — voir journalisation.

2026-08-24T08:43:37Z 127.0.0.1:61721 POST /answer body=102 200 format=toml machine=98fa9b50d810 group=example-rack bytes=431

Les lignes de niveau serveur portent - là où serait l’adresse du pair. Voir dépannage.

Formats et alias d'endpoint

Formats et alias d’endpoint

Trois tables. La version narrative est dans un document par système d’exploitation.

Extensions de document

La liste blanche des extensions que rescriptum ramassera dans un store. Tout le reste est ignoré — txt n’y est délibérément pas, pour qu’un fichier de notes égaré à côté de vos réponses ne devienne jamais un candidat.

ExtensionFamilleSuperpositionContent-Type
tomlTOMLfusion structurelletext/plain; charset=utf-8
yaml, ymlYAMLfusion structurelletext/yaml; charset=utf-8
json, ignJSONfusion structurelleapplication/json
xml, autoyast, unattendXMLfusion structurelle, par élémentapplication/xml; charset=utf-8
ks, cfg, preseed, seed, ipxetexteconcaténation dans l’ordre des couchestext/plain; charset=utf-8

La famille est ce que remonte le champ format= de la ligne de log, donc ks et preseed apparaissent tous deux en format=text. L’extension est ce sur quoi un endpoint filtre, et ce dont check a besoin pour choisir le bon validateur.

Alias d’endpoint

Un segment de chemin nommant l’un de ceux-ci restreint la réponse aux documents portant les extensions listées. N’importe quel segment du chemin peut le nommer, donc /rhel/ks, /ks et /provision/rhel/node.cfg restreignent tous au kickstart.

SegmentSertUsage typique
proxmox, pve, toml.tomlProxmox VE
debian, preseed.preseed, .seedpreseed Debian
rhel, centos, fedora, alma, rocky, kickstart, ks.kskickstart
ubuntu, autoinstall, cloudinit, nocloud, yaml, yml.yaml, .ymlautoinstall Ubuntu, cloud-init
flatcar, coreos, ignition, ign.ign, .jsonIgnition
suse, opensuse, autoyast.autoyast, .xmlAutoYaST
windows, unattend.unattend, .xmlunattend.xml Windows
json.json, .ign
xml.xml
cfg.cfg
ipxe.ipxe

Un segment n’en nommant aucun ne contraint rien, ce qui est pourquoi /answer continue de fonctionner exactement comme avant.

Deux pièges dans cette table

  • Le filtrage porte sur l’extension, pas sur la famille. .ks et .preseed sont tous deux des documents texte ; filtrer par famille laisserait un preseed répondre à /rhel/ks.
  • seed n’est délibérément pas un alias. s=http://server/seed/ est une URL de seed NoCloud parfaitement ordinaire, et elle sert du YAML. Un alias doit être assez spécifique pour que personne ne l’atteigne par accident. (L’extension .seed existe toujours, et /debian/ la sert.)

Clés de contrôle, par format

Retirées avant que la réponse ne soit envoyée.

FormatÉcriture
TOMLextends = "base", members = […], table [match], au premier niveau
YAMLextends:, members:, match: au premier niveau
JSON"extends", "members", "match" au premier niveau
XML<answer-meta extends="base"><member>…</member><match k="v" /></answer-meta>
Texte# answer: extends <nom> · # answer: member a, b · # answer: match k=v k2=v2

Les directives texte acceptent aussi // comme marqueur de commentaire. match prend des paires clé=motif séparées par des espaces ; member une liste séparée par des virgules. Les commentaires ordinaires d’un document texte sont servis — seules les lignes # answer: sont retirées.

Sémantique de fusion

Formats structurésFormats texte
Maps / objets / élémentsfusionnent récursivement
Scalairesla couche supérieure remplace
Tableaux / listesremplacent, jamais de concaténation
Document entierconcaténé dans l’ordre des couches

XML apparie les frères par nom d’élément plus un attribut discriminant — name, id, key, alias, pass — et respecte config:type="list". Déclarations, doctypes, espaces de noms et attributs survivent à une fusion ; l’indentation d’origine et le placement des commentaires, non.

Validateurs que check peut appeler

FormatOutilInvoqué comme
tomlproxmox-auto-install-assistantvalidate-answer <fichier>
xml, autoyast, unattendxmllint--noout <fichier>
ksksvalidator<fichier>
tout le resteaucun n’existe

Un outil absent du PATH est signalé une fois comme note, jamais comme un échec.

Ligne de commande

Ligne de commande

Sans argument, rescriptum lance le serveur. Tout le reste est une sous-commande.

CommandeRôle
rescriptumlancer le serveur
rescriptum render <id>afficher la réponse que cet identifiant recevrait
rescriptum render --body FICHIER…pour un corps de requête capturé
rescriptum render --query Q…pour des étiquettes, p. ex. "mac=aa:bb&serial=7ABC1"
rescriptum checkrendre tout le store configuré et signaler ce qui casse
rescriptum import <dir>copier un répertoire de documents dans le store configuré
rescriptum export <dir>écrire le store configuré comme un répertoire de documents
rescriptum migrate [<dir>]montrer ce que deviendrait un répertoire de réponses plat
rescriptum migrate --applydéplacer ces documents dans un répertoire chacun
rescriptum configafficher la configuration, et d’où vient chaque valeur
rescriptum config --jsonla même chose, pour un panneau de réglages
rescriptum config --value CLÉune valeur, pour un script — jamais un identifiant
rescriptum config set C=V …éditer le fichier que RESCRIPTUM_CONFIG ou RESCRIPTUM_ENV_FILE nomme
rescriptum config unset CLÉ …y retirer un réglage
rescriptum --helpusage et variables d’environnement

Toutes lisent les mêmes variables d’environnement, dont RESCRIPTUM_CONFIG et RESCRIPTUM_ENV_FILE — résolus en premier, donc un fichier illisible arrête toute commande ayant besoin de la configuration. --help et --version répondent avant sa lecture, parce que ce sont les commandes qu’on lance quand quelque chose ne va pas. Il n’y a pas d’options globales.

render

$ rescriptum render 98:fa:9b:50:d8:10
$ rescriptum render --query "serial=7ABC123&mac=98:fa:9b:50:d8:10"
$ rescriptum render --query "path=/rhel/ks&serial=7ABC123"
$ rescriptum render --body /var/log/rescriptum-captures/2026…-0000.body
FormeFaits fournis
<id>l’identifiant comme botte de foin, et rien d’autre — assez pour correspondre par nom, pas assez pour un sélecteur sur serial
--query "k=v&k2=v2"ces étiquettes, décodées. path= fournit aussi file et segment, et contraint le format comme le ferait une vraie URL
--body FICHIERle fichier verbatim : botte de foin, plus le JSON aplati s’il parse comme du JSON
  • Le document part sur stdout ; la ligne # format=… machine=… group=… expliquant comment il a été obtenu part sur stderr. Donc render … > answer.toml ne donne que le document.
  • Les problèmes de chargement sont d’abord affichés comme lignes warning:.
  • Sortie 0 quand quelque chose s’est résolu, 1 quand rien ne s’appliquait (le serveur aurait renvoyé un 404) ou que le rendu a échoué.

check

$ rescriptum check

Signale les problèmes de chargement, rend chaque document machine et chaque membre de groupe, nomme les groupes qui sélectionnent sur un bloc match (qu’il ne peut pas essayer sans vraie requête), et appelle le validateur de l’installateur là où il est dans le PATH.

Sortie 0 quand tout se rend, 1 dès que quelque chose a échoué — il tombe donc tel quel dans une CI. Voir validation.

import / export

$ RESCRIPTUM_STORE=sqlite RESCRIPTUM_DB_PATH=/srv/answers.db rescriptum import /srv/answers
$ RESCRIPTUM_STORE=sqlite RESCRIPTUM_DB_PATH=/srv/answers.db rescriptum export /tmp/backup

import lit un répertoire et écrit dans le store configuré ; export fait l’inverse. L’aller-retour est identique octet pour octet, chemins compris. Aucun des deux ne lance check pour vous — la sortie vous le dit.

migrate

Les réponses étaient des fichiers à la racine du répertoire de réponses — 98fa9b50d810.toml à côté de 98fa9b50d810.preseed. Elles ont désormais un répertoire chacune, et un document resté à plat est signalé et non servi. Cette commande les déplace :

$ rescriptum migrate
migrating /srv/answers
  98fa9b50d810.toml -> 98fa9b50d810/proxmox.toml
  98fa9b50d810.ipxe -> 98fa9b50d810/boot.ipxe
  groups/rack-a.toml -> groups/rack-a/proxmox.toml
  default.toml -> default/proxmox.toml
  4 document(s) to move — nothing has been changed. Re-run with --apply.

Elle montre par défaut et ne déplace que si on le lui demande. Le répertoire de réponses est ce à partir de quoi une baie s’installe ; taper la commande pour savoir ce qu’elle ferait ne doit pas le réorganiser.

--apply effectue les déplacements, chacun un rename dans le même répertoire, si bien qu’aucun document n’est jamais réécrit. Si une destination est déjà prise, rien ne bouge du tout — y compris les documents qui auraient pu — et les collisions sont nommées : un répertoire à moitié migré est l’état sur lequel personne ne peut raisonner. Elle prend un répertoire en argument, RESCRIPTUM_ANSWERS_DIR par défaut, et sur un répertoire déjà migré elle dit qu’il n’y a rien à déplacer.

config

La configuration, ce sont des variables d’environnement, et sur un déploiement qui les lit depuis un fichier — une installation par paquet, surtout — voici comment les voir et les changer sans ouvrir d’éditeur. C’est aussi ce que l’application DSM exécute dessous.

$ rescriptum config
env file: /var/packages/rescriptum/etc/rescriptum.env

  RESCRIPTUM_STORE            files                             default
  RESCRIPTUM_ANSWERS_DIR      /volume1/netboot/answers          file
  RESCRIPTUM_LISTEN_ADDR      0.0.0.0:9000                      environment
  RESCRIPTUM_ADMIN_TOKEN      (set)                             file

La troisième colonne est l’essentiel. Les fichiers fournissent des valeurs par défaut et l’environnement réel l’emporte : une valeur marquée environment ne peut donc pas être changée en éditant un fichier — et config set le dit, plutôt que de vous laisser écrire quelque chose que le serveur en cours continuera d’ignorer. Avec un fichier TOML la colonne affiche toml file, et nommer les deux fichiers affiche les deux chemins ainsi que l’ordre dans lequel ils l’emportent.

config set écrit dans le fichier TOML quand les deux sont nommés, parce que c’est celui que le serveur lit en premier : écrire l’autre serait une modification qui ne change rien en silence.

Un identifiant n’est jamais affiché, sous aucune forme de cette commande. Un jeton apparaît comme (set) ou (not set) ; --value refuse tout net.

$ rescriptum config set RESCRIPTUM_LOG=problems RESCRIPTUM_CAPTURE_DIR=/srv/captures
wrote /var/packages/rescriptum/etc/rescriptum.env

L’écriture laisse le fichier tel qu’il est par ailleurs : les commentaires restent, un réglage est remplacé là où il se trouve, et un réglage commenté est décommenté sur place plutôt qu’ajouté en dessous — ce qui compte quand le commentaire au-dessus est la seule documentation qu’a le fichier. Dans un fichier TOML, le même soin s’applique au document : la valeur est remplacée là où elle est, son commentaire de fin de ligne survit, et config unset vide la valeur au lieu de supprimer la ligne, pour que le paragraphe qui explique le réglage reste en place.

Deux refus sont délibérés :

  • Une modification qui laisserait un serveur incapable de démarrer est refusée, en bloc, avant toute écriture. Activer l’API d’administration sans jeton, ou avec un jeton de moins de 16 caractères, vous vaut la raison plutôt qu’un prochain démarrage cassé.
  • Une variable mal orthographiée est refusée. Écrite, elle serait relue comme une inconnue et signalée au démarrage suivant, quand plus personne ne fait le lien.

Contrairement à toutes les autres sous-commandes, celle-ci fonctionne quand la configuration est trop cassée pour démarrer un serveur — un fichier qui ne parse pas, un jeton d’un caractère trop court. C’est l’état dont on se sert d’elle pour sortir.

media

Les médias de démarrage : les images d’installation que ce serveur détient. Chacune de ces commandes exige RESCRIPTUM_MEDIA_DIR ; sans elle, elles le disent et sortent en 1. Voir Servir les médias de démarrage.

$ rescriptum media list                    # ce qui est détenu : famille, architecture, version, empreinte
$ rescriptum media add FILE [--sha256 D]   # enregistrer une image déjà dans le répertoire
$ rescriptum media add URL --sha256 D      # la récupérer dedans, puis l'enregistrer
$ rescriptum media check                   # revérifier chaque empreinte enregistrée
$ rescriptum media ipxe ID                 # imprimer la réponse .ipxe qui démarre une image
$ rescriptum media prepare ID [--url URL]  # une image Proxmox avec son URL de réponse dedans
$ rescriptum media export ID FICHIER       # matérialiser une entrée préparée, pour une clé

media add prend un fichier déjà dans le répertoire de médias — rien n’est téléchargé et rien n’est copié. Il le hache avec une progression, l’analyse, et écrit un fichier compagnon .media à côté. --sha256 est vérifié avant tout enregistrement : un écart n’écrit rien et sort en 1.

Le code de sortie de media check est un contrat, comme celui de check. deploy.sh s’y fie.

media ipxe imprime sur stdout et met tout le reste sur stderr, de sorte que rescriptum media ipxe pve-8.4 > groups/rack-a/boot.ipxe produit un document de réponse utilisable — ce qu’il est, rien de plus. Il imprime un script, il n’en installe pas.

boot

La moitié démarrage réseau : les chargeurs de TFTP, la configuration DHCP générée, et les deux scripts qu’une machine exécute. Voir Démarrer une machine par le réseau.

$ rescriptum boot dhcp-snippet [--format F] [--one-loader]
$ rescriptum boot check        # les chargeurs qu'un extrait nomme sont-ils sur le disque ?
$ rescriptum boot bootstrap    # imprimer le script de l'étape deux
$ rescriptum boot menu         # imprimer le menu intégré

--format vaut dnsmasq (par défaut), isc, kea, powershell, pfsense ou mikrotik. L’extrait part sur stdout et les avertissements sur stderr, de sorte que boot dhcp-snippet > dhcpd.conf produit un fichier incluable tel quel.

Le code de sortie de boot check est un contrat, comme celui de check. Ce qu’il attrape est la panne la moins diagnosticable de la chaîne : un extrait nommant un chargeur absent du disque échoue silencieusement au niveau de la ROM, sans rien sur aucune console. Il signale aussi que le listener média a quitté le port que les chargeurs distribués ont gravé.

boot bootstrap et boot menu impriment ce qu’une machine exécutera, pour la même raison que render imprime une réponse : tout ce qu’une baie exécute devrait d’abord être lisible par un humain.

Codes de sortie

CodeSignifie
0succès
1la commande a échoué — rien ne s’est résolu, un document ne parse pas, le store n’a pas pu être ouvert

config est la seule à avoir un second sens : 0 dit que la configuration en est une sur laquelle le serveur démarrerait, 1 qu’elle ne l’est pas — ou qu’une écriture a été refusée. Cela la rend utilisable depuis un script, comme check.

Le serveur lui-même sort en 0 sur SIGTERM ou Ctrl-C, et en 1 s’il ne peut pas binder ou ouvrir le store.