Conceptos de los Ports de FreeBSD

De BSD Chile


Tabla de contenidos

Introducción

Este artículo es trabajo en obra. Gracias por tener un poco de paciencia mientras el contenido se finaliza.

Este artículo se dedica particularmente a nuevos o futuros administradores de FreeBSD (en ambiente profesional o simples usuarios a cargo de su máquina), o a usuarios que quieren afinar el manejo de su sistema. El objetivo es mostrar cómo se instalan y mantienen aplicaciones en el contexto de FreeBSD, asegurando una manipulación simple y optimizada sin comprometer la seguridad general de la estación de trabajo o del servidor. Se presenta en forma detallada los pasos a seguir para instalaciones desde fuentes y paquetes binarios, y las ventajas de cada método.

Finalmente, se presenta brevemente la distribución PCBSD, basada en FreeBSD y que permite juntar las ventajas de ambos modelos. PC-BSD será el objeto de otra presentación en este Wiki en un futuro cercano.

Ogautherot

Kernel y sistema base

(Una parte de esta sección retoma información de http://en.wikipedia.org/wiki/Berkeley_Software_Distribution)

Historicamente, BSD (Berkeley Software Distribution) empezó en 1977 con una distribución de software para el sistema UNIX de AT&T. En 1979, se publicó la primera distribución de un sistema completo, bajo el nombre de 3BSD, que incluía un kernel para VAX. Desde esta fecha, las distribuciones libres (FreeBSD, OpenBSD, NetBSD, etc.) y los productos (BSDi, SunOS, etc.) basados en BSD son sistemas operativos completos con su ambiente propio. De esta historia, los BSD conservan herramientas de base específicas que marcan su identidad y relación estrecha con el UNIX original.

En 1983, Richard Stallman inició un proyecto de software libre que iba a dar la luz a la licencia GNU, un acrónimo recursivo que significa "GNU is Not Unix". Es un ambiente parecido a UNIX pero que se diferencia en su sintaxis, con opciones distintas para evitar problemas de copyright. En 1991, se adoptó el kernel Linux para completar el sistema .

Si estos 2 sistemas tienen historias distintas y licencias algo conflictivas, comparten sin embargo una gran cantidad de aplicaciones, que se encuentran en la sección "Ports" o "Packages" de los *BSD.

Aplicaciones de terceros

Actualmente, FreeBSD cuenta con más de 16.000 paquetes opcionales en los ports. Es imposible dar una lista exhaustiva de todas estas aplicaciones pero suelen cubrir muchas de las necesidades de los usuarios: productividad, editores, computación científica, ingeniería, manejo de redes, servidores, audio y multimedia, desarrollo, juegos, etc. Para una información completa, le recomiendo consultar la página web de Freshports [1], que se dedica a la publicación integral de los ports.

En su mayoría, estas aplicaciones vienen en forma de código fuente adaptado para FreeBSD, a menudo bajo licencia GNU. Otras aplicaciones propietarias se distribuyen como ejecutables compilados para Linux y se ejecutan vía una capa de emulación, como el Acrobat Reader, por ejemplo.

Distribución binaria versus fuentes

La decisión de entregar código fuente o binarios es principalmente una cuestión de filosofía. Un binario es más compacto y se instala rápidamente. Sin embargo, fue compilado con un conjunto de opciones predefinido, que no corresponden siempre a las necesidades del usuario. En el ambiente FreeBSD, la instalación de binarios se llama "packages".

La compilación del código fuente requiere más espacio en el momento de la instalación pero ofrece una granularidad mayor en la selección de las opciones y se adapta solo a la arquitectura real de la máquina (puede aprovechar instrucciones MMX si el procesador les soporta, activar funciones que requieren una biblioteca particular que ya está cargada en el sistema, etc.) Eso permite obtener una aplicación más adecuada a las necesidades y más optimizada.

El sistema de ports efectúa una análisis fino de los requerimientos, que se llaman dependencias. En muchos casos, la compilación de una aplicación provoca la compilación de varias dependencias, si no están presentes. Por ejemplo, OpenOffice instala primero Java, una versión particular del compilador GCC, Bison y varias otras cosas - una recompilación suele tomar la mitad del tiempo de la primera instalación, justamente por las dependencias que ya están presentes.

Además del tiempo de instalación, el tipo de entrega afecta la mantención: un binario tiene un lista de dependencias predefinida y el editor sabe de antemano cuáles son los paquetes afectados por un patch de seguridad. Una instalación por compilación de fuentes puede cambiar la lista real de dependencias según las opciones activadas, lo que requiere una anotación exhaustiva de las dependencias y un análisis fino en el momento de corregir una biblioteca.

Licencias y restricciones

Para entender lo que se puede hacer y lo que se debe evitar, veamos brevemente el problema de las licencias. ¿Por qué hay 2 sistemas compitiendo para ser la referencia del mundo libre? En realidad, son varios más sistemas si incluimos Minix, OpenSolaris, etc. pero las licencias se aparentan siempre a uno de los 2 modelos a continuación.

El concepto desarrollado por BSD consiste en publicar parcialmente su trabajo para el bien de la comunidad. Era el ideal de los informáticos de la primera era, cuando los diseñadores eran unos pocos fanáticos. El hecho de publicar una parte de su trabajo permitía a otros de desarrollar sus propios productos, realizando la masa crítica necesaria para el despegue de esta tecnología. En aquella época, la aplicación soportaba muchas de las funciones que están integradas al sistema operativo hoy día.

En 1983, el mundo comercial y la competencia se hacían más fuerte. La idea de Richard Stallman era de conservar el ambiente original, con desarrolladores que comparten experiencia y desarrollos. Su visión era que, si un desarrollador usa código publicado por otro, crea una "obra derivada", que también se debe publicar. Este concepto se describe a veces como el "efecto viral" de GNU, que obliga a publicar código que el autor, originalmente, quería mantener propietario. Por eso, es importante verificar la licencia del código reutilizado antes de empezar un desarrollo.

Al nivel del usuario final, las 2 licencias son transparentes y equivalentes.

Principios usados por otros sistemas operativos

La distribución de aplicaciones suele depender del sistema operativo, de su popularidad y de las costumbres de su comunidad.

.MSI y .EXE

Los .msi y .exe son típicos de MS Windows. Corresponden a una distribución binaria incluida en una aplicación que se encarga de la configuración del sistema operativo. Son muy cómodos para el usuario, que no necesita configurar nada manualmente. Un equivalente en el mundo UNIX son los .bin de aplicaciones propietarias, que se encargan de lo mismo.

Estos archivos son compilados para una arquitectura y un sistema operativo y, aparte de aplicaciones en Java, no suelen ser portables.

.RPM, .DEB, .TGZ

Un modelo más elemental es el .tgz (tar-gzip), que es un respaldo de la distribución que se restaura en la máquina de destino. Tiene la desventaja que la configuración se debe hacer a mano. Tampoco dejan constancia de la instalación, lo que complica la mantención.

Los .rpm y .deb del mundo Linux empiezan por copiar los ficheros en su destino y actualizan una base de datos de aplicaciones instaladas. Suelen contener también un script de configuración de parámetros si necesario.

Como en la sección anterior, estos modelos no suelen ser portables.

Fuentes - por ejemplo, SourceForge

El modelo más abierto es el código fuente. De estos modelos, es el único que no protege el "know-how" del autor pero permite detectar la plataforma en la que se está instalando la aplicación y adaptarla a este ambiente particular.

Según la fuente del código, puede o no compilar directamente en FreeBSD. En general, aplicaciones GNU son desarrolladas en GNU/Linux y requieren algunos cambios para compilar en *BSD. Los proyectos en SourceForge suelen indicar los sistemas soportados.

Los Packages

Para los que necesitan levantar su sistema rápidamente, FreeBSD cuenta con un repositorio de archivos de instalación binarios.

Las herramientas de manejo de packages son extensiones del sistema de base y se deben compilar. Lo básico se instala con:

cd /usr/ports/sysutils/portupgrade
make install clean

Se recomienda instalarlo antes de pasar a las secciones a continuación. En general, se recomienda leer los manuales de los varios comandos después de su instalación para asegurarse de las opciones y de su uso.

Descargar e instalar un package

Lo más simple para descargar un package es revisar en Freshports.org el nombre exacto del paquete a cargar e invocar pkg_add. Por defecto, pkg_add instala solamente el paquete indicado, lo que no asegura la funcionalidad. Por lo tanto, se recomienda usar la opción -r que instala también las dependencias. pkg_add busca los archivos de instalación en prioridad en /usr/ports/packages/All y, si no los encuentra, los baja de un repositorio en Internet.

Si la meta es simplemente de construir un repositorio local, se puede usar pkg_fetch, que baja los paquetes pedidos. Se recomienda añadir la opción -R para conseguir también las dependencias todavía no instaladas. Si el repositorio se debe usar en red para varias máquinas sin tener la certeza que todas tienen siempre la misma lista de paquetes, se debe invocar también con la opción -f para asegurar que el repositorio este completo. Por ejemplo:

pkg_fetch -R -f teTeX

Desinstalar packages

Para desinstalar un paquete, el comando más básico es pkg_delete: permite remover los ficheros específicos listados en la base de datos, a la condición que otros paquetes no dependan de él. Si un nuevo paquete requiere que otro sea desinstalado primero, por ejemplo si ambos comparten un mismo fichero pero que el paquete a desinstalar es una dependencia, se puede forzar con la opción -f.

pkg_deinstall es una versión un poco más sofisticada pero que, básicamente, tiene la misma función. Se recomienda para sacar paquetes completos, con sus dependencias.

A veces, el administador quiere limpiar un sistema de todos los paquetes inútiles - es decir paquetes que los usuarios no usan ni directamente, ni indirectamente. Este caso se puede presentar después de remover otros paquetes, lo que puede liberar dependencias. Los paquetes que se encuentran al final de la lista de dependencias se llaman "hojas" o "leaves". Esta limpieza se puede efectuar con pkg_rmleaves.

Buscar información sobre packages instalados

Lo más rápido para buscar qué paquetes están instalados es revisar el contenido de la base de datos en el directorio /var/db/pkg. Cada aplicación tiene su propio directorio con su descripción, contenido y dependencias. El nombre del directorio indica también la versión. Por ejemplo, /var/db/pkg/aalib-1.4.r5_2 .

pkg_version revisa los paquetes instalados y los compara con la versión actual del sistema de ports. Eso indica cuáles son los que necesitan una actualización.

# pkg_version -v
ImageMagick-6.2.5.5_3               =   up-to-date with port
LinNeighborhood-0.6.5_6             =   up-to-date with port
MuSE-0.9_3                          =   up-to-date with port
ORBit-0.5.17_3                      =   up-to-date with port
ORBit2-2.12.5_2                     =   up-to-date with port
OpenEXR-1.2.2_1                     =   up-to-date with port
...
#

El comando pkg_info agrega una descripción del rol del paquete.

# pkg_info sdcc-2.5.4.2005.11.15
Information for sdcc-2.5.4.2005.11.15:

Comment:
Small Device C Compiler

Description:
SDCC is a Freeware, retargettable, optimizing ANSI-C compiler that
targets the Intel 8051, Maxim 80DS390 and the Zilog Z80 based MCUs.

SDCC also comes with the source level debugger SDCDB, using the
current version of Daniel's s51 simulator.

WWW: http://sdcc.sourceforge.net/

- Tijl Coosemans
tijl@ulyssis.org

#

Para conocer las dependencias y determinar la jerarquía de los cambios necesarios en una actualización, o los conflictos en caso de dependencias compartidas, el sistema ofrece también la visualización del árbol instalado:

# pkg_tree aalib
aalib-1.4.r5_2
|\__ expat-2.0.0_1
|\__ pkgconfig-0.20
|\__ libdrm-2.0_1
|\__ freetype2-2.1.10_3
|\__ fontconfig-2.3.2_3,1
 \__ xorg-libraries-6.9.0
#

pkg_glob y pkg_sort se pueden usar para establecer una lista que paquetes instalados por orden de dependencias.

Investigar la base de datos de packages

Muchos paquetes instalan más de un ejecutable y, a veces, no es obvio determinar qué paquete instaló qué archivo. Para eso, se desarrolló la herramienta pkg_which que indica las dependencias.

# pkg_which pkg_fetch
portupgrade-2.0.1_1,1
#

En general, pkgdb sirve para la mantención de la base de datos. Las opciones más frecuentes son -F para la reparación del árbol -u para su actualización. Nota: la instalación de una aplicación no actualiza automáticamente el árbol para ganar tiempo y evitar daños con ejecuciones concurentes.

Construir sus propios packages

La creación de un paquete nuevo pasa por pkg_create. Ver otro artículo en este WiKi acerca de la creación de paquetes.

Opcionalmente, se puede insertar una firma con pkg_sign para asegurar una descarga segura sin depender de una firma MD5 separada. La integridad del archivo se verifica después con pkg_check.

Detectar packages no usados

En el momento de limpiar un sistema para sacar ejecutables no necesarios, pkg_cutleaves presenta uno por uno los paquetes que no son dependencias de otros.

Los Ports

A la diferencia de los packages, los ports se compilan localmente antes de su instalación. Eso permite afinar las opciones y asegurar que la instalación sea terminada exitosamente.

Instalación básica

Después de cargar el árbol de ports, se puede instalar un port con un simple comando, como (en el caso de SDCC):

# cd /usr/ports/lang/sdcc
# make install clean

El proceso se encarga de bajar el código fuente, compilarlo, instalar los ejecutables y limpiar el árbol - remover el subdirectorio work que se creó para la compilación y que suelen ocupar mucho espacio - por ejempo, OpenOffice ocupa hasta 6,5GB antes de instalación. Por defecto, los ports se compilan en la partición /usr. Según su tamaño, su tasa de utilización y el tamaño del paquete a compilar, uno puede llegar a llenar esta partición y causar efectos colaterales. Para evitar problemas de este tipo, se puede mover el árbol a otra partición y crear un enlace simbólico con:

ln -s /OtroDisco/usr/ports /usr/ports

o definir la variable de ambiente PORTSDIR para definir su nuevo lugar.

Los Makefile compilan e instalan las dependencias necesarias que todavía no se encuentrran disponibles en el sistema. En general, se recomienda instalar primero los paquetes pesados (como OpenOffice, por ejemplo) para minimizar los riesgos de desbordamiento de disco.

La técnica del make install clean tiene la ventaja de iniciarse rápidamente. En caso de que el paquete ya esté instalado, el Makefile se fija solamente al final, después de una posiblemente larga compilación.

Esta opción de compilación directa permite también elegir entre varias versiones de una misma aplicación: por ejemplo, Samba está disponible en inglés (en /usr/ports/net) y en japonés (en /usr/ports/japanese).

Opciones de compilación

Los Makefile suelen soportar la opción make config que define las opciones del paquete. Así, se puede activar la optimización del compilador, seleccionar el tipo de SSH a integrar, etc. Esta opción ajusta automáticamente las dependencias, en el caso de que se requiera.

Base de datos

Los ports mantienen una base de datos que les permite definir las dependencias pendientes de los paquetes a instalar.

Esta base de datos es relativemente frágil en el sentido que es mono-usuario: 2 compilaciones concurrentes pueden provocar una falla. Lo más probable es que las compilaciones no se terminen juntas y que no pase nada pero el riesgo está. Otra razón para evitar compilaciones paralelas son las dependencias: cada compilación empieza por limpiar sus dependencias, que otro paquete puede estar compilando. En este caso, el segundo paquete falla, aunque no debería.

Los errores de base de datos se notan fácilmente, con mensajes de 'ruby'. En este caso, remover /var/db/pkg/pkgdb.db y reconstruirlo con pkgdb -u.

Instalación controlada

El sistema de ports ofrece también una herramienta de instalación de paquetes llamada portinstall. Empieza por revisar en forma recursiva todos los requerimientos de la instalación pedida. La demora en partir depende altamente de los paquetes ya instalados pero compila solamente lo que se necesita.

Actualización

La actualización de aplicaciones se hace con portupgrade. Se requiere después de actualizar los ports y actúa solamente sobre las aplicaciones que cambiaron.

2 de las opciones principales son -r para, además de las dependencias, actualizar los paquetes que dependen del que se está actualizando (dependencias inversas) y -a para actualizar todos los paquetes instalados.

Análisis de los ports ya instalados

Después de su compilación, los ports se instalan como package y se pueden listar de la misma manera con:

ls /var/db/pkg

Una alternativa, que usa las heramientas específicas, es portsversion, que además determina qué paquetes necesitan actualización. Eso aplica sobre todo a los sistemas que acaban de actualizar /usr/ports con el último snapshot o con un cambio de release. Para ver los cambios disponibles, se pueden combinar comandos como:

portsversion | grep -v = 

que extrae las líneas que reportan versiones no idénticas.

Los comandos se pueden combinar libremente para obtener los efectos deseados. Por ejemplo, el número de ports a actualizar se consigue con:

portsversion | grep -v = | wc -l 

Otro ejemplo que muestra las diferencias de versión:

portsversion -v | grep -v = 

o que se restringe a los ports relacionados con KDE:

portsversion -v \*kde\* | grep -v = 

El límite de este concepto es la imaginación del usuario:

portversion -r kde\* | grep \< | awk '{ print "Debo actualizar " $1; }' | mail olivier

Les dejo como tárea la análisis de este último comando. ;-)

