sábado, 23 de enero de 2021

Compilar un kernel en Debian 10 Buster

Compilar un kernel al estilo Debian 10 Buster, aunque este proceso esta realizado en Debian testing 11 Bullseye.


La distribución del kernel se realiza únicamente, en forma de código fuente, aunque lo habitual es utilizar el kernel que nos proporciona el creador de nuestra distribución, es posible compilarnos un kernel a medida para nuestra máquina.

La compilación de un nuevo kernel ofrece las siguientes ventajas:

- Aumentar las prestaciones: compilando un kernel para que se ajusten a las características propias de nuestra maquina

- Soporte nuevo de hardware: a medida que se lanzan nuevas versiones, se incrementan la cantidad de dispositivos soportados.

- Seguridad: como es lógico las prioridades a la hora de lanzar una nueva versión del kernel incluyen la corrección de todos los problemas de seguridad detectados.

- Nuevas características: cada versión del kernel que se lanza, se mejora sus funciones de gestión de memoria, sistema de ficheros, escalabilidad, etc.

Por el contrario, el proceso de compilar el kernel presenta los siguientes inconvenientes:


- Complejo: el proceso de compilar el kernel puede ser complejo para usuarios poco avanzados. Se debe tener un cierto conocimiento de hardware y de compilación si queremos afrontar con éxito la operación. En algunas ocasiones, al compilar el kernel, también debemos actualizar diversos programas del sistema con lo que la complicación es mayor.

- Problemas de inestabilidad: dado que el kernel es una parte fundamental del sistema operativo, una compilación realizada con opciones equivocadas puede volver inestable la maquina. Estos problemas de inestabilidad pueden producir "cuelgues", corrupción de datos, etc... por lo que conviene tenerlo muy en cuenta si el servidor guarda información importante.


========================================================

NOTA IMPORTANTE:
Tenga en cuenta que el proceso de compilación de un kernel, ya no es necesario ni recomendado ser root, se aconseja que se realice como un usuario normal del sistema (vamos un usuario cualquiera, que no sea administrador)

=========================================================


Como es el kernel de Debian

El núcleo o kernel que provee Debian incluye la mayor cantidad de funcionalidad posible así como también la mayor cantidad de controladores para cubrir el espectro más amplio de configuraciones de hardware.
Es por esto que algunos usuarios prefieren compilar el núcleo para incluir solamente y 
específicamente lo que necesiten.

Hay dos razones para esta elección:

- Podría optimizar el consumo de memoria ya que el código del núcleo, aún cuando no sea utilizado, ocupa memoria por nada (y nunca es «bajado» al espacio de swap, ya que utiliza RAM real) lo que puede disminuir el rendimiento general del sistema.

- Un núcleo compilado localmente también puede limitar el riesgo de problemas de seguridad ya que sólo se compila y ejecuta una fracción del código del núcleo.

=========================================================
OBSERVACION:
No es sorprendete que Debian administre el núcleo como un paquete, ya que no es la forma tradicional en la que se compilan e instalan núcleos. Debido a que el núcleo se mantiene bajo el control del sistema de paquetes, puede ser eliminado limpiamente o desplegado en varias máquinas. Es más, los scripts asociados con estos paquetes, automatizan la interacción con el gestor de arranque y el generador de initrd.
=========================================================

Las fuentes del kernel Linux en origen contienen todo lo necesario para crear el paquete Debian del núcleo. Sin embargo, se necesita instalar los siguientes paquetes:

- build-essential: para asegurarnos que tenemos las herramientas necesarias para crear el paquete Debian.

- libncurses5-dev: para la creación y configuración del archivo .config (aunque este paquete actualmente apunta al paquete llamado libncurses-dev, en próximas versiones de Debian, el paquete que se tiene que instalar se llamará: libncurses-dev)

- fakeroot: para realizar todo el proceso como usuario normal, sin utilizar permisos de administrador.

