Instalar paquetes en servidor sin internet mediante repositorio local
En este artículo te hablaré de una forma sencilla de resolver la actualización de paquetes de terceros en una máquina virtual Linux que no tenga salida a Internet por restricciones de seguridad, pero al cual tienes acceso para subir archivos por ssh o ftp, es decir, un servidor air-gapped o aislado (isolated-server) y del cual quieras instalar las aplicaciones por rpm.
Aunque existen otras soluciones como compilar las aplicaciones para generar los binarios que requieres, bajarlos como tarball y solo exportar en la variable path o crear un repositorio espejo en la red local, una de las formas mas sencillas de instalar y actualizar estas aplicaciones o utilerías que quieres tener en tu servidor o máquina aislada de Internet es instalar por medio de un repositorio local en el filesystem con los RPM necesarios.
La solución planteada se reduce a crear un repositorio local de paquetes rpm con solo los que requieres instalar o actualizar, para ello necesitas descargar en alguna máquina con la misma versión de sistema operativo los paquetes y luego generar la metadata del repositorio y pasar el paquete a la máquina sin salida a Internet donde ya podrás instalar los paquetes rpm creando un enlace al repositorio local.
Los requisitos que vas a necesitar son:
- El servidor offline o sin conexión a internet donde quieres instalar los paquetes.
- Un servidor con salida a Internet donde vas a descargar los paquetes rpm que quieres instalar con la misma versión de sistema operativo.
- El usuario root de ambos servidores.
- Conexión por ssh o ftp a ambos servidores.
Ahora vamos a plantear la situación hipotética:
Tienes un servidor con Red Hat 9 en el que quieres instalar paquetes de php 8.5 que no existen en los repositorios oficiales del sistema operativo, por lo que requieres instalar paquetes de repositorios epel y remi, pero no cuentas con salida a Internet desde el servidor, ya que es un servidor con reglas de seguridad.
Por tanto, para resolverlo ejecutas los siguientes pasos:
1. Instalar repositorios: Debes instalar los repositorios de epel, remi-modular y rpmfusion y configurar el módulo para poder obtener los paquetes de php-8.5 e instalaremos algunas utilerías de compresión y yum-utils que serán necesarios para nuestro objetivo, lo cual se puede resumir en los siguientes comandos:
rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
rpm --import https://rpms.remirepo.net/enterprise/9/RPM-GPG-KEY-remi
dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm
rpm --import https://download1.rpmfusion.org/free/el/RPM-GPG-KEY-rpmfusion-free-el-9
dnf install -y https://download1.rpmfusion.org/free/el/rpmfusion-free-release-9.noarch.rpm
dnf module enable -y php:remi-8.5
dnf install -y yum-utils bzip2 zip nodejs
2. Hacer dnf download sobre un directorio: con esto logramos descargar los paquetes rpm necesarios para la instalación, en este caso como ejemplo usaremos el directorio /opt con algunos paquetes de php y módulos:
dnf download --resolve --alldeps --destdir=/opt/rpmrepo php-cli php-dom php-mbstring php-intl php-pdo php-mysqlnd php-zip php-sodium php-posix php-dbg
3. Crear el repositorio local mediante el comando createrepo_c, este paquete debe estar instalado en la VM con:
dnf install createrepo_c
Si no puedes por algún motivo instalarlo desde los repositorios de Red Hat puedes descargar el de centos-stream o almalinux
y luego ejecutar los comandos:
rpm -ivh createrepo_c-libs-0.20.1-4.el9.x86_64.rpm
rpm -ivh createrepo_c-0.20.1-4.el9.x86_64.rpm
4. Sincronizar todo el repositorio remi-modular mediante reposync: Un problema al que nos enfrentamos al solo haber descargado una parte de los rpm es que php 8.5 requiere el uso de módulos, y para saber que paquetes son dependencia de la versión exacta que queremos instalar se requiere la metadata, por lo tanto, vamos a bajar todo el repositorio y solo extraer su metadata para insertarla en nuestro repositorio, así lo haremos más ligero y solo con los rpms necesarios, para ello ejecutamos el comando:
reposync --repo=remi-modular --download-path=/opt/remi-modular --download-metadata
5. Obtener module.yml: dado que el archivo esta en un comprimido ejecutamos el siguiente comando para extraerlo:
MODULE=$(find remi-modular -name '*modules.yaml.bz2') && bzip2 -dc ${MODULE} > /opt/modules.yaml
6. Agregar module.yml al directorio del punto 2 mediante modifyrepo_c: lo logramos con el comando:
modifyrepo_c /opt/modules.yaml /opt/rpmrepo/repodata/
7. Comprimir el directorio del punto 2: finalmente ejecutamos:
zip -r rpmrepo.zip rpmrepo/
8. Subir a la máquina sin conexión a Internet: el paquete lo descomprimimos en alguna ruta, por ejemplo /tmp/rpmrepo
unzip rpmrepo.zip -d /tmp
9. Crear archivo de repositorio de filesystem local: En la máquina sin conexión a Internet, para usarlo debemos crear un archivo que apunte a este repositorio, lo podemos hacer mediante el siguiente comando:
cat > /etc/yum.repos.d/localfilesystem.repo <<EOF
[localfilesystem]
name=Repositorio Local en filesystem
baseurl=file:///tmp/rpmrepo
enabled=1
gpgcheck=0
priority=1
EOF
10. Y ya podemos hacer la instalación de los paquetes que bajamos en el punto 2 mediante:
dnf install php-cli php-dom php-mbstring php-intl php-pdo php-mysqlnd php-zip php-sodium php-posix php-dbg
Al final puedes borrar los rpm, pero no olvides desactivar el repositorio para que no de errores:
dnf config-manager --disable localfilesystem
Si quieres más adelante actualizar los paquetes solo debes volver a ejecutar los pasos y al final en lugar de dnf install en la VM desatendida u offline, habilitas el repositorio y haces update mediante:
dnf config-manager --enable localfilesystem
dnf update
Te dejo un Dockerfile el cual el cual puedes ejecutar de la siguiente forma:
docker build --no-cache -t packreporhel9php8_5 --output ./ .
y te va a dejar el archivo rpmrepo.zip, lo puedes ajustar a tu gusto con los paquetes que requieras y también lo puedes ejecutar con podman.


