Compilar tu propio kernel te permite usar una versión más reciente que la de tu distribución, activar opciones que Ubuntu no incluye o reducir el kernel a los controladores que realmente usa tu hardware. En este tutorial descargarás el código fuente oficial desde kernel.org, verificarás su firma, partirás de la configuración del kernel de Ubuntu, compilarás paquetes .deb con make bindeb-pkg y los instalarás en Ubuntu 24.04 de forma que puedas volver al kernel anterior en cualquier momento.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS (x86_64), por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Al menos 4 vCPU y 8 GB de RAM para que la compilación termine en un tiempo razonable (con 2 vCPU también funciona, pero puede tardar más de una hora).
- Unos 40 GB libres en disco: la configuración de Ubuntu activa la información de depuración y el árbol compilado ocupa mucho.
- Acceso a la consola del servidor (por ejemplo, la consola VNC del panel de CubePath) por si el nuevo kernel no arrancara y necesitaras elegir el anterior en GRUB.
AdvertenciaNo pruebes un kernel nuevo por primera vez en un servidor de producción. Hazlo en una máquina de pruebas o después de crear un snapshot o una copia de seguridad.
Paso 1: Instalar las herramientas de compilación
El kernel necesita un compilador, las herramientas flex y bison para los analizadores de configuración, las cabeceras de OpenSSL y libelf, y dwarves (que aporta pahole) para generar la información BTF que usan las herramientas eBPF. Para empaquetar el resultado en .deb hacen falta además debhelper y rsync:
sudo apt update
sudo apt install build-essential bc bison flex libssl-dev libelf-dev libncurses-dev dwarves rsync cpio zstd debhelper fakeroot gnupg wget
Comprueba la versión de GCC instalada:
gcc --version | head -n1
gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
Anota también el kernel que estás usando ahora, porque te servirá para comparar y para volver atrás:
uname -r
6.8.0-79-generic
Paso 2: Descargar y verificar el código fuente
Consulta en kernel.org qué versión quieres compilar. Para un servidor lo razonable es la última versión de una rama longterm o la última stable. En esta guía se usa 6.12.50 como ejemplo; sustitúyela por la versión exacta que aparezca en kernel.org.
Crea un directorio de trabajo y guarda la versión en una variable para reutilizarla:
mkdir -p ~/kernel && cd ~/kernel
KVER=6.12.50
Descarga el archivo comprimido y su firma:
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${KVER}.tar.xz
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${KVER}.tar.sign
La firma se calcula sobre el archivo .tar sin comprimir, así que primero descomprime el .xz:
unxz linux-${KVER}.tar.xz
Importa las claves de Linus Torvalds y Greg Kroah-Hartman, que firman las versiones publicadas, y verifica el archivo:
gpg --locate-keys [email protected] [email protected]
gpg --verify linux-${KVER}.tar.sign linux-${KVER}.tar
La línea importante es Good signature:
gpg: assuming signed data in 'linux-6.12.50.tar'
gpg: Signature made ...
gpg: using RSA key 647F28654894E3BD457199BE38DBBDC86092693E
gpg: Good signature from "Greg Kroah-Hartman <[email protected]>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
El aviso WARNING: This key is not certified es normal si no has firmado esas claves en tu anillo; lo que importa es que la firma sea válida. Si ves BAD signature, borra el archivo y vuelve a descargarlo.
Extrae el código fuente y entra en el directorio:
tar xf linux-${KVER}.tar
cd linux-${KVER}
Paso 3: Preparar la configuración
La forma más segura de empezar es reutilizar la configuración del kernel de Ubuntu que ya arranca en tu servidor. Cópiala como .config:
cp /boot/config-$(uname -r) .config
La configuración de Ubuntu hace referencia a certificados de Canonical (debian/canonical-certs.pem y debian/canonical-revoked-certs.pem) que no existen en el código fuente de kernel.org. Desactiva esas dos opciones o la compilación fallará:
scripts/config --disable SYSTEM_TRUSTED_KEYS
scripts/config --disable SYSTEM_REVOCATION_KEYS
Añade un sufijo a la versión para distinguir tu kernel de los de Ubuntu:
scripts/config --set-str LOCALVERSION "-custom"
Por último, adapta la configuración a la nueva versión. olddefconfig conserva tus opciones y asigna el valor por defecto a las que no existían en el kernel de Ubuntu, sin hacerte preguntas:
make olddefconfig
#
# configuration written to .config
#
Opcional: reducir el kernel a los módulos cargados
La configuración de Ubuntu compila miles de módulos para soportar cualquier hardware. Si quieres un kernel más pequeño y una compilación mucho más rápida, localmodconfig desactiva todos los módulos que no estén cargados en este momento:
make localmodconfig
Pulsa Intro en cada pregunta para aceptar el valor por defecto.
AdvertenciaUn módulo que no estuviera cargado al ejecutar
localmodconfig(por ejemplo, el de un sistema de archivos que montas solo a veces,wireguardonf_tablessi el firewall no estaba activo) no existirá en el nuevo kernel. Carga antes todo lo que vayas a necesitar o sáltate este paso.
Opcional: cambiar opciones concretas
Para revisar o modificar opciones con un menú interactivo usa menuconfig. Con / puedes buscar una opción por nombre:
make menuconfig
Si prefieres cambios puntuales y reproducibles, scripts/config modifica una opción sin abrir el menú. Tras cualquier cambio, ejecuta de nuevo make olddefconfig para resolver las dependencias.
Comprueba que el sufijo de versión ha quedado aplicado:
grep '^CONFIG_LOCALVERSION=' .config
CONFIG_LOCALVERSION="-custom"
Paso 4: Compilar el kernel como paquetes .deb
En Ubuntu y Debian lo más limpio es generar paquetes .deb con make bindeb-pkg. Así el kernel se instala y se desinstala con apt, y los scripts de Ubuntu generan el initramfs y actualizan GRUB automáticamente. -j"$(nproc)" usa todos los núcleos disponibles.
Como la compilación dura bastante, ejecútala dentro de tmux o screen para que no se interrumpa si se corta la sesión SSH:
make -j"$(nproc)" bindeb-pkg
Cuando termine, los paquetes quedan en el directorio padre:
ls ../*.deb
../linux-headers-6.12.50-custom_6.12.50-1_amd64.deb
../linux-image-6.12.50-custom_6.12.50-1_amd64.deb
../linux-image-6.12.50-custom-dbg_6.12.50-1_amd64.deb
../linux-libc-dev_6.12.50-1_amd64.deb
Los nombres exactos pueden variar ligeramente según la versión del kernel. El paquete -dbg contiene los símbolos de depuración y no necesitas instalarlo. Tampoco instales linux-libc-dev: sustituiría las cabeceras del sistema que usa Ubuntu para compilar programas.
Paso 5: Instalar el nuevo kernel
Instala la imagen del kernel y sus cabeceras (las cabeceras las necesitan módulos externos como DKMS):
sudo apt install ../linux-image-${KVER}-custom_*_amd64.deb ../linux-headers-${KVER}-custom_*_amd64.deb
Si has abierto una sesión nueva desde el paso 2, vuelve a definir KVER antes de ejecutar el comando.
Durante la instalación, los scripts de /etc/kernel/postinst.d/ generan el initramfs y ejecutan update-grub. Comprueba que los archivos están en /boot:
ls /boot | grep custom
System.map-6.12.50-custom
config-6.12.50-custom
initrd.img-6.12.50-custom
vmlinuz-6.12.50-custom
Y que GRUB ha añadido una entrada para él:
grep -E "menuentry .*${KVER}-custom" /boot/grub/grub.cfg | head -n2
GRUB ordena los kernels por versión y arranca por defecto el más reciente, así que si tu versión es mayor que la de Ubuntu será la que arranque. El kernel anterior sigue disponible en Opciones avanzadas para Ubuntu.
Comprobar Secure Boot
Tu kernel no está firmado con la clave de Canonical. Si el servidor arranca con Secure Boot activado, el firmware se negará a cargarlo. Compruébalo antes de reiniciar:
mokutil --sb-state
SecureBoot disabled
Si la salida es SecureBoot enabled, tendrás que firmar el kernel con tu propia clave MOK o desactivar Secure Boot en el firmware; ese proceso queda fuera de esta guía. En la mayoría de VPS Secure Boot está desactivado o el comando indica que no está soportado.
Paso 6: Reiniciar y verificar
Reinicia el servidor:
sudo reboot
Cuando vuelvas a conectarte, comprueba la versión en ejecución:
uname -r
6.12.50-custom
Revisa los mensajes del arranque en busca de errores y comprueba que los servicios han arrancado:
sudo dmesg --level=err,warn | head -n 20
systemctl --failed
UNIT LOAD ACTIVE SUB DESCRIPTION
0 loaded units listed.
Comprueba también que la red y el disco funcionan (ip -br a, df -h) y que los módulos que necesitas están disponibles, por ejemplo:
lsmod | head
Paso 7: Volver al kernel anterior o eliminar el personalizado
Si algo no funciona, reinicia y en el menú de GRUB elige Opciones avanzadas para Ubuntu y el kernel -generic anterior. En Ubuntu el menú suele estar oculto; mantén pulsada la tecla Mayús (BIOS) o pulsa Esc (UEFI) al arrancar desde la consola VNC para mostrarlo.
Una vez arrancado con el kernel de Ubuntu, desinstala el personalizado con apt, que también limpia /boot y regenera la configuración de GRUB:
sudo apt remove linux-image-${KVER}-custom linux-headers-${KVER}-custom
Para liberar espacio después de compilar, puedes borrar el árbol de compilación:
rm -rf ~/kernel/linux-${KVER}
Solución de problemas
No rule to make target 'debian/canonical-certs.pem': no se desactivaron SYSTEM_TRUSTED_KEYS o SYSTEM_REVOCATION_KEYS. Repite los comandos scripts/config del paso 3, ejecuta make olddefconfig y vuelve a compilar.
BTF: .tmp_vmlinux.btf: pahole (pahole) is not available: falta el paquete dwarves. Instálalo con sudo apt install dwarves y vuelve a lanzar la compilación.
El compilador muere con Killed o signal 9: el sistema se ha quedado sin memoria. Reduce el número de trabajos en paralelo, por ejemplo make -j2 bindeb-pkg, o añade swap temporalmente.
dpkg-buildpackage se queja de dependencias: el mensaje Unmet build dependencies indica qué paquetes faltan. Instálalos con apt y repite make bindeb-pkg.
Kernel panic - not syncing: VFS: Unable to mount root fs: el kernel no encuentra el controlador del disco o del sistema de archivos raíz. Suele ocurrir tras localmodconfig si el controlador no estaba en el initramfs. Arranca con el kernel anterior, revisa que CONFIG_VIRTIO_BLK, CONFIG_VIRTIO_SCSI (en máquinas virtuales KVM) y CONFIG_EXT4_FS estén activados como =y o =m y recompila.
Conclusión
Has compilado un kernel Linux desde el código fuente oficial, verificado su firma, adaptado la configuración de Ubuntu e instalado el resultado como paquetes .deb que puedes retirar con apt. Como siguientes pasos puedes:
- Repetir el proceso con cada versión nueva de la rama longterm elegida, reutilizando tu
.configconmake olddefconfig. - Medir el impacto de tus cambios con herramientas como
perfosysbenchantes y después de cambiar de kernel. - Explorar funciones que dependen del kernel, como eBPF, que aprovecha la información BTF que has generado.
