Configuración de Nginx y PHP‑FPM para Geeklog

Autor: Joel Barrios Dueñas
Correo electrónico: darkshram en gmail punto com
Sitio de Red: https://www.alcancelibre.org

Licencia Creative Commons
© 1999‑2026 Joel Barrios Dueñas. Este manual se distribuye bajo la licencia Creative Commons Reconocimiento‑NoComercial‑CompartirIgual 4.0 Internacional (CC BY‑NC‑SA 4.0). Usted es libre de compartir y adaptar el material bajo los siguientes términos: debe dar crédito al autor, no puede utilizarlo para fines comerciales y debe compartir las obras derivadas bajo la misma licencia. La licencia completa está disponible en https://creativecommons.org/licenses/by‑nc‑sa/4.0/legalcode.es.

Introducción

Geeklog es un sistema de gestión de contenido (CMS) escrito en PHP y MySQL/MariaDB. Constituye una excelente alternativa para bitácoras (blogs), pues es ligero, muy seguro y dispone de funcionalidad para establecer permisos de acceso y edición por usuario o grupo. Su colección de complementos es pequeña pero suficiente para la mayoría de las necesidades.

La principal ventaja de Geeklog frente a alternativas como Drupal, Joomla o Wordpress radica en el escaso interés que muestra la delincuencia informática por realizar ataques contra él. En otras palabras, su baja popularidad se convierte en una ventaja de seguridad. Sus desventajas son la relativamente reducida lista de complementos y la escasez de plantillas disponibles. Si requiere una plantilla, se sugiere partir de la plantilla modern_curve incluida con Geeklog y adaptarla a sus necesidades.

La interfaz de programación de aplicaciones (API) para temas de Geeklog cambia con cada nuevo lanzamiento. Los temas para Geeklog 2.0 o 2.1 requieren algunas pocas adaptaciones, mientras que los temas para versiones anteriores a 2.0 necesitan muchas modificaciones para funcionar con la versión actual 2.2.

Ubicación segura de los archivos del sistema

  1. Descargue y descomprima la versión más reciente de Geeklog.
  2. Genere un usuario regular sin privilegios, como se recomienda en el manual Configuración de Nginx.
  3. Lea la documentación que incluye Geeklog para el proceso de instalación.
  4. Lea este documento en su totalidad.

Un aspecto de seguridad crítica es la correcta ubicación del directorio system/. Este directorio jamás debe residir dentro de public_html o de cualquier ruta accesible directamente desde la web, pues contiene bibliotecas y configuraciones sensibles.

Estructura recomendada:

En el archivo siteconfig.php, las rutas se configurarían de la siguiente manera:

$_CONF['path'] = '/home/usuario/private/';
$_CONF['path_system'] = $_CONF['path'] . 'system/';

Configuración de SELinux para RHEL y derivados

En distribuciones como AlmaLinux, Rocky Linux o Red Hat Enterprise Linux, que utilizan SELinux por defecto, es imprescindible asegurar los contextos de seguridad para los directorios de Geeklog. ALDOS, al ser una distribución basada enfocada en escritorio, tiene SELinux desactivado por defecto para maximizar los recursos. Si en ALDOS desea utilizar SELinux, puede iniciar el sistema con el parámetro de núcleo selinux=1.

Para configurar los contextos en distribuciones con SELinux activo, ejecute los siguientes mandatos como usuario root:

# Establecer la política para el directorio privado y sus archivos PHP
semanage fcontext -a -t httpd_sys_rw_content_t '/home/usuario/private(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/home/usuario/private/system/.*\.php'

# Aplicar los cambios de contexto
restorecon -Rv /home/usuario/private/

# Verificar los contextos
ls -Z /home/usuario/private/

Configuración del anfitrión virtual en Nginx sin URLs amigables

Si prefiere utilizar Geeklog sin las denominadas «URLs bonitas» o amigables para motores de búsqueda (SEO), la configuración del bloque location / se simplifica notablemente, pues se omiten las reglas de rewrite. En este modo, las URLs tendrán el formato tradicional con parámetros de consulta, por ejemplo https://www.ejemplo.net/article.php?story=123.

