FreeBSD: Pakete selber bauen

Ich betreibe jetzt seit einigen Jahren FreeBSD Server für meine privaten Dienste und bin bisher immer gut mit den normalen Paketen gefahren.

Jetzt gab es diese Woche ein kritisches NodeJS Update das eine mögliche Remote Code Execution abgeschaltet hat. Wenn so etwas auftritt dann gibt es immer die Alternative “warten oder selbst kompilieren”

Irgendwie dauert mit das allerdings jetzt zu lange und ich habe Zeit das mal selbst zu bewerkstelligen. Leider ist auch in der Definition der Ports noch nicht die neue Version enthalten so das ich auch noch diese Definition “patchen” musste.

Der folgende Ansatz basiert im Wesentliche auf diesem sehr schönen Beitrag plus einige Hinweise von dem Autor in einer privaten Konversation.

Die Reihenfolge ist:

  • Erstellen eines “Wegwerfjails” für den Buildprozess
  • Patchen der Port Definition
  • Bauen des Installationspaketes
  • Erstellen einer Paketquelle im Ziel Jail und upgraden.

Zuerst ein Jail erstellen das der Release Version der Zielumgebung entspricht

bastille bootstrap 14.4-RELEASE
bastille create nodejs22-14 14.4-RELEASE 10.1.0.99/24 bastille0
bastille config nodejs22-14 set boot off

Außerdem ist sicherzustellen das aus dem Jail heraus die Firewall den Zugriff auf die diversen Software Seiten zulässt / ermöglicht.

Dann sicherstellen das die Pakete im “Bau-Jail” aus der gleichen Quelle kommen wie das Zieljail und Pakete aktualisieren. Ich verwende latest und default ist quartely

bastille console nodejs22-14
vi /etc/pkg/FreeBSD.conf 

pkg update
pkg upgrade

Installation von git und download der Quelldefinition

env ASSUME_ALWAYS_YES=yes pkg bootstrap -f
pkg install -y git-tiny
git clone https://git.FreeBSD.org/ports.git /usr/ports

Wenn wir nicht das aktuelle brotli Paket haben scheitert gleich die nodejs Installation

cd /usr/ports/archivers/brotli/
make reinstall

Zum jetzigen Zeitpunkt hat die Portkonfiguration allerdings nicht auf die neueste Version gezeigt. Wie ich heute gelernt habe scheint es manchmal auszureichen hier einfach die Version in der Quelle einzutragen.

cd /usr/ports/www/node22/
vi  Makefile.version
  NODEJS_PORTVERSION=	22.23.4

und die Version auf 0 zu setzen

vi Makefile
 PORTREVISION=  0

Damit wir nicht alle Quellen bauen müssen gibt es in dem verlinkten Artikel ein Script, das zuerst prüft welche Pakete fehlen und die werden normal aus den Paketquellen installiert. Der Rest wird gebaut.

vi build-nodejs22.sh
-----
#!/bin/sh
set -e
export BATCH=yes
P=/usr/ports

for o in www/node22; do
    echo "=== $o"
    missing=$(make -C $P/$o missing)
    deps=$(printf '%s\n' "$missing" || true)
    if [ -n "$deps" ]; then
        pkg install -y $deps
    fi
    make -C $P/$o clean package install clean
done
----
 
chmod +x build-nodejs22.sh
./build-nodejs22.sh

Am Ende habe ich dann 2 Pakete

ls /usr/ports/packages/All/
brotli-1.2.1,1.pkg	node22-22.23.4.pkg

die wir installieren könnten. Es soll jedoch besser sein diese in ein eigenes Repository zu packen und dieses dann als Quelle im Jail einzutragen. Auf dem Host also

mkdir /root/node22-23-4
cp /usr/local/bastille/jails/nodejs22-14/root/usr/ports/packages/All/* /root/node22-23-4/
pkg repo /root/node22-23-4/
  Creating repository in /root/node22-23-4/: 100%
  Packing files for repository: 100%

jail=mstdn2

mkdir -p /usr/local/bastille/jails/$jail/root/var/tmp/node22-local /usr/local/bastille/jails/$jail/root/usr/local/etc/pkg/repos
cp /root/node22-23-4/* /usr/local/bastille/jails/$jail/root/var/tmp/node22-local

cat > /usr/local/bastille/jails/$jail/root/usr/local/etc/pkg/repos/node22-local.conf <'EOF'
node22-local: {
  url: "file:///var/tmp/node22-local",
  signature_type: "none",
  priority: 100,
  enabled: yes
}
EOF


 bastille pkg $jail update
 bastille pkg $jail upgrade -g node22

Wenn ich dann in das Jail gehe und die Version prüfe

 bastille console $jail
 node -v
  v22.23.4

Sieht es gut aus :-)

Sobald dies neue Version in den Paketquellen ist werde ich versuchen wird auf diese zurück zu schwenken.

Bei Nodejs24 hat das übrigens nicht so gut geklappt. Hier gab es Patches die auf die neueste Version aus den Herstellerquellen nicht angewendet werden konnten. Aber da zum Zeitpunkt des Versuches schon die original Updates am Horizont zu sehen waren habe ich das nicht weiter verfolgt.

Auch wenn die richtigen Updates bald kommen sollen hat sich die Übung gelohnt. Wer weiß wann ich das noch mal brauchen kann.