=========================================================
NOTA INFORMATIVA:
Las fuentes del núcleo Linux están disponibles en un paquete, en el repositorio oficial de Debian. Para obtenerlas simplemente instalamos el paquete linux-source-versión. Puede ver las diferentes versiones del núcleo empaquetados por Debian con el comando: apt search linux-source*. La última versión está disponible en la distribución Unstable: puede descargarlas sin problemas desde los repositorios oficiales de Debian. Sepa que el código fuente que contienen estos paquetes no corresponde exactamente con el código publicado por Linus Torvalds y los desarrolladores del núcleo o kernel Linux, cosa que pasa en todas las distribuciones, Debian aplica una serie de parches, que pueden (o no) ser incluídas en la versión de original del kernel Linux. Estas modificaciones incluyen retroadaptaciones de correcciones/funcionalidades/controladores de nuevas versiones del núcleo, funcionalidades que no están (completamente) incluídas en el árbol de origen de Linux e inclusive algunos cambios específicos para Debian.
=========================================================



¿Porqué compilar un kernel al estilo Debian y no hacerlo de la manera clásica?

El hecho de compilar al estilo Debian nos proporciona mas ventajas, ya que este se empaqueta automáticamente en un fichero con extensión .deb, es decir se crea un paquete del kernel nuevo, pudiendo grabarlo en un cd-rom, pendrive, Disco duro, ponerlo en nuestro servidor, en nuestro repositorio, etc.. para poder instalarlo en otros ordenadores de una manera muy sencilla.


Cambio en el proceso de compilación del Kernel.

- Anteriormente (ya no se usa este método) el paquete kernel-package : Antes que el sistema de compilación de Linux tuviera la capacidad de crear paquetes Debian apropiados, la forma recomendada de crear dichos paquetes era utilizar make-kpkg, incluido en el paquete kernel-package.

- Actualmente se usa build-essential: las fuentes del kernel de Linux en origen contienen todo lo necesario para crear el paquete Debian del núcleo. Sin embargo, necesitará instalar build-essential para asegurarnos que tenemos las herramientas necesarias para crear el paquete Debian.

- Anteriormente la ubicación de las fuentes (ya no se usa esta ubicación) del núcleo o kernel: Tradicionalmente, las fuentes del núcleo Linux estarían ubicadas en: /usr/src/linux lo que necesitaría permisos de root para compilarlo. Sin embargo, se debe evitar trabajar con permisos de administración cuando no es necesario. Existe un grupo llamado: src que permitía a sus miembros trabajar en este directorio, pero debe evitar trabajar en /usr/src de todas formas. Al mantener las fuentes del núcleo en nuestro directorio personal (por ejemplo en una carpeta llamada: /kernel), se obtiene seguridad en todos lados, no existirán archivos en /usr ajenos al sistema de paquetes y no hay riesgos de despistar a los programas que leen /usr/src/linux al intentar conseguir información sobre el núcleo utilizado.

- Actualmente se usa fakeroot: este paquete permite compilar el kernel o núcleo de Linux como paquete .deb de Debian sin utilizar permisos de administrador. Utilizando
 nuestro directorio personal (por ejemplo en una carpeta llamada: /kernel), se obtiene seguridad en todos lados


========================================================================

COMENZAMOS EL PROCESO DE COMPILAR EL KERNEL LINUX

========================================================================


Recordar que todo el proceso de compilación se realiza como usuario normal, y realizaremos todo el proceso en modo gráfico (descarga y descompresión del archivo tar.xz, copiado, renombrado y edición del archivo .config) desde el explorador de archivos Dolphin, y en una carpeta llamada: kernel. Finalizamos el proceso en una consola de comandos, también como usuario normal: make deb-pkg LOCALVERSION=-usuariodebian.


Únicamente, la instalación del nuevo kernel que hemos creado se hace como usuario administrador (root)



0- Espacio libre necesario

Les informo: Para compilar un kernel o núcleo de Linux, se necesitan al menos 25 gb de espacio disponible, porque compilar el kernel de linux ocupa alrededor de 22 gb.
Aunque los archivos generados para el nuevo kernel ocupa muchísimo menos, abajo vemos lo que ocupa aproximadamente cada archivo:

- linux-headers-5.9.12-usuariodebian_5.9.12-usuariodebian-1_amd64.deb (7,5 mb)

- linux-image-5.9.12-usuariodebian_5.9.12-usuariodebian-1_amd64.deb (50,1 mb)