Mantención de versiones

portmaster tiene una funcionalidad interesante, que es la determinación del tipo de relación dentro de la jerarquía (portmaster -l). Las otras funciones se duplican relativamente fácilmente con portupgrade.

Limpieza del árbol

Si el árbol de ports ocupa alrededor de 300MB después extracción, puede llegar a gastar un espacio tremendo después de compilar los paquetes. El espacio usado se puede clasificar en 3 grupos: el árbol, las distribuciones de las aplicaciones (típicamente en /usr/ports/distrib) y el espacio de trabajo.

El árbol en si contiene referencias para las dependencias, los repositorios del código fuente e información general para el usuario. Cada directorio contiene un Makefile que define el rol del directorio. Note que borrar directorios afecta la integridad del árbol y puede causar errores de compilación.

Las distribuciones vienen en forma de archivos comprimidos .tgz (TAR-GZIP) o .tbz (TAR-BZIP2).

Resolución de dependencias con portsdb

Estrategia de mantención y seguridad

Mantener un sistema operativo es la meta número 1 de todo administador. A menudo, se trata de luchar contra los usuarios que quieren cambiar cosas a su "pinta" o un proveedor que actualiza funcionalidades, pensando que es mejor. Como dice el refrán, "el 'mejor' es el enemigo del 'bien'", o en una versión más pragmática: "If it works, don't fix it!" (si funciona, ¡no lo repares!)