server {
    listen 80;
    server_name www.ejemplo.net;
    root /home/usuario/public_html;

    access_log /var/log/nginx/ejemplo.net-access_log main;
    error_log /var/log/nginx/ejemplo.net-error_log notice;

    charset UTF-8;

    # El valor para client_max_body_size debe ser el mismo que se estableció
    # en PHP para upload_max_filesize y post_max_size.
    client_max_body_size 128M;
    client_body_buffer_size 128M;
    server_tokens off;

    # Este archivo de inclusión tiene las opciones para compresión gzip.
    include /etc/nginx/default.d/gzip.conf;

    add_header X‑Frame‑Options "SAMEORIGIN" always;
    add_header X‑XSS‑Protection "1; mode=block" always;
    add_header X‑Content‑Type‑Options "nosniff" always;

    location / {
        index index.html index.htm index.php;
        error_page 404 /404.php;

        # Aquí se omiten las reglas rewrite para Geeklog.

        location = /favicon.ico {
            log_not_found off;
            access_log off;
        }

        location = /robots.txt {
            log_not_found off;
            access_log off;
        }

        location ~ /\.(ht|git) {
            deny all;
        }

        location /.well‑known {
            default_type "text/plain";
        }

        location ~ ^/install/(.+\.php)$ {
            allow 127.0.0.1;
            allow 192.168.100.6;
            deny all;
            # allow all;   # Descomente solo durante la instalación.
        }
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_intercept_errors on;
        include fastcgi_params;
        fastcgi_param SERVER_NAME $host;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:8500;   # Ajuste según su configuración de PHP‑FPM.

        fastcgi_param PHP_VALUE "upload_max_filesize=128M \n post_max_size=128M";
        fastcgi_index index.php;

        # Las instalaciones y actualizaciones fallarán si los siguientes valores son menores.
        fastcgi_read_timeout 600;
        proxy_buffers 16 16k;
        proxy_buffer_size 16k;
        proxy_connect_timeout 3600s;
        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

Activación y configuración de Geeklog

Una vez preparado el entorno del servidor, es necesario configurar el propio equipamiento lógico. Esta sección explica los archivos clave de Geeklog donde se definen comportamientos esenciales, como el uso de URLs amigables y las personalizaciones avanzadas.

El archivo siteconfig.php

La función de URLs amigables y otras configuraciones clave se controlan mediante el archivo siteconfig.php en el directorio private/ de Geeklog. Los valores definidos aquí prevalecen sobre cualquier cambio realizado desde la interfaz administrativa, lo que sirve como salvaguarda.

// ¿Usar URLs amigables? (1 = sí, 0 = no)
$_CONF['url_rewrite'] = 1;

// Tipo de URLs amigables (actualmente solo 'standard' es compatible)
$_CONF['url_routing'] = 'standard';

// Codificación de caracteres (recomendado utf-8 para soporte multilingüe)
$_CONF['default_charset'] = 'utf-8';

// URLs del sitio
$_CONF['site_url'] = 'https://www.ejemplo.net';
// RUTA SEGURA DE ADMINISTRACIÓN: Cambie 'panel_de_control_privado' por un valor único.
// RECUERDE: También debe renombrar el directorio físico 'public_html/admin/'.
$_CONF['site_admin_url'] = 'https://www.ejemplo.net/panel_de_control_privado';

Importante: Si establece $_CONF['url_rewrite'] = 1 pero carece de las reglas de reescritura en Nginx, los enlaces generados por Geeklog producirán errores 404. A la inversa, si tiene las reglas de reescritura en Nginx pero $_CONF['url_rewrite'] = 0, los enlaces seguirán la forma tradicional y las reglas permanecerán sin efecto.

Personalización avanzada con lib-custom.php

Para extensiones que requieren código PHP personalizado, Geeklog proporciona el archivo lib-custom.php. Su uso está reservado para administradores con conocimientos avanzados de PHP y de la API de Geeklog. Un caso de uso común es añadir variables personalizadas a las plantillas mediante la función CUSTOM_templateSetVars.

/**
 * Función para añadir variables personalizadas a las plantillas.
 * @param    string $templatename nombre de la plantilla, ej. 'header'
 * @param    object $template     objeto de la clase plantilla
 */
function CUSTOM_templateSetVars($templatename, $template)
{
    switch ($templatename) {
        case 'header':
            $template->set_var('hello_world', 'Hello, world!');
            break;

        case 'storytext':
        case 'featuredstorytext':
        case 'archivestorytext':
            $template->set_var('hello_again', 'Hello (again)!');
            break;

        default:
            // omitir realizar más acciones
            break;
    }
}

Configuración del anfitrión virtual en Nginx con URLs amigables

Esta configuración se recomienda únicamente si activó $_CONF['url_rewrite'] = 1. El orden de las reglas es crítico: las más específicas (con /print) deben preceder a las generales.

server {
    listen 80;
    server_name www.ejemplo.net;
    root /home/usuario/public_html;

    access_log /var/log/nginx/ejemplo.net-access_log main;
    error_log /var/log/nginx/ejemplo.net-error_log notice;

    charset UTF-8;
    client_max_body_size 128M;
    client_body_buffer_size 128M;
    server_tokens off;

    include /etc/nginx/default.d/gzip.conf;

    add_header X‑Frame‑Options "SAMEORIGIN" always;
    add_header X‑XSS‑Protection "1; mode=block" always;
    add_header X‑Content‑Type‑Options "nosniff" always;

    location / {
        index index.html index.htm index.php;
        error_page 404 /404.php;

        # Rewrites para Geeklog (URLs amigables)
        # 1. Reglas específicas para el modo "imprimir"
        rewrite "^/article.php/(.*)/print$" /article.php?story=$1&mode=print last;
        rewrite "^/staticpages/index.php/(.*)/print$" /staticpages/index.php?page=$1&mode=print last;

        # 2. Reglas generales para cada módulo
        rewrite "^/article.php/(.*)$" /article.php?story=$1 last;
        rewrite "^/index.php/topic/(.*)$" /index.php?topic=$1 last;
        rewrite "^/staticpages/index.php/(.*)$" /staticpages/index.php?page=$1 last;
        rewrite "^/links/index.php/(.*)$" /links/index.php?category=$1 last;
        rewrite "^/links/portal.php/link/(.*)$" /links/portal.php?what=link&item=$1 last;
        rewrite "^/directory.php/(.*)/(\d{1,})/(\d{1,})$" /directory.php?topic=$1&year=$2&month=$3 last;

        location = /favicon.ico {
            log_not_found off;
            access_log off;
        }

        location = /robots.txt {
            log_not_found off;
            access_log off;
        }

        location ~ /\.(ht|git) {
            deny all;
        }

        location /.well‑known {
            default_type "text/plain";
        }

        location ~ ^/install/(.+\.php)$ {
            allow 127.0.0.1;
            allow 192.168.100.6;
            deny all;
        }
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_intercept_errors on;
        include fastcgi_params;
        fastcgi_param SERVER_NAME $host;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:8500;
        fastcgi_param PHP_VALUE "upload_max_filesize=128M \n post_max_size=128M";
        fastcgi_index index.php;
        fastcgi_read_timeout 600;
        proxy_buffers 16 16k;
        proxy_buffer_size 16k;
        proxy_connect_timeout 3600s;
        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

Configuración para PHP‑FPM

A continuación se presenta una configuración de ejemplo para una instancia de PHP‑FPM dedicada a Geeklog. Ajuste los valores de user, group y las rutas según su entorno.

[geeklog]
user = usuario
group = usuario
listen = localhost:8500
pm = dynamic
pm.max_children = 9999
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 5

php_admin_value[upload_tmp_dir] = /home/usuario/tmp
php_admin_value[session.save_path] = /home/usuario/tmp
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /home/usuario/logs/php‑fpm‑error_log

php_value[error_reporting] = E_ALL|E_NOTICE
php_value[max_execution_time] = 7200
; Se necesitan al menos 512M para instalar o actualizar.
php_value[memory_limit] = 1024M
; Establezca su zona horaria correspondiente.
php_value[date.timezone] = America/Mexico_City
php_value[expose_php] = off

; Las instalaciones y actualizaciones fallarán si los siguientes valores son menores.
php_value[request_terminate_timeout] = 600
php_value[max_input_time] = 360
php_value[max_input_vars] = 4000

Solución de problemas frecuentes

Esta sección aborda los inconvenientes más comunes al integrar Geeklog con Nginx y PHP‑FPM, junto con los pasos para resolverlos. Si su configuración presenta un comportamiento distinto al esperado, revise los siguientes puntos antes de considerar opciones más avanzadas.

El modo «Imprimir» de páginas estáticas presenta fallas

Si la URL https://www.ejemplo.net/staticpages/index.php/manuales‑indice/print genera un error 404, verifique que la regla específica esté presente y ubicada antes de la regla general para páginas estáticas en la configuración de Nginx:

rewrite "^/staticpages/index.php/(.*)/print$" /staticpages/index.php?page=$1&mode=print last;
rewrite "^/staticpages/index.php/(.*)$" /staticpages/index.php?page=$1 last;

Nota avanzada: Si la página carga pero muestra una copia idéntica de la pagina original en lugar de mostrar una versión para imprimir (sin cabecera, pie o barras laterales), el problema probablemente reside en las plantillas del tema de Geeklog. Asegúrese de que los archivos de plantilla para impresión (como printable.thtml o print.thtml) existan y sean correctos dentro del directorio de su tema (ej: public_html/layout/modern_curve/). La restauración de estos archivos desde una instalación limpia de Geeklog suele resolver el problema.

Las URLs amigables de artículos, temas, enlaces o directorio que fallan al redireccionar

Asegúrese de que todas las reglas de rewrite necesarias estén incluidas en el bloque location / y que la directiva $_CONF['url_rewrite'] esté establecida en 1 en siteconfig.php.

Los archivos PHP se descargan en lugar de ejecutarse

Verifique que el bloque location ~ \.php$ esté presente, que fastcgi_pass apunte al zócalo (socket) o puerto correcto de PHP‑FPM y que el parámetro SCRIPT_FILENAME se defina correctamente.

Error 403 al acceder al directorio de instalación

La configuración presentada restringe el acceso a /install/. Para realizar la instalación, debe añadir su dirección IP a la lista allow o comentar temporalmente la línea deny all. Reestablezca la restricción una vez finalizado el proceso.

Límites de tamaño de archivo subidos

Los tres valores client_max_body_size (Nginx), upload_max_filesize y post_max_size (PHP) deben coincidir. En los ejemplos se establecen en 128 MiB (equivalente a 134.2 MB); ajústelos según sus necesidades. Nota: Aunque aquí se menciona MiB para ser precisos, en los archivos de configuración debe utilizar siempre las unidades convencionales K, M o G (ej: 128M), pues el software las interpreta según el contexto binario o decimal.

Consideraciones finales

La configuración presentada ha sido probada en producción con Geeklog 2.2 y Nginx 1.20+ en distribuciones como AlmaLinux/Rocky Linux 8/9 y ALDOS (que utiliza SysVinit). Aunque Geeklog es un sistema maduro y estable, es recomendable probar cualquier cambio en un entorno de desarrollo antes de aplicarlo en producción.

Si requiere redireccionar páginas estáticas específicas desde una antigua instalación de Geeklog hacia un nuevo sitio, puede añadir reglas de redirección 301 individuales mediante bloques location, tal como se explica en el manual Configuración de Nginx.

Proceda con las instrucciones de instalación de Geeklog como se establece en la documentación incluida tomando en consideración toda la información incluida en este documento.

Consideraciones para la creación de documentación técnica

Al crear publicaciones en Geeklog que contengan ejemplos de mandatos con el carácter de continuación de línea (\), es importante considerar que PHP procesa el contenido y lo interpreta como carácter de escape, lo que provoca su eliminación al guardar. Para evitar este conflicto y publicar documentación técnica precisa, siga estas recomendaciones:

Ejemplo:

# Formato incorrecto (el '\' se perderá):
mandato -opciones \
    -más opciones \
    argumentos

# Formato correcto (usando entidad HTML):
mandato -opciones \
    -más opciones \
    argumentos

Para dudas o comentarios, puede contactar al autor a través del correo electrónico indicado al inicio de este documento.