- linux-image-5.9.12-usuariodebian-dbg_5.9.12-usuariodebian-1_amd64.deb (608,9 mb)

- linux-libc-dev-5.9.12-usuariodebian-1_amd64.deb (1,1 mb)

Una vez creado los paquetes necesarios, podemos borrar la carpeta /kernel/linux-5.9.12 que pesa mas o menos 22 gb, para recuperar dicho espacio.




1- Instalar los programas necesarios para compilar

Para realizar todo el proceso sin problemas, necesitamos tener instalados los siguientes paquetes: build-essential, libncurses5-dev, fakerootlibssl-dev, gcc, bc, bison, flex, libelf-dev, kmod, cpio (aunque realmente el manual oficial de Debian nos dice que solo se necesita los paquetes: build-essentiallibncurses5-dev (aunque este paquete actualmente apunta al paquete llamado libncurses-dev, en próximas versiones de Debian, el paquete que se tiene que instalar se llama: libncurses-dev)
, y fakeroot)

Y como siempre hacemos en este blog, y con la ayuda del programa synaptic, instalamos los siguiente paquetes:

# apt install build-essential libncurses5-dev fakeroot libssl-dev gcc bc bison flex libelf-dev kmos cpio






============================================================
IMPORTANTE:
Antes de comenzar el proceso de compilación, asegúrese de que el protector de pantalla y la suspensión automática estén deshabilitados, ya que en muchos casos interrumpirían el proceso de compilación.
============================================================



2- Descargar el código fuente del nuevo kernel

Descargaremos el ultimo kernel estable, y evitaremos descargar kernels de versiones RC, ya que pueden ser inestables. Se recomienda elegir un kernel de lanzamiento estable y de largo plazo. Para ello nos vamos a
La web oficial del kernel Linux: http://www.kernel.org

Una vez que haya elegido la versión del kernel que desea descargar. Haga clic en el enlace que dice " [tarball] ". Ahora la descarga comienza y estaremos descargando un archivo que termina en " .tar.xz ".




3- Descomprimir el archivo fuente .tar.xz

Una vez completada la descarga, no situamos en la carpeta donde se encuentra el archivo .tar.xz que hemos descargado, y usamos el programa Ark, para descomprimirlo.




Al descomprimir el archivo, nos crea una carpeta que tiene el mismo nombre del archivo descargado: linux-5.9.12


O si prefieres hacerlo desde una consola de comandos, tienes que usar los siguientes comandos:


$ mkdir ~/kernel

$ cd ~/kernel

$ tar -xaf /usr/src/linux-5.9.12.tar.xz




4- Configurar el kernel

Antes de que podamos compilar la fuente de kernel Linux que hemos descargado, necesitamos tener un archivo de configuración, llamado .config. Este archivo de configuración le dice al compilador qué características tiene que configurar, tales como: controladores, sistemas de archivos, seguridad, etc...

Es muy difícil crear y/o editar manualmente el archivo de configuración .config, ya que cuenta con miles de opciones y módulos.

Entonces, tenemos dos formas de crear el archivo de configuración:

1- Creamos un nuevo archivo de configuración (.config) basado en los dispositivos que actualmente tenemos conectados a nuestro ordenador.

2- Copiar el archivo de configuración del kernel actual de Debian 
(.config).

Al compilar una versión más reciente del núcleo o kernel linux, probablemente usemos la misma configuración propuesta por Debian. En este caso, y en lugar de reconfigurar todo desde cero, es suficiente copiar el archivo /boot/config-versión (donde versión: es la del núcleo utilizado actualmente, que se encuentra en el directorio /boot) y lo copiamos en el directorio /kernel/linux-5.9.12 cambiándole el nombre a .config

Por tanto usaremos la opción 2, copiamos el archivo de configuración del kernel actual de Debian.

Lo hacemos desde el explorador de archivos Dolphin, y usando la tecla F3 (Dividir pantalla del explorador), nos posicionamos en ambas carpetas:

- Lado izquierdo en: /home/nuestro_usuario/kernel/linux-5.9.12
- Lado derecho en: /boot 


y en el lado derecho buscamos el archivo que vamos a copiar, en esta manual vamos a usar, el archivo: config-5.8.0-2-amd64 (pero vosotros podéis usar cualquier otro)