Sin embargo, las causas de fallas no son siempre internas: numerosos servidores web fueron botados por terroristas, cuya meta es simplemente dañar la propiedad de otros, que sea para afectar la imagen de otros o puro deporte. Por eso, es importante seguir las publicaciones de vulnerabilidades de los paquetes instalados y evaluar el peligro. Recuerde que no todos los grupos tienen su auditor de seguridad y que una falla sin descubrir es latente... Nunca debe bajar la guarda con "el falso sentimiento de seguridad": un cortafuergo y un antivirus no son suficientes. En esta sección, vamos a revisar las técnicas de actualización y de auditoría de un sistema.

Versión estable con las entregas oficiales

La meta número 1 siendo asegurar que el sistema sigue funcionando sin drama... significa que se debe instalar un sistema con la etiqueta CVS "-RELEASE": estas versiones pasaron por un ciclo intensivo de QA y todas las aplicaciones del árbol de ports fueron probadas. En fin, es la opción que trae menos jaquecas en el momento de levantar un nuevo servicio.

Mi consejo es siempre mantener una copia del árbol original de la release para asegurarse que uno siempre puede volver al estándar probado. También, recomiendo no actualizarlo a menos que sea necesario - y, en muchos casos, no lo es.

Versión -CURRENT

Esta versión es para los que aman vivir en peligro. Suele ser relativamente estable e incluye las correcciones para las vulnerabilidades detectadas pero, para ser consecuente, requiere una mentención permanente. Mi pregunta es siempre: ¿cuál es la meta de mi sistema: jugar a instalar paquetes o ejecutar trabajos útiles? Si es una máquina de prueba, el riesgo es menor y un tiempo fuera de servicio es probablemente sin mayor consecuencia. Al revés, en una máquina de producción, el riesgo es mayor ya que la instalación de un paquete puede afectar otros vía las dependencias. Por ejemplo, 2 paquetes que dependen de openSSL pueden requerir 2 versiones distintas e incompatibles (el caso se dió hace poco). Resolver esta situación es complejo y puede significar una marcha atrás mayor.

