This commit is contained in:
MacRimi 2025-02-15 17:39:01 +01:00
parent 185b0ba510
commit 14e0c1cf23
16 changed files with 443 additions and 40 deletions

357
guides/nvidia/guide.md Normal file
View File

@ -0,0 +1,357 @@
---
title: "Setting up NVIDIA Drivers on Proxmox VE with GPU Passthrough"
description: "Learn how to install and configure NVIDIA drivers on your Proxmox VE host and enable GPU passthrough to your virtual machines."
---
# Instalar drivers de tarjeta grafica Nvidia en Promox (Actualización PVE 8)
Antes de empezar quiero agradecer al compañero @juanlu13 por proporcionarme la [fuente original](https://forums.plex.tv/t/plex-hw-acceleration-in-lxc-container-anyone-with-success/219289/34?utm_source=pocket_mylist) de la cual se basa este manual.
#
Este manual vamos a instalar los drivers de Nvidia, el servicio persistente y un parche opcional para eliminar las sesiones de codificación máxima.
- Instalaremos los drives Nvidia en el host de Proxmox.
- Configuraremos los drives para poder usarlos en cualquier LXC.
Para poder realizar la instalación debemos:
<br>
<br>
1- poner en la lista negra el controlador de "nouveau" si no lo tenemos ya. Si ya lo tenemos podemos saltarnos este paso.
Lo podemos comprobar asi:
```
cat /etc/modprobe.d/blacklist.conf
```
En la imagen del ejemplo se muestra que si que esta añadido a la lista negra "blacklist nouveau"
![This is an image](nvidia-2.png)
Si en nuestro caso no se muestra: blacklist nouveau
Lo añadimos así para que no lo use y podemos instalar el driver de Nvidia.
```
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf
```
```
reboot
```
2- Asegurarnos que tenemos estos repositorios añadidos:
(*Si tenemos instalado el script post instalación de [tteck](https://tteck.github.io/Proxmox/) o el de [xshok](https://github.com/extremeshok/xshok-proxmox), podemos saltarnos este paso ya que no es necesario puesto que están añadidos estos repositorios.*)
```
nano /etc/apt/sources.list
```
##
## Proxmox 7
```
deb http://ftp.debian.org/debian bullseye main contrib
deb http://ftp.debian.org/debian bullseye-updates main contrib
deb http://security.debian.org/debian-security bullseye-security main contrib
deb http://download.proxmox.com/debian/pve bullseye pve-no-subscription
```
##
## Proxmox 8
```
deb http://ftp.debian.org/debian bookworm main contrib
deb http://ftp.debian.org/debian bookworm-updates main contrib
deb http://security.debian.org/debian-security bookworm-security main contrib
deb http://deb.debian.org/debian bookworm main contrib non-free-firmware
deb http://deb.debian.org/debian bookworm-updates main contrib non-free-firmware
# security updates
deb http://security.debian.org/debian-security bookworm-security main contrib non-free-firmware
```
##
Actualizamos los paquetes y promox
```
apt update && apt dist-upgrade -y
```
Antes de empezar, instalamos dos paquetes que necesitaremos, git y los encabezados del kernel para poder instalar los drivers:
```
apt-get install git
```
```
apt-get install -qqy pve-headers-`uname -r` gcc make
```
## 1 - Instalar los drivers de Nvidia en el host de Proxmox
### - Driver:
Para empezar, necesitamos saber cual es el ultimo controlador estable disponible:*
<br>
(*Si vamos a instalar el parche para saltarnos el limite de codificaciones máximas, tenemos que tener en cuenta que ese parche este disponible para la versión del controlador que vamos a instalar.*) Podemos verlo [aquí](https://github.com/keylase/nvidia-patch).
```
https://download.nvidia.com/XFree86/Linux-x86_64/latest.txt
```
Podemos comprobar el listado completo de Drivers [aquí](https://download.nvidia.com/XFree86/Linux-x86_64/)
Cuando nos muestre el resultado, copiamos el numero y los sustituimos por “/latest.txt”
Por ejemplo así:
```
https://download.nvidia.com/XFree86/Linux-x86_64/525.116.03/
```
Una vez dentro del directorio copiamos el enlace del instalador que termina con la extensión .run
![This is an image](nvidia-1.png)
Por ejemplo:
```
https://download.nvidia.com/XFree86/Linux-x86_64/525.116.03/NVIDIA-Linux-x86_64-525.116.03.run
```
#### Empezamos con la instalación:
```
mkdir /opt/nvidia
```
```
cd /opt/nvidia
```
Descargamos el controlador que copiamos antes.
```
wget https://download.nvidia.com/XFree86/Linux-x86_64/525.116.03/NVIDIA-Linux-x86_64-525.116.03.run
```
Le damos permisos de ejecución.
```
chmod +x NVIDIA-Linux-x86_64-525.116.03.run
```
ejecutamos.
```
./NVIDIA-Linux-x86_64-525.116.03.run --no-questions --ui=none --disable-nouveau
```
Una vez terminado reiniciamos.
```
reboot
```
Una vez reiniciado proxmox continuamos con la intalación. Ejecutamos:
```
/opt/nvidia/NVIDIA-Linux-x86_64-525.116.03.run --no-questions --ui=none
```
Ahora añadimos a etc/modules:
```
nano /etc/modules-load.d/modules.conf
```
```
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
nvidia
nvidia_uvm
```
Guardamos:
ctrl + x.
<br>
Actualizamos initramfs:
```
update-initramfs -u -k all
```
A continuación creamos reglas para cargar los controladores en el arranque para nvidia y nvidia_uvm:
```
nano /etc/udev/rules.d/70-nvidia.rules
```
Pegamos:
```
# /etc/udev/rules.d/70-nvidia.rules
# Create /nvidia0, /dev/nvidia1 … and /nvidiactl when nvidia module is loaded
KERNEL=="nvidia", RUN+="/bin/bash -c '/usr/bin/nvidia-smi -L'"
#
# Create the CUDA node when nvidia_uvm CUDA module is loaded
KERNEL=="nvidia_uvm", RUN+="/bin/bash -c '/usr/bin/nvidia-modprobe -c0 -u'"
```
Guardamos: ctrl + x
<br>
### - NVIDIA driver persistence:
Ahora instalamos NVIDIA driver persistence:
```
cd /opt/nvidia
git clone https://github.com/NVIDIA/nvidia-persistenced.git
cd nvidia-persistenced/init
./install.sh
```
```
reboot
```
Comprobamos que el controlador este instalado y el servicio este ejecutándose:
```
nvidia-smi
```
![This is an image](nvidia-3.png)
```
systemctl status nvidia-persistenced
```
![This is an image](nvidia-4.png)
### - Parche:
Ahora como opcion, parcheamos el controlador nvidia para eliminar las sesiones de codificación máxima. Según el desarrollador el parche NVENC elimina la restricción sobre la cantidad máxima de sesiones de codificación de video NVENC simultáneas impuestas por Nvidia a las GPU de nivel de consumidor.
```
cd /opt/nvidia
git clone https://github.com/keylase/nvidia-patch.git
cd nvidia-patch
./patch.sh
```
![This is an image](nvidia-5.png)
<br>
## 2- Configurar los drives para poder usarlos en cualquier LXC.
Primeramente necesitamos obtener estos datos:
```
ls -l /dev/nv*
```
![This is an image](nvidia-6.png)
Pongamos por ejemplo que vamos a usar el LXC de Plex del scrip de tteck con ID100. Si lo tenemos ejecutado lo apagamos.
```
nano /etc/pve/lxc/100.conf
```
Si las hubiera, comentamos todas las líneas en las que aparezca:
<br>
- lxc.cgroup2.devices.allow...
- /dev/dri...
<br>
y pegamos esto dentro del archivo de configuración del LXC, que corresponde a los datos que obtuvimos con: ls -l /dev/nv*
<br>
(*los numeros pueden variar que un equipo a otro*)
```
lxc.cgroup2.devices.allow: c 195:* rwm
lxc.cgroup2.devices.allow: c 509:* rwm
lxc.cgroup2.devices.allow: c 10:* rwm
lxc.cgroup2.devices.allow: c 238:* rwm
lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,optional,create=file
lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm dev/nvidia-uvm none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-modeset dev/nvidia-modeset none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm-tools dev/nvidia-uvm-tools none bind,optional,create=file
lxc.mount.entry: /dev/nvram dev/nvram none bind,optional,create=file
```
![This is an image](nvidia-7.png)
<br>
Guardamos:
ctrl + x.
Ejecutamos el LCX y vamos a instalar dentro de el, el driver de Nvidia.
**IMPORTANTE esta instalación la hacemos desde la consola del LCX no desde Proxmox**
```
mkdir /opt/nvidia
```
```
cd /opt/nvidia
```
```
wget https://download.nvidia.com/XFree86/Linux-x86_64/525.116.03/NVIDIA-Linux-x86_64-525.116.03.run
```
```
chmod +x NVIDIA-Linux-x86_64-525.116.03.run
```
```
./NVIDIA-Linux-x86_64-525.116.03.run --no-kernel-module
```
<br>
Cuando aparezca esta pantalla seleccionamos todo por defecto, cada vez que nos pregunte.
<br>
![This is an image](nvidia-8.png)
<br>
Una vez terminada la instalación comprobamos que todo este correcto
```
nvidia-smi
```
![This is an image](nvidia-9.png)
```
ls -l /dev/nv*
```
![This is an image](nvidia-10.png)
## Comprobamos que Plex use la grafica.
<br>
Como podemos observar el contenedor LXC de Plex hace uso de la grafica de Nvidia de nuestro host Proxmox.
<br>
![This is an image](nvidia-11.png)
<br>
![This is an image](nvidia-12.png)
<br>
Si queremos que cualquier LXC haga uso de nuestra grafica simplemente es seguir los mismos pasos.
##
Si queremos usar la grafica nvida en Docker, necesitanos como extra instalar: nvidia-docker2.
Dentro del LCX donde tengamos Docker, Lo podemos hacer con este simple script:
```
wget https://raw.githubusercontent.com/MacRimi/manuales/main/NVIDIA/nvidia-docker.sh
```
```
chmod +x nvidia-docker.sh
```
```
./nvidia-docker.sh
```
Enjoy!!
Un tutorial de Proxmology.
#
<div style="display: flex; justify-content: center; align-items: center;">
<a href="https://ko-fi.com/G2G313ECAN" target="_blank" style="display: flex; align-items: center; text-decoration: none;">
<img src="https://raw.githubusercontent.com/MacRimi/HWEncoderX/main/images/kofi.png" alt="Support me on Ko-fi" style="width:175px; margin-right:65px;"/>
</a>
</div>
Si este tutorial te ha gustado y te ha sido útil, ¡puedes invitarme a un Ko-fi! ¡Gracias! 😊

BIN
guides/nvidia/nvidia-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
guides/nvidia/nvidia-10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
guides/nvidia/nvidia-11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
guides/nvidia/nvidia-12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
guides/nvidia/nvidia-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
guides/nvidia/nvidia-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
guides/nvidia/nvidia-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
guides/nvidia/nvidia-5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
guides/nvidia/nvidia-6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
guides/nvidia/nvidia-7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
guides/nvidia/nvidia-8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
guides/nvidia/nvidia-9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@ -0,0 +1,14 @@
#!/bin/bash
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
tee /etc/apt/sources.list.d/nvidia-docker.list
apt-get update
# Install nvidia-docker2 and reload the Docker daemon configuration
apt-get install -y nvidia-docker2
pkill -SIGHUP dockerd
reboot

View File

@ -2,66 +2,77 @@ import fs from "fs"
import path from "path"
import { remark } from "remark"
import html from "remark-html"
import * as gfm from "remark-gfm" // ✅ Asegura la correcta importación de `remark-gfm`
import * as gfm from "remark-gfm"
import dynamic from "next/dynamic"
import React from "react"
import parse from "html-react-parser"
// 🔹 Importamos `CopyableCode` dinámicamente para evitar problemas de SSR
const CopyableCode = dynamic(() => import("@/components/CopyableCode"), { ssr: false })
const guidesDirectory = path.join(process.cwd(), "..", "guides")
// 🔹 Función para buscar archivos Markdown dentro de subdirectorios
function findMarkdownFiles(dir: string, basePath = "") {
let files: { slug: string; path: string }[] = []
fs.readdirSync(dir, { withFileTypes: true }).forEach((entry) => {
const fullPath = path.join(dir, entry.name)
const relativePath = path.join(basePath, entry.name)
if (entry.isDirectory()) {
files = files.concat(findMarkdownFiles(fullPath, relativePath))
} else if (entry.isFile() && entry.name.endsWith(".md")) {
files.push({
slug: relativePath.replace(/\.md$/, ""), // 🔹 Quitamos la extensión .md
path: fullPath,
})
}
})
return files
}
async function getGuideContent(slug: string) {
try {
const guidePath = path.join(guidesDirectory, `${slug}.md`)
const markdownFiles = findMarkdownFiles(guidesDirectory)
const guideFile = markdownFiles.find((file) => file.slug === slug)
if (!fs.existsSync(guidePath)) {
console.error(`❌ Archivo ${slug}.md no encontrado en guides/`)
if (!guideFile) {
console.error(`No se encontró la guía: ${slug}`)
return "<p class='text-red-600'>Error: No se encontró la guía solicitada.</p>"
}
const fileContents = fs.readFileSync(guidePath, "utf8")
const fileContents = fs.readFileSync(guideFile.path, "utf8")
// ✅ Agregamos `remark-gfm` para permitir imágenes, tablas y otros elementos avanzados de Markdown
const result = await remark()
.use(gfm.default || gfm) // ✅ Manejo seguro de `remark-gfm`
.use(gfm.default || gfm)
.use(html)
.process(fileContents)
return result.toString()
} catch (error) {
console.error(`❌ Error al leer la guía ${slug}.md`, error)
console.error(`❌ Error al leer la guía ${slug}`, error)
return "<p class='text-red-600'>Error: No se pudo cargar la guía.</p>"
}
}
// 🔹 Asegura que `generateStaticParams()` esté presente para `output: export`
// 🔹 Generamos rutas estáticas incluyendo subdirectorios
export async function generateStaticParams() {
try {
if (fs.existsSync(guidesDirectory)) {
const guideFiles = fs.readdirSync(guidesDirectory)
return guideFiles.map((file) => ({
slug: file.replace(/\.md$/, ""),
}))
} else {
console.warn("⚠ No se encontró el directorio guides/. No se generarán rutas estáticas.")
return []
}
const markdownFiles = findMarkdownFiles(guidesDirectory)
return markdownFiles.map((file) => ({ slug: file.slug }))
} catch (error) {
console.error("❌ Error al generar las rutas estáticas para guides:", error)
return []
}
}
// 🔹 Limpia las comillas invertidas en fragmentos de código en línea
function cleanInlineCode(content: string) {
return content.replace(/<code>(.*?)<\/code>/g, (_, codeContent) => {
return `<code class="bg-gray-200 text-gray-900 px-1 rounded">${codeContent.replace(/^`|`$/g, "")}</code>`
})
}
// 🔹 Envuelve los bloques de código en <CopyableCode />
function wrapCodeBlocksWithCopyable(content: string) {
return parse(content, {
replace: (domNode: any) => {
@ -78,13 +89,13 @@ function wrapCodeBlocksWithCopyable(content: string) {
export default async function GuidePage({ params }: { params: { slug: string } }) {
const guideContent = await getGuideContent(params.slug)
const cleanedInlineCode = cleanInlineCode(guideContent) // 🔹 Primero limpiamos código en línea
const parsedContent = wrapCodeBlocksWithCopyable(cleanedInlineCode) // 🔹 Luego aplicamos JSX a bloques de código
const cleanedInlineCode = cleanInlineCode(guideContent)
const parsedContent = wrapCodeBlocksWithCopyable(cleanedInlineCode)
return (
<div className="min-h-screen bg-white text-gray-900">
<div className="container mx-auto px-4 py-16" style={{ maxWidth: "980px" }}> {/* 📌 Ajuste exacto como GitHub */}
<div className="prose max-w-none text-[16px]">{parsedContent}</div> {/* 📌 Texto ajustado a 16px */}
<div className="container mx-auto px-4 py-16" style={{ maxWidth: "980px" }}>
<div className="prose max-w-none text-[16px]">{parsedContent}</div>
</div>
</div>
)

View File

@ -1,27 +1,49 @@
import fs from "fs"
import path from "path"
import matter from "gray-matter"
import Link from "next/link"
const guidesDirectory = path.join(process.cwd(), "..", "guides")
interface Guide {
title: string
description: string
slug: string
}
const guides: Guide[] = [
{
title: "Setting up NVIDIA Drivers on Proxmox VE with GPU Passthrough",
description:
"Learn how to install and configure NVIDIA drivers on your Proxmox VE host and enable GPU passthrough to your virtual machines.",
slug: "nvidia_proxmox",
},
{
title: "Ejemplo de Guía Adicional",
description: "Esta es una guía de ejemplo para mostrar cómo se manejan múltiples guías.",
slug: "example_guide",
},
// Añade más guías aquí según sea necesario
]
function getGuides(): Guide[] {
let guides: Guide[] = []
function findGuides(dir: string, basePath = "") {
fs.readdirSync(dir, { withFileTypes: true }).forEach((entry) => {
const fullPath = path.join(dir, entry.name)
const relativePath = path.join(basePath, entry.name)
if (entry.isDirectory()) {
findGuides(fullPath, relativePath)
} else if (entry.isFile() && entry.name.endsWith(".md")) {
const slug = relativePath.replace(/\.md$/, "")
// 🔹 Extraer metadatos usando gray-matter
const fileContents = fs.readFileSync(fullPath, "utf8")
const { data } = matter(fileContents)
guides.push({
title: data.title || slug.replace(/_/g, " "),
description: data.description || "No description available.",
slug,
})
}
})
}
findGuides(guidesDirectory)
return guides
}
export default function GuidesPage() {
const guides = getGuides()
return (
<div className="container mx-auto px-4 py-16">
<h1 className="text-4xl font-bold mb-8">ProxMenux Guides</h1>
@ -41,4 +63,3 @@ export default function GuidesPage() {
</div>
)
}