lo seleccionamos con el ratón y lo arrastramos al lado izquierdo y soltamos el botón izquierdo del ratón


al soltar el botón izquierdo nos aparece la siguiente ventana preguntándonos que vamos a hacer, seleccionamos: Copiar aquí


y vemos como se a copiado


Ahora tenemos que cambiarle el nombre de: config-5.8.0-2-amd64 a .config para ello pulsamos la tecla F2, o pulsamos con el botón derecho del ratón y seleccionamos cambiar nombre...


y le cambiamos el nombre a: .config, y pulsamos la tecla Intro.
Al pulsar la tecla intro, nos informa: Si añade un punto al principio del nombre este sera un archivo oculto.
Pulsamos en Cambiar nombre y ocultar


una vez cambiado el nombre a .config, ya no aparece, observamos como esta oculto.



Podemos realizar el mismo proceso desde una consola de comando.
Para copiar el archivo de configuración, usamos el siguiente comando:

$ cp /boot/config-5.8.0.2-amd64 ~/kernel/linux-5.9.12/.config

o este otro comando dependiendo de donde no encontremos situado:

$ cp /boot/config-$(uname -r) .config


======================================
Volviendo a la opción 1-: Si necesitas cambiar o si decide reconfigurar todo desde cero (.config). Hay varias interfaces dedicadas para dicha operación, en el directorio de fuentes del núcleo que puedes utilizar ejecutando make objetivo donde objetivo es uno de los valores descritos al final de este manual.
======================================




5- Compilación y creación del paquete .deb

=========================================================
NOTA IMPORTANTE: 
Si hemos copiamos la configuración de un archivo .config desde /boot, debemos modificar la opción de llaves de confianza del sistema, por tanto tenemos que editar el archivo: .config y asignarle una cadena vacía a la siguiente variable: CONFIG_SYSTEM_TRUSTED_KEYS. quedaría tal cual: CONFIG_SYSTEM_TRUSTED_KEYS = "".

Y si ya hemos realizado una compilación en el directorio y deseamos reconstruir todo desde cero (por ejemplo: porque realizó cambios importantes a la configuración del núcleo), tendrá que ejecutar make clean para eliminar los archivos compilados. make distclean elimina todavía más archivos generados, incluyendo también el archivo .config, por lo que deberá asegurarnos de hacer una copia antes de borrarlo. 
=========================================================

Como nosotros hemos copiado el archivo .config desde /boot, vamos a asignarle una cadena vacía a la variable: CONFIG_SYSTEM_TRUSTED_KEYS 

Para ello en el explorador de archivos Dolphin, pulsamos la combinación de teclas Ctrl + h, o pulsamos en el menú: Ver > Mostrar archivos ocultos



y ya visualizamos el archivo oculto .config



Hacemos clic en el archivo .config para editarlo, y buscamos la variable: CONFIG_SYSTEM_TRUSTED_KEYS 


A nosotros nos interesa la cadena que aparece entre comillas


y borramos dicha cadena, la dejamos vacía



Una vez que está preparado el archivo de configuración del núcleo llamado .config, solo nos queda compilar el kernel de Linux.

Para ello tenemos que abrir una consola de comandos y situarnos en la carpeta: /home/nuestro_usuario/kernel/linux-5.9.12 lo mas fácil es abrir una consola directamente desde Dolphin, para ello desde la carpeta: /kernel/linux-5.9.12 hacemos clic derecho del ratón en un espacio en vacío de dicha carpeta, y seleccionamos: Acciones > Abrir terminal aquí...


y vemos como se no abre un terminal de comandos



simplemente ejecutamos el siguiente comando:


$ make deb-pkg


o si quiere personalizar el nombre puede usar:


$ make deb-pkg LOCALVERSION=-usuariodebian



Cambiando usuariodebian por el nombre que quieras.



========================================================
Muy importante al principio del proceso de compilación:
- Para la mayoría de usuarios, pulsamos la tecla Intro para todas las preguntas que nos hace al principio del proceso de compilación, ya que nos solicita habilitar las nuevas funciones. (Al pulsar intro toma la opción por defecto). En caso contrario, si sabes la respuesta de las preguntas realizadas, entonces debes leer cada pregunta y contestar según tus necesidades.

