Koha 7 min de lectura 8 de julio de 2026

Guía maestra: instalación y restauración de Koha en un servidor Webmin/Virtualmin

Una guía completa para integrar Koha en un servidor Webmin/Virtualmin, incluyendo la solución definitiva para la renovación automática de certificados SSL de Let's Encrypt.

Solución en "Dos Clics" (TL;DR)

Guía completa de instalación y restauración de una instancia Koha 22.05 (instancia dosclic, dominio catalogo.dosclic.edu.ni) sobre un servidor gestionado por Webmin/Virtualmin. Cubre respaldos previos, restauración de base de datos y configuración, integración del panel administrativo (Intranet 8080) con SSL, y la solución para la renovación automática del certificado Let's Encrypt mediante ACME en aplicaciones que no exponen un directorio público (caso Koha en Perl/CGI). En reto más complejo: hacer que el 'well-known' funcione sin que Koha intercepte las peticiones.

Recientemente me enfrenté al desafío de instalar y restaurar una instancia de Koha (versión 22.05) en un servidor Ubuntu gestionado con Webmin y Virtualmin. El objetivo era migrar la instancia dosclic, con su base de datos y configuración, al dominio catalogo.dosclic.edu.ni. La instalación base de Koha es sencilla, pero el verdadero reto surgió al intentar que una aplicación Perl/CGI como Koha conviviera con un panel de control como Virtualmin, que está optimizado para un ecosistema PHP con un DocumentRoot tradicional. El punto más crítico fue lograr que la renovación automática de certificados SSL de Let's Encrypt funcionara, ya que Koha interceptaba las peticiones de validación ACME.

1. Contexto técnico y preparación

Antes de iniciar cualquier cambio, me aseguré de tener los respaldos completos de la instancia original. El entorno de trabajo era un servidor Ubuntu 22.04 con un stack bastante estándar para Koha, pero con la capa de gestión de Webmin/Virtualmin.

El stack técnico del servidor de destino era el siguiente:

  • OS: Ubuntu 22.04.5 LTS
  • Apache: 2.4.52
  • MariaDB: 10.6.23
  • Perl: 5.34.0
  • Koha: 22.05.22 (koha-common)
  • Webmin: 2.621 + Virtualmin 7.0.24

Los respaldos con los que contaba eran un dump de la base de datos y un archivo tar con la configuración de Koha, Zebra y Apache.

2. Instalación y restauración de Koha

El primer paso fue instalar Koha desde su repositorio oficial para la versión 22.05.

Terminal (SSH)
echo "deb http://debian.koha-community.org/koha 22.05 main" | sudo tee /etc/apt/sources.list.d/koha.list
wget -O- http://debian.koha-community.org/koha/gpg.asc | sudo apt-key add -
sudo apt update
sudo apt install koha-common koha-l10n mariadb-server -y

Luego, configuré los parámetros básicos del sitio en /etc/koha/koha-sites.conf y creé la instancia con el nombre dosclic.

Terminal (SSH)
sudo koha-create --create-db dosclic

Este comando crea la base de datos koha_dosclic, el usuario correspondiente y la estructura de directorios y configuración inicial.

Restauración de la base de datos y la configuración

Con la instancia creada, detuve los servicios de Koha para proceder con la restauración.

Terminal (SSH)
sudo koha-zebra --stop dosclic
sudo koha-indexer --stop dosclic
sudo koha-worker --stop dosclic
sudo koha-plack --stop dosclic

Importé el dump de la base de datos y descomprimí los archivos de configuración y los índices de Zebra en sus ubicaciones correspondientes, ajustando los permisos.

Terminal (SSH)
zcat /path/dosclic-2026-03-20.sql.gz | sudo koha-mysql dosclic
sudo tar -xzf /path/dosclic-2026-03-20.tar.gz -C / etc/koha/sites/dosclic/ etc/apache2/sites-available/dosclic.conf
sudo chown -R dosclic-koha:dosclic-koha /var/lib/koha/dosclic/
sudo chown -R dosclic-koha:dosclic-koha /etc/koha/sites/dosclic/

