- SteamOS 3 « Holo » est une distribution basée sur Arch pour le Steam Deck, mais pour corriger le problème de reprise après suspension sur un PC de salon, il a fallu annuler un commit du noyau et forker directement jusqu’à l’image rootfs
- La structure de mise à jour suit un schéma A/B qui installe un nouveau rootfs en lecture seule sur la partition inactive avant de redémarrer, et
/etcconserve les modifications via overlayfs - Les patchs du noyau de Valve suivent un flux où l’on clone un dépôt Git bare à partir d’un tarball source du miroir pacman, comme
linux-neptune-61-6.1.52.valve9-1.src.tar.gz, puis où l’on construit le paquet avec ses propres tags et un PKGBUILD - Le reconditionnement du rootfs consiste à extraire
rootfs.img.caibxd’un bundle RAUC SteamOS, à le convertir en image, puis à le rebundler en bundle RAUC après changement de l’UUID Btrfs, remplacement de paquets, modification dubuildid, et remplacement de l’URL de mise à jour et du certificat RAUC - Un serveur web maison peut fournir
live.json, et en modifiantQueryUrl,ImagesUrletMetaUrldesteamos-atomupd, même une installation SteamOS existante peut être mise à jour vers sa propre image
Pourquoi j’ai forké SteamOS pour l’adapter à un PC de salon
- SteamOS 3 « Holo » est une distribution Linux basée sur Arch pour le Steam Deck, la console/PC portable de Valve Software
- Son mode de mise à jour repose sur une mise à jour atomique A/B : un nouveau rootfs en lecture seule est téléchargé sur la partition inactive, puis le système redémarre dessus
- L’utilisateur peut exécuter
steamos-devmodepour désactiver le verrouillage du rootfs et rétablir la base de données pacman, ce qui permet de manipuler le système comme une distribution Linux classique - L’objectif n’était pas de contourner facilement le système via
steamos-devmode, mais de créer un véritable fork capable de modifier directement l’image rootfs - Sur le PC de salon, SteamOS fonctionnait presque entièrement, à l’exception de la reprise après suspension
- Sur la même machine, d’autres distributions utilisant le noyau mainline ou stable reprenaient correctement après suspension
- Après avoir retrouvé les sources du noyau Valve et lancé un
git bisect, il est apparu qu’un commit censé corriger la reprise sur le matériel du Steam Deck causait ici le problème - Le besoin d’annuler ce commit et de recompiler le noyau a été la raison directe de tout ce travail
- Utiliser directement Arch ou une autre distribution restait possible, mais s’il fallait de toute façon ajuster une distribution Linux destinée au jeu, il semblait préférable de s’appuyer sur l’ensemble de paquets testé par Valve
Structure des partitions et des mises à jour de SteamOS
- Le système SteamOS utilise 8 partitions
- La partition système EFI contient le bootloader de niveau 1 et les métadonnées servant à choisir entre les ensembles de partitions A/B
- Chaque ensemble A/B contient GRUB comme bootloader de niveau 2, le système de fichiers root et une partition
/var - Le reste du disque est occupé par une unique partition
home
- Au démarrage, plusieurs pseudo-systèmes de fichiers sont montés en plus
- Près de 12 répertoires, comme
/var/log,/rootet/nix, sont bind mount depuis/home/.steamos/offloadpour persister les données
- Près de 12 répertoires, comme
/etcest géré avec overlayfs- Les modifications sont stockées dans
/var/lib/overlays/etc/upper - Les éléments qui doivent normalement rester dans
/etc, commemachine-idou les connexions NetworkManager, sont conservés - Les fichiers de configuration non modifiés peuvent être mis à jour
- Cette méthode permet de gérer à la fois la conservation des réglages et les mises à jour dans une structure de partitions A/B, sans logique de gestionnaire de paquets
- Les modifications sont stockées dans
- La mise à jour système démarre quand le client Steam ou un utilisateur en terminal exécute
steamos-update- Cette commande lance le programme Python
steamos-atomupd-client - Le client envoie les informations de l’OS courant et le canal de mise à jour choisi par l’utilisateur à l’URL définie dans
/etc/steamos-atomupd/client.confpour vérifier si une nouvelle mise à jour est disponible
- Cette commande lance le programme Python
- Si une nouvelle mise à jour existe, le serveur renvoie le chemin d’un bundle RAUC
- Le client télécharge le bundle puis exécute
rauc install - RAUC vérifie la signature du bundle et cherche
rootfs.img.caibx casync extracttélécharge les nouveaux fragments d’image et les écrit sur la partition rootfs inactive- Le script post-install synchronise sélectivement des données depuis le
/varactif vers le/varinactif, puis modifie la configuration du bootloader de niveau 1 dans la partition système EFI pour démarrer sur le nouvel ensemble de partitions
- Le client télécharge le bundle puis exécute
Construire un paquet à partir des sources du noyau Valve
- Valve utilise dans SteamOS un noyau Linux fortement modifié, et ses sources sont téléchargeables
- Les sources de l’image SteamOS actuelle se trouvent dans
sources/holo-3.5etsources/jupiter-3.5sur le miroir pacman de Valve - Au moment de la rédaction, le noyau de l’image stable est
6.1.52-valve9-1-neptune-61, et le tarball source correspondant pèse 2.9 GiB - Si le tarball est aussi gros, c’est parce qu’il contient l’intégralité de l’arbre Git Linux
- On y trouve
PKGBUILD,config,config-neptune,archlinux-linux-neptune/, etc. archlinux-linux-neptune/n’est pas un working tree classique directement exploitable, mais un dépôt bare
- On y trouve
- Le PKGBUILD désigne comme source un dépôt GitLab privé sous la forme
git+ssh://git@gitlab.steamos.cloud/jupiter/linux-integration.git#tag=$_tag- Il n’est pas possible de le cloner directement ni de lier un commit
- En revanche, les sources de
makepkgpermettent d’obtenir un instantané contenant tout l’historique des commits de chaque tag - C’est grâce à cette structure qu’il a été possible de bisecter le commit qui cassait la suspension du PC de salon
- La méthode de travail consiste à cloner le dépôt bare en working tree normal, puis à maintenir sa propre branche et ses propres tags
- L’exemple montre la création de
my-branchà partir du tag6.1.52-valve9 - Les modifications sont poussées vers un hôte Git séparé, et la source du PKGBUILD est changée pour pointer vers ce dépôt et ces tags personnalisés
- Un dépôt d’exemple est disponible ici : linux
- L’exemple montre la création de
- Il est ensuite possible de construire le paquet du noyau avec
makepkgmakepkg MAKEFLAGS=-j$(nproc)ou la mise à jour de/etc/makepkg.confsont utiles si l’on n’est pas sur une petite VM- Dans le périmètre observé, les paquets spécifiques à SteamOS utilisaient eux aussi une structure comparable avec un dépôt Git comme première source
- Pour simplifier les étapes suivantes, un dépôt pacman personnel a été mis en place
- Il suffit de placer les paquets dans un répertoire, d’exécuter
repo-add $REPO_NAME.db.tar.zst [PACKAGES...], puis d’envoyer le tout sur un hébergement web - Ce dépôt aide aussi les outils à fonctionner correctement plus tard si
steamos-devmodeest exécuté
- Il suffit de placer les paquets dans un répertoire, d’exécuter
Récupération et montage du système de fichiers root
- Comme les scripts de release engineering n’ont pas été retrouvés, le choix a été fait de repackager le système de fichiers root existant selon les besoins
- Des scripts sans explication ni commentaires sont disponibles dans fauxlo
- La manière habituelle d’obtenir une image rootfs SteamOS est soit d’acheter un Steam Deck, soit de télécharger l’image de récupération du Steam Deck, mais les deux exigent d’accepter le Steam End User License Agreement
- La version de release actuelle peut être trouvée dans un snapshot JSON qui semble servir d’URL de secours au système de mise à jour
- Au moment de l’écriture, la version stable était
20231122.1 - Il existe aussi un snapshot JSON distinct pour le canal preview
- Au moment de l’écriture, la version stable était
- Le téléchargement du rootfs suit la même séquence que
steamos-atomupd-client- Téléchargement du fichier
.raucb, qui est le bundle RAUC - Extraction de
rootfs.img.caibxdepuis ce bundle, qui est un système de fichiers SquashFS - Création de
rootfs.imgaveccasync extractà partir des fragments stockés dans un store.castr - L’URL du store
.castrs’obtient en remplaçant.raucbpar.castrdans l’URL du bundle RAUC - Ce comportement est codé en dur dans
steamos-atomupd - Un script d’automatisation est disponible ici : fetch-current.sh
- Téléchargement du fichier
- Les fichiers voisins
.img.zipet.img.zstne sont pas le rootfs mais des images de récupération bootables distinctes- Il est possible d’en extraire la partition rootfs pour les étapes suivantes
- Mais elle n’était pas identique bit à bit à l’image obtenue via RAUC et casync, et ces outils seront de toute façon nécessaires pour recréer ensuite un bundle de mise à jour
- Avant de modifier le rootfs, il faut changer l’UUID du système de fichiers
- Sans cela, lors d’une mise à jour depuis une image SteamOS d’origine vers une image personnalisée, deux systèmes de fichiers différents partageraient le même UUID
- Cette situation peut poser problème
- Exemple :
btrfstune -fu rootfs.img
- Valve utilise une image Btrfs compressée en zstd
- Pour conserver la compression pendant les modifications, on la monte avec
mount -o compress=zstd rootfs.img rootfs - SteamOS utilise l’attribut de sous-volume Btrfs
readonly, qu’il faut désactiver viabtrfs property set -ts rootfs ro false
- Pour conserver la compression pendant les modifications, on la monte avec
- Modifier des paquets comme le noyau Linux peut déclencher des scripts qui exigent
/devet/proc- Il faut monter
devtmpfsetprocsous le rootfs - Pour éviter toute écriture dans des répertoires qui seront montés sur le système démarré, on monte des tmpfs sur
/tmp,/run,/varet/home - Pour permettre la résolution de noms dans le chroot, on bind mount le
/etc/resolv.confde l’hôte
- Il faut monter
Remplacement de paquets et modification des métadonnées de l’image
- Le dépôt personnel est ajouté comme premier dépôt dans
/etc/pacman.conf- Cela lui donne la priorité même si le dépôt Valve contient des versions plus récentes
- Et cela permet de réinstaller ses propres paquets plus tard, même après exécution de
steamos-devmode
- L’exemple de stanza de dépôt utilise
[fauxlo],Server = https://fauxlo.ili.fyi/pacman/$archetSigLevel = NeverSigLevel = Neverautorise les paquets non signés- Pour installer des paquets signés GPG, il faut alimenter le keyring pacman
- Plutôt que de toucher au keyring vide de
/etc/pacman.d/gnupg, la méthode utilisée consiste à remplir un nouveau keyring sur tmpfs
- L’installation de paquets se fait avec une commande du type
pacman --sysroot rootfs --noconfirm -Sy linux-neptune-61- Dans le script réel, l’option
-yest évitée et seule la base du dépôt personnel est synchronisée en arrière-plan par pacman - Cela permet de figer l’état des autres dépôts au moment où l’image originale a été construite
- Le but est de limiter les changements visibles dans le diff de l’image
- Dans le script réel, l’option
steamos-atomupdlit la version de l’image en cours et le build ID depuis/lib/steamos-atomupd/manifest.json, ou à défaut depuis/etc/os-release- Si le build ID fourni par le serveur pour une mise à jour est identique à celui de l’image actuelle, la mise à jour est refusée
- C’est aussi pratique pour identifier quelle image est en cours d’exécution
- Le build ID doit impérativement respecter le format
YYYYMMDD.N- Si le format n’est pas correct,
steamos-atomupds’arrête avec une traceback Python - Pour éviter l’incrémentation manuelle, il est possible d’utiliser
HHMMSSou un timestamp Unix comme valeur deN - Il faut modifier à la fois
buildiddansmanifest.jsonetBUILD_IDdansos-release - Un extrait de script Bash pour cette étape est disponible ici : repack.sh
- Si le format n’est pas correct,
- RAUC utilise des certificats X.509 pour la configuration de confiance
- Le certificat de confiance est dans
/etc/rauc/keyring.pem - Un simple certificat autosigné suffit
- Le nouveau certificat est installé dans
rootfs/etc/rauc/keyring.pem
- Le certificat de confiance est dans
- Les URL de
rootfs/etc/steamos-atomupd/client.confsont elles aussi remplacées par celles du serveur personnelQueryUrlImagesUrlMetaUrl
- D’autres modifications sont possibles tant qu’on ne dépasse pas les 5 GiB de l’image Btrfs
- Par exemple, pour retrouver un appareil SteamOS sur le réseau via
hostname.local, on peut supprimerrootfs/usr/lib/systemd/resolved.conf.d/00-disable-mdns.conf - Cela pourrait aussi être surchargé via la configuration overlay de
/etc, mais cette solution a été jugée trop pénible
- Par exemple, pour retrouver un appareil SteamOS sur le réseau via
- Le principe est d’éviter de mettre dans le rootfs les changements qu’on peut gérer facilement sans image
- On peut par exemple y installer Firefox
- Mais alors il faut repackager l’image à chaque mise à jour de sécurité de Firefox
Démontage du rootfs et création du bundle RAUC
- Une fois les modifications terminées, le système de fichiers est remis en lecture seule
btrfs property set -ts rootfs ro true
- Les blocs inutilisés sont libérés avec
fstrim -v rootfs - Pour le démontage,
umount --recursive rootfsest pratique- Cela permet aussi de démonter les pseudo-systèmes de fichiers montés plus tôt
- Avant de créer le bundle RAUC, il faut générer le store casync et l’index de blobs
- Exemple :
casync make --store=rootfs.img.castr bundle/rootfs.img.caibx rootfs.img
- Exemple :
- Un bundle RAUC nécessite trois fichiers
manifest.raucmrootfs.img.caibxUUID, qui contient l’UUID du système de fichiers
manifest.raucmcontient les informations de mise à jour et celles de l’image rootfscompatible=steamos-amd64version=$versionsha256sizefilename=rootfs.img.caibx
- Le fichier
UUIDest créé avecblkid -s UUID -o value rootfs.img >bundle/UUID - Une fois les trois fichiers prêts, il suffit d’exécuter
rauc bundle--signing-keyring,--certet--keyreçoivent le certificat et la clé à utiliser- Le fichier produit est
rootfs.img.raucb
rootfs.img.raucbetrootfs.img.caibxsont ensuite envoyés sur le serveur web pointé parImagesUrldansclient.conf- Les deux fichiers doivent se trouver dans le même répertoire
Serveur de mise à jour maison et déploiement
- Le serveur web utilisé pour
QueryUrletMetaUrldoit servir des fichiers JSON - Dans une configuration simple, un seul fichier
live.jsonsuffit- L’objet
.minor.candidates[0].imagedoit correspondre à/lib/steamos-atomupd/manifest.jsonprésent dans l’image update_pathest le chemin que le client de mise à jour ajoute aprèsImagesUrlpour télécharger le bundle
- L’objet
- Un exemple de configuration Caddy réécrit les requêtes envoyées par
steamos-atomupdàQueryUrletMetaUrlverslive.json- Réécriture de
/updatesvers/live.json - Réécriture de
/meta/*/*/*/*.jsonet/meta/*/*/*/*/*.jsonvers/live.json - Utilisation de
file_server browse
- Réécriture de
- Les véritables
QueryUrletMetaUrlde SteamOS semblent intégrer davantage de logique, mais cette configuration suffit àsteamos-atomupdpour détecter une nouvelle mise à jour - Une logique empêche la mise à jour si l’image annoncée est déjà celle en cours d’exécution
- Pour mettre à jour une installation SteamOS existante vers une image personnalisée, il suffit de modifier
/etc/rauc/keyring.pemet/etc/steamos-atomupd/client.confsteamos-readonly disablen’est pas nécessaire- Les changements vont dans l’overlay
/etc - Après exécution de
steamos-update, on peut envisager de nettoyer ces modifications dans/var/lib/overlays/etc/upper
- Il semble aussi possible d’installer un SteamOS modifié en prenant l’une des images de récupération Valve et en remplaçant son rootfs par sa propre image, mais cette méthode n’a pas été testée
1 commentaires
Avis sur Hacker News
J’aime ce genre d’article qui explique comment personnaliser en profondeur le logiciel/l’OS d’un appareil qu’on possède. C’est aussi appréciable de ne pas avoir à s’inquiéter de la tivoïsation sur le Steam Deck
La partie la plus intéressante de l’article, pour moi, était la partition
/nix. Je ne savais pas que le Steam Deck prenait en charge nixpkgs ; en cherchant un peu plus, j’ai vu que même si ce n’est pas installé par défaut, on peut l’ajouter sur l’appareil sans forker tout l’OSLe dépôt Nix peut être placé dans n’importe quel emplacement inscriptible, et il suffit de faire pointer
$PATHvers un répertoire de liens symboliquesC’est un article vraiment méticuleux et intéressant. Personnellement, je ne pense pas que j’irais jamais aussi loin
Toute mon expérience avec Linux remonte à l’époque où j’utilisais un Raspberry Pi, et encore, à peut-être 1 %, donc l’auteur m’impressionne
C’est similaire à https://github.com/kiler129/relax-intel-rmrr, mais ce n’est pas mon dépôt
La cause racine ne peut être corrigée que par une mise à jour de ROM du fabricant, mais le vieux DL360 que j’utilise n’est plus pris en charge par HPE
Le correctif lui-même tient en une ligne, mais les mises à jour du noyau sont pénibles. Il faut récupérer le SRPM et, comme il n’y a pas de dépôt Git, décompresser le SRPM, appliquer le patch, puis reconstruire et installer
Il existe déjà des distributions basées sur des éléments de SteamOS, adaptées à l’usage sur PC avec manette. ChimeraOS inclut même EmuDeck, un outil complémentaire pour Steam Deck, et fonctionne plutôt sans souci dans mon environnement
J’ai commandé un GPU pour faire tourner Steam Headless dans une belle image Docker sur mon serveur NAS unRaid, puis m’y connecter depuis un laptop Windows avec un client comme Moonlight
Si ça marche bien, ce sera bien mieux que d’acheter encore du matériel de desktop gaming alors que le NAS reste inactif la plupart du temps. Il faudra toutefois maintenir la consommation de la carte Nvidia au repos quand elle n’est pas utilisée. J’espère que ce sera possible via un appel à
nvidia-persistenced1: https://github.com/Steam-Headless/docker-steam-headless
1: https://github.com/games-on-whales/gow
https://kubevirt.io/user-guide/virtual_machines/host-devices...
Lancer des jeux de façon déclarative et cloud native, incroyable !
kubectl apply -f crysis.yamlJ’ai découvert RAUC(https://rauc.io/) aujourd’hui. Je me demandais comment Valve avait implémenté son système de mises à jour A/B
Le favicon météore de Netscape ne vous manque pas un peu ?
Article intéressant. Les mises à niveau A/B me semblent un peu excessives. En cas de problème, on peut démarrer une distribution live, ou installer un système de récupération d’une version précédente sur une partition séparée
Après avoir utilisé NixOS ces dernières années, je suis revenu à Arch ; j’avais déjà utilisé Arch longtemps auparavant, et les inquiétudes de l’auteur me semblent mal placées
Arch est clairement une distribution très sérieuse et mature, et je lui fais davantage confiance qu’à Valve
La raison de mon passage à Arch, c’est la qualité des paquets. Le dépôt principal est mis à jour très rapidement, et l’AUR contient beaucoup de paquets utiles
Une récupération automatique du système après une mise à niveau ratée est presque indispensable pour un OS à faible maintenance aujourd’hui
Je trouve globalement que la qualité des paquets NixOS est élevée
J’ai récemment mis la main sur un appareil portable de jeu, le Legion Go, et je me mets davantage à Linux. Avant, ça me semblait être une perte de temps infinie à bricoler, et je l’évitais aussi parce que la compatibilité avec les choses que je voulais vraiment utiliser était limitée
Les systèmes de fichiers immuables, et l’idée que Linux traditionnel accorde facilement les droits root à toutes sortes de logiciels arbitraires, ont piqué ma curiosité
J’utilise maintenant NixOS ; ça peut clairement devenir une perte de temps en bricolage, mais c’est très bien pour explorer. On peut tester facilement différents composants, et si l’on décide de ne pas les garder, les supprimer complètement, à l’exception d’une éventuelle pollution de
~/.config. Appliquer des patchs avant l’installation est aussi trivial, ce qui permet d’ajouter facilement des patchs du noyau pour faire fonctionner Linux sur du matériel atypique, comme une console portable de jeuUne communauté NixOS appelée Jovian reconstitue les tarballs SteamOS arbitraires de Valve sous forme de commits tagués sur GitHub, ce qui permet de parcourir les sources comme un employé de Valve. Ils ont fait en sorte qu’en ajoutant seulement quelques lignes à la configuration Nix, on puisse installer sa propre copie de SteamOS par-dessus NixOS
Ce sont manifestement des experts Linux, et en regardant les sources, on peut vérifier qu’ils récupèrent les paquets Valve tels quels, à l’exception de simples ajustements comme le fait de détecter la position du bouton d’alimentation au lieu de la coder en dur
Si vous voulez une expérience SteamOS pure, mais sans héberger vous-même un miroir du système de mise à jour de Valve, ou si vous voulez explorer les sources de Valve sans télécharger des tarballs de 3 Go, Jovian vaut le détour
Guide d’installation : https://jovian-experiments.github.io/Jovian-NixOS/getting-st...
Miroir des sources de Valve : https://github.com/orgs/Jovian-Experiments/repositories?type...
bazzite.gg fait aussi ça très bien. Sur du matériel AMD, le VRR 120 Hz a fonctionné immédiatement, et la prise en charge du HDR peut aussi être testée en alpha
« Bazzite est une image OCI pouvant servir de système d’exploitation alternatif pour le Steam Deck, et un environnement de type SteamOS prêt pour le jeu destiné aux ordinateurs de bureau, aux PC home cinéma de salon et à plusieurs PC portables »
https://github.com/ublue-os/bazzite/
Même si cela ne vous intéresse pas, le README vaut le coup d’œil. La liste de ce qui est inclus est immense, avec beaucoup d’éléments qui semblent particulièrement sympas et utiles pour les joueurs ou les streamers
Je n’ai pas creusé assez profondément pour l’expliquer de façon concise et parfaite en un commentaire HN, mais l’idée de base est d’avoir à la racine une distribution Linux vérifiée et en lecture seule, puis d’y superposer des paquets en couches. C’est une architecture largement inspirée des conteneurs côté serveur
L’objectif est d’être plus sûr, plus fiable, reproductible et plus facile à personnaliser que Linux traditionnel. On indique les paquets souhaités dans un manifeste de conteneur ; lorsqu’une mise à niveau arrive, elle est appliquée, puis les paquets sont réinstallés par-dessus
https://universal-blue.org/guide/fork-your-own/
Et comme c’est un OS immuable, en cas de problème, on peut aussi revenir à l’image précédente
La plupart du temps, c’était sur Steam Deck ou avec Bazzite dans une machine virtuelle avec GPU passthrough, et c’est vraiment bien fait
Un PC de salon : on n’utilise donc plus vraiment les termes HTPC ou « media center » ?