- Dependiendo de la potencia de tu ordenador, el proceso de compilación puede tardar desde algunos minutos, hasta algunos días.

- No interrumpas el proceso de compilación, de lo contrario tendrás que empezar desde el principio.
========================================================










Una vez finalizado el proceso se generará hasta 5 paquetes Debian: 


- linux-image-versión: contiene la imagen del núcleo y los módulos asociados.

- linux-headers-versión: contiene los archivos de cabecera necesarios para crear módulos externos

- linux-image-versión-dbg: contiene los símbolos de depuración para la imagen del núcleo y sus módulos

- linux-libc-dev: contiene las cabeceras relevantes a algunas bibliotecas de espacio de usuario como glibc de GNU.

- linux-firmware-image-versión: contiene los archivos de firmware necesarios para algunos controladores (este paquete puede no aparecer cuando se compila el kernel a partir de las fuentes proporcionadas por Debian)




5- Instalación del kernel compilado

Una vez que el proceso de compilación se haya completado con éxito (sin errores), encontrará los nuevos paquetes creados con el kernel de Linux en formato .deb en el directorio superior (en este manual es : ~/kernel).


Ahora puedes instalarlo en tu ordenador y/o distribuir estos paquetes en formato .deb para instalarlo en otros ordenadores, como un kernel ya compilado. 
La instalación se puede hacer desde consola, escribiendo uno o varios comandos, o desde el entorno gráfico, usando la aplicación: qapt-deb-installer. Si vas realizar la instalación desde el entorno grafico tienes que instalar dicho paquete: qapt-deb-installer


Instalación desde una consola de comandos.

Desde consola, podemos instalarlo ejecutando los siguiente comando.
- Usamos el primer comando para volver a la carpeta: kernel

$ cd ..



- Ahora usamos el siguiente comando para instalar los paquetes de uno en uno:

$ dpkg -i nombre_de_paquete.deb

Donde nombre_de_paquete es el nombre de uno de los nuevos archivos creados.



- Si los quieres instalar todos los paquetes de una sola vez, usaremos el siguiente comando:

$ dpkg -i linux-*.deb




Una vez terminada la instalación, puede reiniciar su ordenador y disfrutar del nuevo kernel compilado.


Instalación desde el entorno gráfico.

Si vas realizar la instalación desde el entorno gráfico tienes que instalar el paquete: qapt-deb-installer


Una vez instalado, nos situamos en la carpeta: kernel y hacemos clic con el ratón en un archivo para instalarlo.


En este caso he seleccionado el archivo llamado: linux-image-5.9.12-usuariodebian_5.9.12-1_amd64.deb, y nos aparecerá el instalador de qapt-deb-installer.
Vemos que contiene tres pestañas y cada una tiene informa relevante de dicho fichero.




Pulsamos en: Install Package para realizar la instalación.
Lógicamente nos pide la contraseña de administrador. Pulsamos Aceptar



Observamos el proceso de instalación.



Pulsamos en Cerrar para finalizar.

Realizamos el mismo proceso con el paquete: linux-headers-5.9.12-usuariodebian_5.9.12_amd64.deb





Puedes realizar el proceso con los otros dos paquetes que faltan por instalar, aunque con los dos paquetes anteriores ya es funcional.
 
Si ahora usamos synaptic, podemos ver los paquetes que acabamos de instalar.




En la siguiente captura de pantalla, podemos ver como esta en perfecto funcionamiento, el nuevo kernel instalado.





=======================================================
NOTA IMPORTANTE:
- Si hemos copiado el archivo de configuración (.config) de otro kernel de Debian, seguramente funcionara sin problemas.

- Si hemos compilado desde cero o hemos realizado cambios importantes en un archivo de configuración (.config) de otro kernel de Debian,  se recomienda que antes de instalar el nuevo kernel en un ordenador real, primero instale el nuevo kernel en una ordenador virtual para asegurarse que todo funciona bien. Y si todo funciona bien, entonces ya lo puedes instalar en un ordenador real.
=======================================================

-------------------------------------------

Regresando al punto 4- Configurar el kernel descargado