Un detalle importante: Virtualmin ya había creado una base de datos llamada catalogo para el dominio. Decidí usar esa base en lugar de la que creó Koha (koha_dosclic). Para ello, modifiqué el archivo koha-conf.xml para que apuntara a la base de datos, usuario y contraseña correctos.

Actualización del esquema de la base de datos

Tras restaurar los datos, el esquema de la base de datos no coincidía con la versión del código de Koha (el backup era de la versión 22.05.14 y el código instalado era 22.05.22). Esto provocaba que el sitio se mostrara en modo mantenimiento. La solución fue ejecutar el comando de actualización de esquema:

Terminal (SSH)
sudo koha-upgrade-schema dosclic

El proceso actualizó el esquema exitosamente y el catálogo público (OPAC) volvió a estar en línea, respondiendo con un 200 OK.

3. El reto principal: integrar Koha con Virtualmin

Aquí es donde comenzaron los verdaderos problemas. El VirtualHost que Virtualmin genera para un dominio está pensado para aplicaciones PHP. Utiliza directivas como SuexecUserGroup y asume un DocumentRoot. Koha, al ser una aplicación Perl/CGI, no funciona de esa manera; gestiona sus rutas con ScriptAlias y directivas de reescritura propias. La colisión era inevitable.

Error detectado: El log de Apache mostraba un error de permisos al intentar ejecutar los scripts de Koha, causado por la directiva SuexecUserGroup de Virtualmin.
AH01215: (13)Permission denied: exec of '/usr/lib/apache2/suexec' failed: /usr/share/koha/opac/cgi-bin/opac/opac-main.pl

La solución fue editar manualmente el VirtualHost generado por Virtualmin y eliminar las directivas conflictivas (SuexecUserGroup y DocumentRoot). En su lugar, incluí los archivos de configuración compartidos de Koha y asigné el usuario con AssignUserID.

Apache VirtualHost
Include /etc/koha/apache-shared.conf
Include /etc/koha/apache-shared-opac.conf
SetEnv KOHA_CONF "/etc/koha/sites/dosclic/koha-conf.xml"
AssignUserID dosclic-koha dosclic-koha

Mantuve las configuraciones de SSL, logs y alias de Virtualmin, logrando una configuración híbrida que funcionaba para ambos sistemas.

4. Habilitando la Intranet en el puerto 8080 con SSL

El siguiente requisito era que el panel de administración de Koha (la Intranet) estuviera accesible en https://catalogo.dosclic.edu.ni:8080. Para ello, añadí Listen 8080 a la configuración de Apache y creé un nuevo VirtualHost para ese puerto.

Este nuevo VirtualHost incluía la configuración específica de la intranet de Koha y, lo más importante, las directivas SSL para usar los mismos certificados que Virtualmin gestionaba para el dominio principal.

Apache VirtualHost (*:8080)
<VirtualHost *:8080>
    ServerName catalogo.dosclic.edu.ni
    SSLEngine on
    SSLCertificateFile /etc/ssl/virtualmin/[Virtualmin_Server_ID]/ssl.cert
    SSLCertificateKeyFile /etc/ssl/virtualmin/[Virtualmin_Server_ID]/ssl.key
    SSLCACertificateFile /etc/ssl/virtualmin/[Virtualmin_Server_ID]/ssl.ca

    Include /etc/koha/apache-shared.conf
    Include /etc/koha/apache-shared-intranet.conf
    SetEnv KOHA_CONF "/etc/koha/sites/dosclic/koha-conf.xml"
    AssignUserID dosclic-koha dosclic-koha
</VirtualHost>

Tras recargar Apache, la intranet respondió correctamente en el puerto 8080 con una conexión segura.

5. La batalla por la renovación automática de SSL

