Desde hace tiempo tenia en mente la idea de hacer un post sobre cómo descargar los repositorios de Debian y derivados con apt-mirror pero por cuestiones ajenas a mi voluntad no había tenido el tiempo para sentarme a redactar. Ya se que algunos dirán “bueno, ya se ha publicado sobre apt-mirror en humanos” y tendrán toda la razón pero, esta publicación data de 5 años atrás por lo que me tomé el atrevimiento de hacer una especie de actualización pero desde mi experiencia personal en el uso de apt-mirror.

debian-mirror

Para los que no conocen esta herramienta, apt-mirror es una aplicación que permite realizar una réplica exacta de un repositorio de internet para tener como resultado un repositorio local.

Instalación

La instalación es muy sencilla, solo tenemos que ejecutar:

sudo apt-get install apt-mirror

Configuración

La configuración del apt-mirror está localizada en el fichero /etc/apt/mirror.list.

Entre las opciones más importantes encontramos:

  • mirror_path: la ruta donde se alojará el repositorio.
  • nthreads: la cantidad de hilos de descargas. Por defecto su valor es 20 pero para los repos de la UCI recomiendo usar 10 porque es el límite de conexiones permitidas desde un ip hacia el servidor web que publica los repos.

Otras opciones que uso a diario son:

  • cleanscript: script de limpieza que elimina paquetes con versiones anteriores.
  • postmirror_script: script postmirror que permite ejecutar tareas después de descargar el repositorio.
  • run_postmirror: ejecuta el script postmirror.
  • _ntilde: permite la descarga de paquetes o urls con tilde.
  • _autoclean: ejecuta automáticamente el script de limpieza una vez descargado el respositorio.

A modo de cultura general:

  • base_path: esta ruta es la ruta base de todo el repositorio incluyendo los archivos temporales y temporales de índices. Si se establece esta y no se establecen los valores de las otras rutas, apt-mirror descargará hacia este directorio el contenido de la carpeta mirror, skel y var.
  • skel_path: donde se guardan con carácter temporal los índices del repositorios. Dígase ficheros como los Packages y los Translations.
  • var_path: guarda otros temporales como los archivos que están en descarga, logs etc.
  • defaultarch: establece la arquitectura por defecto. Por defecto su valor es la arquitectura del sistema operativo que esté usando pero se pueden descargar paquetes de otras arquitecturas si se le especifica. Si usas 64 bits y quieres los de 32 tendrias que poner algo como “deb-i386 http://debian.uci.cu/debian testing main contrib non-free” entre los repositorios a descargar.

Luego de las variables de configuración se colocan los repositorios a los que se les va a hacer mirror utilizando el mismo estilo que se emplea en el /etc/apt/sources.list. Seguido de las intrucciones clean, para limpiar el repo de archivos innecesarios.

Para que  más menos se guíen, mi fichero de configuración luce así:

############# config ##################
set mirror_path  /home/mirror
set cleanscript $var_path/clean.sh
set postmirror_script $mirror_path/postmirror.sh
set run_postmirror 1
set nthreads     10
set _tilde 0
set _autoclean 1
#
############# end config ##############
deb http://debian.uci.cu/debian testing main contrib non-free
deb http://debian.uci.cu/security testing/updates main contrib non-free
deb http://debian.uci.cu/debian-multimedia/ testing main non-free

clean http://debian.uci.cu/debian
clean http://debian.uci.cu/security
clean http://debian.uci.cu/debian-multimedia

También les comparto mi script postmirror.sh:

#!/bin/sh
set -e
DEBIAN_PATH=/home/mirror/debian.uci.cu
REPOSITORIES="$DEBIAN_PATH"
for REPOSITORY in $REPOSITORIES; do
    find $REPOSITORY -type f -name "Packages.*" ! -name "*.gz" -exec rm -f {} \;
    find $REPOSITORY -type f -name "Translation-*" ! -name "*-es*" ! -name "*-en*" -exec rm -f {} \;
done

Describiendolo por arribita les diria que en mi postmirror.sh elimino los ficheros de traducción de idiomas que no me interesan y además me quedo solamente con los ficheros Packages y Packages.gz (esto último solo lo recomiendo para Debian Testing, en las demás versiones de Debian y derivados recomiendo conservarlos todos si no les molestan).

Uso

El uso también es muy simple. Una vez configurado basta con ejecutar:

sudo apt-mirror # y esperar sentado en una silla muy cómoda a que termine.

Una vez descargado el repositorio, ya podemos usarlo simplemente editando nuestro /etc/apt/sources.list que debe quedarnos más menos así:

deb file:/home/mirror/debian.uci.cu/debian/ testing main contrib non-free 
deb file:/home/mirror/debian.uci.cu/security/ testing/updates main contrib non-free 
deb file:/home/mirror/debian.uci.cu/debian-multimedia/ testing main non-free

Actualizaciones automáticas

Hasta este punto del tutorial ya tenemos un repositorio funcional pero sin la capacidad de actualizarse automáticamente, lo que nos obligaría a ejecutar manualmente el apt-mirror cada vez que queramos actualizarlo. Por suerte esto es remediable.

Cuando instalamos apt-mirror por defecto se nos crea una tarea en el cron (por defecto [valga la redundancia] deshabilitada) /etc/cron.d/apt-mirror con este contenido:

#      
#0 4    * * *   apt-mirror  /usr/bin/apt-mirror > /var/spool/apt-mirror/var/cron.log

Lo anterior nos dice que el apt-mirror se ejecutará (si le quitamos el símbolo de # inicial) todos los días a las 4:00 AM. Pueden cambiarle la hora de la programación para la que más les convenga. Yo en lo personal prefiero que se ejecute cada una hora. Esto lo consigo creando un script de bash en /etc/cron.hourly/sysupdate con el siguiente contenido:

#!/bin/sh
# Compruebo que el repositorio esté accesible por la web.
$(which wget) --spider -q debian.uci.cu || exit 0

# Voy a usar aptitude aunque no tenga poderes de Super Vaca. Sea cual sea la 
# que usen ustedes, primero asegúrense de tenerla instalada.
APTBIN=$(which aptitude)
APTMIRROR=$(which apt-mirror)

# Estas opciones son específicas para aptitude. Los que usan apt-get o apt tienen 
# que sustituirlas por --auto-remove --allow-unauthenticated --force-yes -y -q
APTOPTS="--allow-untrusted -y -q"
APTLOG=/var/log/sysupdate.log

# Las dos líneas a continuación solo las utilizo cuando tengo el típico problema
# de "la suma de hash no coincide". Corro el script manualmente y luego las
# comento otra vez. Si no resolvemos es que no es problema de nuestro 
# repositorio local.

# find /home/mirror/ -type d -name dists -exec rm -rf {} \;
# rm -rf /var/spool/apt-mirror/skel/*

# Actualizamos nuestro repositorio
$APTMIRROR > $APTLOG || exit 0

# Reconstruimos nuestra caché de paquetes
$APTBIN update >> $APTLOG || exit 0

# Actualizamos nuestro sistema operativo. Acá utilizo safe-upgrade porque uso 
# Debian Testing. Con versiones estables podemos usar upgrade directamente.
# OJO: apt ni apt-get tienen la opción safe-upgrade.
$APTBIN $APTOPTS safe-upgrade >> $APTLOG
RETCODE="$?"
# Limpiamos un poco la casa
PKGS=$(dpkg -l | grep ^rc | awk '{print $2}')
$APTBIN -y -q purge $PKGS >> $APTLOG
$APTBIN clean >> $APTLOG

echo "RETCODE: ${RETCODE}" >> $APTLOG
echo "DATE: $(date)" >> $APTLOG

# PD: No es obligatorio usar el script y menos con todos estos 
# comentarios incluidos.

Publicando por HTTP

Es probable que queramos publicar nuestros repositorios descargados por la web si somos una institución y queremos brindar este servicio o si queremos tirarle un cabo a un amigo que esté en aprietos y el mirror de internet o de la institución no responden. Para ello lo más común es instalarnos un Apache pero podría ser un Nginx o cualquier otro:

sudo aptitude install apache2

No voy a abordar toda una superteoría acerca de este servidor web. Tan solo nos creamos un nuevo virtual host (el mío lo ubiqué en /etc/apache2/sites-available/debian.conf) con un contenido similar a este:


    DocumentRoot /home/mirror/debian.uci.cu

    
            Options Indexes FollowSymLinks
            AllowOverride None
            Require all granted
    

    ErrorLog ${APACHE_LOG_DIR}/debian.error.log
    CustomLog ${APACHE_LOG_DIR}/debian.access.log combined


Lo habilitamos con el comando a2ensite debian.conf o de la forma que les sea más cómoda.

Como además de amables y buenas personas nos preocupamos por nuestra seguridad. Nos aseguraremos de no mostrar cierta información de nuestro servidor web.  Para ello, en el caso de Apache, editamos un fichero que está localizado en /etc/apache2/conf-available/security.conf y lo dejamos más menos así:

ServerTokens Prod
ServerSignature Off
TraceEnable Off
Header set X-Content-Type-Options: "nosniff"
Header set X-Frame-Options: "sameorigin"

Nota: Para que la anterior configuración funcione a la perfección debemos habilitar el módulo headers con el comando a2enmod headers.

Reiniciamos el apache:

sudo service apache2 restart

Nginx (altamente recomendado)

Si prefieres Nginx, primero lo instalamos si no lo hemos hecho:

sudo aptitude install nginx

Seguidamente creamos el virtual host. Yo lo creo en /etc/nginx/sites-available/debian.conf:

server {

    listen 80 default_server;
    root /home/mirror/debian.uci.cu;
    server_name _;
    server_tokens off;
    
    location / {
        autoindex on;
    }

    location ~ /\.ht {
        deny all;
    }
}

Luego habilitamos el virtual host ejecutando:

sudo ln -s /etc/nginx/sites-{available,enabled}/debian.conf

Hecho esto reiniciamos el Nginx para ver los cambios:

sudo service nginx restart

Ya sea con Apache, con Nginx(RECOMENDADO) o cualquier otro servidor web. Si nuestra PC o servidor es todo un búnker abrimos en el firewall el puerto 80. Como uso iptables al strike, lo hago así:

sudo iptables -A INPUT -m state --state NEW --dport 80 -j ACCEPT

Y todo listo. Ya tenemos todo un repositorio de Debian, Ubuntu o cualquier otro que se le parezca. Espero que les haya sido de utilidad. En caso de que no les haya servido de nada, por favor, disimulen 🙂