1- Creamos un nuevo archivo de configuración (.config) basado en los dispositivos que actualmente tenemos conectados a nuestro ordenador.

Como dijimos antes. Si necesitas cambiar o si decide reconfigurar todo desde cero (.config). Hay varias interfaces dedicadas para dicha operación, en el directorio de fuentes del núcleo que puedes utilizar ejecutando make objetivo donde objetivo es uno de los valores descritos a continuación:


- make menuconfig: compila y ejecuta una interfaz en modo texto (aquí es donde necesita el paquete libncurses5-dev) que permite navegar entre las opciones disponibles en una estructura jerárquica. 

- Tecla Espacio: cambia el valor de la opción seleccionada
- Tecla Enter: valida el botón seleccionado al pie de la pantalla
Seleccionar: vuelve al submenú seleccionado
- Salir: cierra la pantalla actual y vuelve un paso atrás en la jerarquía
- Ayuda: mostrará información más detallada sobre el comportamiento de la opción seleccionada.
- Las teclas de flecha: le permiten moverse en la lista de opciones y botones. 
- Para salir del programa de configuración, seleccione Salir del menú principal. El programa luego ofrece guardar los cambios que realizó; acéptelos si está satisfecho con sus selecciones.

Existen otras interfaces  que tienen funcionalidades similares pero trabajan con interfaces gráficas más modernas, como:

make xconfig que utiliza una interfaz gráfica QT (necesita instalar el paquete libqt4-dev)

make gconfig que utiliza GTK+ (necesita instalar los paquetes libglade2-dev y libgtk2.0-dev)

Cuando utiliza una de las interfaces de configuración, siempre es buena idea comenzar desde una configuración predeterminada razonable. El núcleo provee tales configuraciones en:  arch/arquitectura/configs/*_defconfig 
y puede mover la configuración que desee:

- En el caso de un equipo de 64 bits a: make x86_64_defconfig 
- En el caso de un equipo de 32 bits a: make i386_defconfig 










2 comentarios:

Knight99 dijo...

Muy buen artículo.
Lo he seguido para compilar el kernel 6.4 sobre Debian 12, y sin problemas.
Por si fuera de tu interés, y de cara a futuras actualizaciones del post, te indico las 2 únicas diferencias que he visto en el procedimiento:

1.- las llaves de confianza que debemos dejar 'vacías' (siempre que nos hayamos copiado el archivo de configuración desde /boot, son 2:
CONFIG_SYSTEM_TRUSTED_KEYS=""
CONFIG_SYSTEM_REVOCATION_KEYS=""

2.- Y para la creación de los paquetes, tuve que usar:
$ make bindeb-pkg (en vez de make deb-pkg)

Por lo demás, todo perfecto.

Aunque aquí no lo probé, supongo que el 'make' admitirá el parámetro -j para indicarle que use todos los core posibles del procesador. En otra distribución yo usé el make de la siguiente forma:
$ make -j $(nproc) para que me tomara todos los núcleos.
Cuando vuelva a animarme a compilar otra versión, en Debian, probaré a ver si funciona algo del tipo: make -j 8 bindeb-pkg

Knight99 dijo...

Muy buen artículo.
Lo he seguido para compilar el kernel 6.4 sobre Debian 12, y sin problemas.
Por si fuera de tu interés, y de cara a futuras actualizaciones del post, te indico las 2 únicas diferencias que he visto en el procedimiento:

1.- las llaves de confianza que debemos dejar 'vacías' (siempre que nos hayamos copiado el archivo de configuración desde /boot, son 2:
CONFIG_SYSTEM_TRUSTED_KEYS=""
CONFIG_SYSTEM_REVOCATION_KEYS=""

2.- Y para la creación de los paquetes, tuve que usar:
$ make bindeb-pkg (en vez de make deb-pkg)

Por lo demás, todo perfecto.

Aunque aquí no lo probé, supongo que el 'make' admitirá el parámetro -j para indicarle que use todos los core posibles del procesador. En otra distribución yo usé el make de la siguiente forma:
$ make -j $(nproc) para que me tomara todos los núcleos.
Cuando vuelva a animarme a compilar otra versión, en Debian, probaré a ver si funciona algo del tipo: make -j 8 bindeb-pkg