Este fue el problema más complejo. Virtualmin utiliza Let's Encrypt para gestionar los certificados, lo que requiere validar la propiedad del dominio colocando un archivo en la ruta /.well-known/acme-challenge/. El problema es que Koha, por su diseño, intercepta todas las peticiones que no reconoce y las maneja internamente, devolviendo su propia página de error 403. Esto impedía que el servidor de Let's Encrypt pudiera leer el archivo de validación.

Primer intento fallido

Mi primera idea fue usar una directiva Alias en Apache para mapear la ruta /.well-known/acme-challenge/ al directorio public_html que Virtualmin crea por defecto.

Apache VirtualHost (Intento fallido)
Alias /.well-known/acme-challenge/ /home/catalogo/public_html/.well-known/acme-challenge/
<Directory /home/catalogo/public_html/.well-known/acme-challenge/>
    Require all granted
</Directory>

No funcionó. A pesar de que los permisos del sistema de archivos eran correctos, Koha seguía capturando la petición antes de que el Alias pudiera servir el archivo.

La solución definitiva

La solución requirió una combinación de tres directivas de Apache, colocadas estratégicamente antes de los Include de Koha en el VirtualHost. La clave fue crear un directorio para el challenge dentro de la propia estructura de datos de Koha y darle los permisos adecuados.

Terminal (SSH)
mkdir -p /var/lib/koha/dosclic/acme-challenge
chown -R dosclic-koha:dosclic-koha /var/lib/koha/dosclic/acme-challenge

Luego, en el VirtualHost, añadí estas reglas:

Apache VirtualHost (Solución final)
# Estas reglas deben ir ANTES de los Includes de Koha
ProxyPass /.well-known !
RewriteRule ^/\.well-known - [L]

Alias /.well-known/acme-challenge/ /var/lib/koha/dosclic/acme-challenge/
<Directory /var/lib/koha/dosclic/acme-challenge/>
    Options None
    AllowOverride None
    Require all granted
</Directory>
Consejo Práctico: La directiva RewriteRule ^/\.well-known - [L] le dice a Apache que deje de procesar reglas de reescritura para esta ruta, mientras que ProxyPass /.well-known ! evita que la petición sea pasada a la aplicación backend de Koha. Esto permite que el Alias funcione sin interferencias.

Una prueba rápida con curl confirmó que el servidor ahora servía correctamente los archivos desde el directorio de validación, despejando el camino para la renovación automática de los certificados.

6. Pasos finales y verificación

Con los problemas principales resueltos, quedaban algunos ajustes finales.

Instalación del idioma español

El comando estándar para instalar traducciones fallaba. Tuve que invocar el script de Perl directamente, especificando las variables de entorno necesarias para que encontrara la configuración y las librerías de Koha.

Terminal (SSH)
PERL5LIB=/usr/share/koha/lib KOHA_CONF=/etc/koha/sites/dosclic/koha-conf.xml \
  /usr/share/koha/misc/translator/translate install es-ES

Tras esto, el idioma español apareció como disponible en el panel de administración y pude activarlo.

Reconstrucción de índices y arranque de servicios

Finalmente, reconstruí los índices de búsqueda de Zebra y arranqué todos los servicios de la instancia para ponerla en producción.

Terminal (SSH)
sudo koha-rebuild-zebra -f dosclic
sudo koha-zebra --start dosclic
sudo koha-indexer --start dosclic
sudo koha-worker --start dosclic
sudo koha-plack --start dosclic

Una verificación final confirmó que todos los endpoints funcionaban como se esperaba: el OPAC público redirigía a HTTPS, la intranet era accesible en el puerto 8080 con SSL y la ruta de validación ACME respondía correctamente.

La historia detrás de la nota

La lección más importante de este proceso fue entender que no se puede tratar a todas las aplicaciones web por igual. La clave para desplegar Koha en un servidor gestionado por Webmin/Virtualmin es aceptar y adaptar las diferencias entre el modelo Perl/CGI de la aplicación y el modelo PHP/DocumentRoot que asume el panel. En lugar de luchar contra las herramientas, la solución fue crear una configuración híbrida que aprovechara lo mejor de ambos mundos.

Sigue explorando