{
"meta": {
"title": "Dispositifs et accélération ProxMenux",
"description": "Comment OCI manager Apps rend les GPU, NVIDIA, Coral, USB, FUSE et autres périphériques accessibles à un conteneur OCI sous forme de ressources natives Proxmox VE validées."
},
"header": {
"title": "Dispositifs et accélération",
"description": "GPU, NVIDIA, Coral, USB, FUSE et les dispositifs de blocs deviennent des ressources natives validées Proxmox VE du conteneur.",
"section": "OCI manager Apps"
},
"sections": [
{
"id": "principle",
"title": "L'appareil dont l'application a besoin, pas l'hôte entier",
"blocks": [
{
"p": "Un appareil demandé par le fichier Compose ou par le profil d'application devient une entrée concrète devN ou un montage LXC. Demander un GPU, un périphérique USB ou un Coral ne rend pas le conteneur privilégié."
},
{
"flow": {
"nodes": [
{
"label": "Inventaire des hôtes",
"detail": "/dev/dri/renderD128\nGID 993 · Intel"
},
{
"label": "ProxMenux",
"detail": "fournisseur et\npermissions vérifiées"
},
{
"label": "LXC",
"detail": "même périphérique\nGID effectif"
}
]
}
}
]
},
{
"id": "origin",
"title": "D'où vient la demande de l'appareil",
"blocks": [
{
"table": {
"headers": [
"Source",
"Ce qui est lu",
"Ce que fait l'installateur"
],
"rows": [
[
"Docker Compose",
"Demandes devices, group_add, deploy.resources et NVIDIA",
"Chaque exigence devient une demande d'appareil présentée pour examen"
],
[
"Profil du catalogue",
"La prise en charge réelle des GPU, de Coral, d’OpenCL, d’USB ou de FUSE par l’application",
"Seules les options validées pour cette image sont proposées"
],
[
"métadonnées d'images et documentation",
"VA-API, Selkies, LinuxServer mods ou le NVIDIA runtime",
"Les variables documentées et la préparation sont ajoutées"
],
[
"Sélection de l'utilisateur",
"CPU uniquement, Intel/AMD, OpenCL, NVIDIA ou un appareil optionnel",
"La sélection est stockée dans le contrat d'instance"
]
]
}
},
{
"calloutWarning": {
"title": "Les périphériques détectés ne sont pas ajoutés automatiquement",
"body": "L'hôte est inventorié, mais seuls les appareils déclarés par le fichier Compose ou par un profil compatible sont proposés et attachés. Un GPU, un dongle USB ou un Coral présent sur l'hôte n'est pas exposé à tous les LXC."
}
}
]
},
{
"id": "identify",
"title": "Comment le périphérique hôte est identifié",
"intro": "Avant que le LXC ne soit modifié, l'appareil est lu sur l'hôte et correspond au profil choisi.",
"blocks": [
{
"table": {
"headers": [
"Type",
"Identité",
"Validation"
],
"rows": [
[
"Intel/AMD DRM",
"/dev/dri/renderD* et /sys/class/drm/NODE/device/vendor",
"Dispositif de caractères avec fournisseur 0x8086 (Intel) ou 0x1002 (AMD)"
],
[
"AMD OpenCL",
"Le nœud de rendu, plus /dev/kfd lorsque le profil en a besoin",
"Existence, type, fournisseur, autorisations et compatibilité déclarée"
],
[
"AMD ROCm",
"Le nœud de rendu, /dev/kfd et la génération indiquée par le pilote de calcul dans /sys/class/kfd/kfd/topology/nodes/*/properties",
"Un GPU d’une génération prise en charge par l’image ROCm de l’application (les GPU RDNA2 qu’elle cite et les plus récents) est proposé tel quel. Les autres GPU de ces familles, comme les Radeon 680M et 780M, sont proposés à titre expérimental et ne sont jamais l’option proposée par défaut. ROCm ne les prend pas officiellement en charge : l’application les présente comme la génération de leur famille (HSA_OVERRIDE_GFX_VERSION) et l’installateur demande confirmation avant de télécharger l’image plus volumineuse. Un GPU plus ancien, tel que la partie graphique intégrée d’un Ryzen 5000U, n’est pas proposé et Immich conserve la reconnaissance sur le CPU"
],
[
"NVIDIA",
"nvidia-smi et nvidia-container-cli",
"GPU, UUID, PCI bus, version pilote, Toolkit, /dev/nvidia* nœuds, binaires et bibliothèques"
],
[
"Coral PCIe/M.2",
"/dev/apex_N et son lien dans /sys/dev/char/MAJOR:MINOR",
"Nœud de caractère, majeur/mineur, propriétaire, GID et permissions"
],
[
"USB et série",
"/dev/ttyUSB*, /dev/ttyACM* ou /dev/bus/usb/BBB/DDD",
"Nœud de caractère; pour USB aussi fournisseur, produit et série lorsque sysfs les publie"
],
[
"KVM, TUN, FUSE, vidéo et SCSI générique",
"/dev/kvm, /dev/net/tun, /dev/fuse, /dev/videoN ou /dev/sgN",
"Chemin pris en charge, type de nœud et permissions effectives"
],
[
"Lecteur optique",
"/dev/srN",
"Un périphérique bloc"
]
]
}
}
]
},
{
"id": "install",
"title": "Ce qui se passe pendant l'installation",
"blocks": [
{
"steps": {
"items": [
{
"title": "Le modèle offre ses profils",
"body": "Par exemple CPU seulement, Intel/AMD VA-API, AMD OpenCL, Intel OpenCL ou NVIDIA. Les options appartiennent à l'image, pas à un menu commun."
},
{
"title": "Un profil est choisi",
"body": "Il définit les nœuds de périphérique, l'environnement, les mods ou l'exécution dont l'application a besoin."
},
{
"title": "Un chemin est proposé",
"body": "Pour DRM, /dev/dri/renderD128, qui peut être modifié sur un hôte avec plusieurs nœuds de rendu. Pour USB ou série, le nœud précis est sélectionné."
},
{
"title": "Validation",
"body": "L'existence, le type, le fournisseur autorisé, les autorisations et le GID sont vérifiés. Une inadéquation arrête l'opération."
},
{
"title": "Le contrat est écrit",
"body": "Chemin, mode, GID, accès à l'écriture et profil sont enregistrés pour les mises à jour et les recréations de conteneurs."
},
{
"title": "Ajout et vérification",
"body": "pct set ajoute l'entrée devN et l'accès est ensuite vérifié à l'intérieur du LXC. Les images LinuxServer sont également vérifiées en tant qu'utilisateur abc."
}
]
}
}
]
},
{
"id": "config",
"title": "Comment il apparaît dans la configuration LXC",
"intro": "Valeurs indicatives : dev0 et dev1 sont les emplacements libres attribués par Proxmox VE ; renderD128, apex_0 et le GID dépendent du matériel du nœud.",
"blocks": [
{
"codeGrid": {
"items": [
{
"title": "Intel/AMD VA-API",
"code": "dev0: path=/dev/dri/renderD128,mode=0660,gid=993,deny-write=0"
},
{
"title": "Coral PCIe/M.2",
"code": "dev0: path=/dev/apex_0,mode=0660,gid=GID,deny-write=0"
},
{
"title": "Un périphérique USB spécifique",
"code": "dev0: path=/dev/bus/usb/003/004,mode=0660,gid=GID,deny-write=0"
},
{
"title": "AMD OpenCL",
"code": "dev0: path=/dev/dri/renderD128,mode=0660,gid=GID,deny-write=0\ndev1: path=/dev/kfd,mode=0660,gid=GID,deny-write=0"
}
]
}
},
{
"p": "Le GID est lu avec stat sur l'hôte et écrit à l'entrée devN; les groupes render et video ne sont pas supposés avoir un nombre fixe. L'appareil conserve le même chemin /dev à l'intérieur du LXC, où les propres mécanismes de l'application le recherchent."
}
]
},
{
"id": "profiles",
"title": "Profils qu'une image peut offrir",
"blocks": [
{
"table": {
"headers": [
"Profil",
"Configuration résultante",
"Proposé quand"
],
"rows": [
[
"Intel/AMD VA-API",
"Le noeud de rendu /dev/dri",
"L'application prend en charge l'accélération vidéo"
],
[
"OpenCL",
"Noeud Render, /dev/kfd au besoin et le mod officiel",
"L'image ou le profil le documente"
],
[
"NVIDIA",
"Dispositifs pilotes et bibliothèques de l'hôte",
"L’hôte dispose d’un pilote fonctionnel et de NVIDIA Container Toolkit"
],
[
"Coral",
"/dev/apex_0 ou le bus USB",
"Le profil déclare la prise en charge de Coral (Frigate)"
],
[
"USB, série, FUSE",
"Un seul appareil, un arbre validé ou une fonction LXC",
"Le contrat le demande"
]
]
}
}
]
},
{
"id": "nvidia",
"title": "NVIDIA",
"blocks": [
{
"calloutWarning": {
"title": "Prérequis sur le nœud : NVIDIA Container Toolkit",
"body": "Un pilote fonctionnel sur Proxmox VE ne suffit pas à donner une GPU NVIDIA à une image OCI. OCI Manager Apps utilise nvidia-container-cli, de NVIDIA Container Toolkit, pour identifier les appareils et obtenir les binaires et les bibliothèques qui correspondent au pilote chargé."
}
},
{
"p": "Le installateur NVIDIA de ProxMenux installe NVIDIA Container Toolkit du dépôt officiel NVIDIA avec le pilote. Il vérifie ses quatre paquets, valide nvidia-container-cli et enregistre le résultat dans le journal de changement de Audit & Report."
},
{
"p": "Ces deux commandes sur l'hôte montrent si le pilote et le Toolkit sont disponibles :"
},
{
"shell": {
"code": "nvidia-smi -L\nnvidia-container-cli --version"
}
},
{
"p": "Sur un hôte où le pilote a été installé par d'autres moyens, le Toolkit est installé à partir du dépôt stable officiel:"
},
{
"shell": {
"code": "apt-get update\napt-get install -y --no-install-recommends ca-certificates curl gnupg2\n\ncurl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \\\n | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg\n\ncurl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \\\n | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \\\n > /etc/apt/sources.list.d/nvidia-container-toolkit.list\n\napt-get update\napt-get install -y nvidia-container-toolkit libnvidia-container-tools"
}
},
{
"p": "L’inventaire utilisé par OCI manager Apps provient de la sortie de :"
},
{
"shell": {
"code": "nvidia-container-cli list --device all --libraries --binaries --firmwares --ipcs"
}
},
{
"calloutInfo": {
"title": "La configuration d'exécution Docker n'est pas impliquée",
"body": "Les conteneurs sont des LXC natifs sans démon Docker : nvidia-ctk runtime configure --runtime=docker ne joue donc aucun rôle. ProxMenux interroge directement nvidia-container-cli et écrit les périphériques et montages LXC. Les commandes et plateformes prises en charge sont maintenues dans le guide d’installation de NVIDIA Container Toolkit."
}
},
{
"cards": {
"items": [
{
"icon": "cpu",
"title": "Inventaire issu du pilote",
"body": "nvidia-container-cli énumère les nœuds de périphérique, les binaires, les micrologiciels et les bibliothèques du pilote installé."
},
{
"icon": "refresh",
"title": "Pas de version fixe",
"body": "Le modèle ne nomme pas les fichiers de bibliothèque. Le profil est généré à partir de l'hôte actuel."
},
{
"icon": "shield",
"title": "Montages en lecture seule",
"body": "Les bibliothèques hôtes sont montées en lecture seule au lieu d'être copiées dans le conteneur."
},
{
"icon": "hardDrive",
"title": "Changements de pilote",
"body": "Après un changement de pilote, l'inventaire est généré à nouveau avant le démarrage des LXC touchés."
}
]
}
},
{
"code": {
"title": "Résultat NVIDIA (simplifié)",
"code": "devN: path=/dev/nvidia0,...\ndevN: path=/dev/nvidiactl,...\ndevN: path=/dev/nvidia-uvm,...\nlxc.mount.entry: HOST_LIBRARY CONTAINER_LIBRARY none ro,bind,create=file 0 0"
}
},
{
"p": "Passer uniquement /dev/nvidia0 ne suffit pas. Les composants espace utilisateur du pilote chargé sont montés en lecture seule, et nvidia-smi fonctionne ensuite à l'intérieur du LXC pour comparer GPU, UUID, PCI bus et version avec l'inventaire hôte."
}
]
},
{
"id": "usb",
"title": "Coral USB, série et USB",
"blocks": [
{
"calloutWarning": {
"title": "La numérotation USB peut changer",
"body": "Un chemin tel que /dev/bus/usb/003/004 peut changer lorsque le périphérique est reconnecté ou que l'hôte redémarre. Le profil enregistre le fournisseur, le produit et la série lorsqu'ils sont disponibles, mais une nouvelle adresse de bus n'est pas automatiquement réaffectée."
}
},
{
"p": "Un périphérique est donné par son nœud concret : /dev/ttyUSB0, /dev/ttyACM0, /dev/apex_0 ou /dev/bus/usb/BBB/DDD. Passer l'intégralité de /dev n'est pas accepté. Coral est proposé uniquement aux applications dont le profil le déclare."
}
]
},
{
"id": "trees",
"title": "Arbres de périphériques et fonctionnalités LXC",
"blocks": [
{
"table": {
"headers": [
"Demande",
"Configuration résultante",
"Portée"
],
"rows": [
[
"/dev/dvb, /dev/snd ou /dev/bus/usb",
"Chaque noeud de caractère de l'arbre obtient sa propre entrée devN avec le mode hôte et GID",
"Seulement l'arbre demandé, pas le reste de /dev"
],
[
"/dev/fuse",
"Le nœud et, lorsque le profil en a besoin, la fonction fuse=1",
"FUSE seul ne publie pas de montages sur d'autres LXC"
],
[
"/dev/net/tun",
"Une entrée devN sur le même chemin à l'intérieur du LXC",
"La configuration VPN ou réseau reste dans l'application"
],
[
"/dev/kvm",
"Une entrée devN validée",
"Offert seulement lorsque le contrat le demande"
]
]
}
}
]
},
{
"id": "security",
"title": "Confirmations par niveau de risque",
"blocks": [
{
"p": "Les périphériques concrets, les privilèges facultatifs, les privilèges requis, la relaxation AppArmor ou seccomp et l'accès à l'espace de noms PID hôte sont traités comme des cas distincts, et non sous une seule étiquette privilégiée générique. Chaque option présentant un risque est expliquée et confirmée lors de l'installation."
}
]
}
]
}