En general, el riesgo no vale la pena para los principiantes ya que puede dejar una impresión negativa de un sistema, cuya fama viene justamente de su estabilidad.

Cómo y cuando actualizar

Básicamente, hay 2 métodos generales: 1) bajar el árbol completo ports.tgz y reemplazar el directorio actual o 2) crear un repositorio CVS local. La primera opción es rápida y predecible: se puede estimar el tiempo de descarga del archivo y de instalación. La opción CVS suele ocupar más espacio en el disco y es relativamente más lenta ya que los archivos se editan en tiempo real.

La pregunta "cuándo" es más subjetiva. Si se descubrió y corrigió una falla de seguridad en un servidor conectado a Internet, es seguramente útil instalar la actualización. Si hay una mejora sensible o nuevas funcionalidades (por ejemplo, un compilador soporta ahora un nuevo procesador que ocupo en mi trabajo actual), también tiene sentido. Si KDE migró de 3.5.2 a 3.5.3, vale mejor evaluar si hubo cualquier cambio que justifique la actualización (la respuesta es probablemente no en la mayoría de los casos y es más razonable esperar que la 3.5.3 sea integrada a -RELEASE).

Auditoria de seguridad con portaudit

Finalmente,los aspectos de auditoría. Como mencionado antes, no todos los paquetes son sujetos a auditoría. Para tener una idea del alcance, instale sysutils/portaudit y revise /var/db/portaudit/auditfile.tbz - es un archivo texto comprimido.

Este paquete instala un job recurrente que investiga los paquetes instalados. El job corre durante la noche y, por lo tanto, requiere que el PC esté encendido. Un servidor seguirá operando probablemente 24h al día pero una estación de trabajo puede ser bajada después de los horarios de trabajo. Pero nunca olvide la regla de oro: para que un sistema sea seguro, ¡instale y habilite solamente lo necesario!

Y ahora, ¡PRUEBE ESTE MARAVILLOSO SISTEMA! Les aseguro que no se van a arrepentir.

Herramientas personales