Apuntes redes

No vayas a access.log, donde habitan los monstruos.

Introducción

El archivo php.ini es el núcleo de configuración del intérprete de PHP. Desde cómo se manejan los errores hasta qué extensiones se cargan y qué límites de memoria o tiempo se imponen a los scripts, todo pasa por aquí.

En sistemas modernos basados en Linux, el archivo php.ini suele encontrarse en una ruta similar a /etc/php/8.x/{sapi}/php.ini, donde {sapi} puede ser cli, apache2, fpm, etc. Cada uno se carga dependiendo del contexto en el que se ejecute PHP. Por lo tanto:

  • Línea de comandos (CLI): usa /etc/php/8.x/cli/php.ini
  • Apache con mod_php: usa /etc/php/8.x/apache2/php.ini
  • PHP-FPM (Nginx, Apache MPM Event, etc.): usa /etc/php/8.x/fpm/php.ini

Importante: No asumas que el archivo indicado por php --ini es el que influye en tu sitio web. Ese comando sólo te muestra el que usa el ejecutable PHP en consola (CLI), y en la práctica, eso rara vez es relevante para entornos de producción web.

Cómo saber cuál php.ini se está usando realmente

La forma más confiable es preguntárselo directamente a PHP mediante código. Puedes usar php_ini_loaded_file(), que devuelve la ruta exacta del archivo cargado en ese entorno.

Desde un script web

<?php
echo php_ini_loaded_file();
?>

Guarda esto como ini.php o similar y ábrelo en el navegador. Verás en pantalla la ruta al archivo php.ini que está usando tu servidor web.

Desde la terminal (CLI)

php -r 'echo php_ini_loaded_file() . PHP_EOL;'

Eso te muestra el archivo cargado por el entorno de consola. Ten en cuenta que puede ser distinto al usado por Apache o FPM.

En resumen: no edites nada en este archivo hasta que estés seguro de cuál archivo php.ini afecta al entorno que te interesa. Una confusión aquí es causa habitual de frustración, especialmente cuando los cambios no surten efecto.

Asimismo recuerda que ningun cambio surte efecto hasta que no reinicies el servidor.

php.ini: Configuración Esencial de PHP

En muchas ocasiones la instalación de PHP no genera un archivo php.ini. En el directorio raíz de tu instalación de PHP encontrarás archivos como php.ini-production o php.ini-development (anteriormente php.ini-recommended y php.ini-dist).

Lo primero que debes hacer es seleccionar una de estas versiones, configurarla según tus necesidades y guardarla con el nombre php.ini. La versión production está optimizada para entornos de producción con mayor seguridad y rendimiento, mientras que la development es más permisiva y útil durante el desarrollo.

Dentro de php.ini:

  • Todo lo que comienza con un punto y coma (;) es un comentario y es ignorado.
  • El texto entre corchetes, como [PHP], indica una cabecera de sección.
  • Las instrucciones son directivas, compuestas por una clave y su valor, por ejemplo: asp_tags = Off. Las directivas distinguen entre mayúsculas y minúsculas (asp_tags no es lo mismo que Asp_tags).
  • Algunas directivas pueden estar comentadas por defecto (precedidas por ;), lo que significa que están inactivas. Debes descomentarlas si necesitas esa funcionalidad.

Consideraciones sobre rutas (paths):

En Linux, las rutas utilizan la barra (/usr/local/bin/). En Windows, se usa la barra invertida (C:\windows). En php.ini, los formatos admisibles incluyen:

/var/www/html/directorio
./directorio/directorio/

¿Cómo funciona el archivo php.ini?

Si PHP está configurado como módulo de un servidor web (como Apache o Nginx), el archivo php.ini se lee cada vez que se reinicia el servicio del servidor web. Por lo tanto, cualquier cambio que realices requerirá un reinicio del servidor para que surta efecto.

Si PHP se ejecuta como CGI/FastCGI, php.ini se puede leer en cada solicitud, dependiendo de la configuración del servidor web y del gestor de FastCGI. Sin embargo, para un rendimiento óptimo, muchos sistemas FastCGI mantienen un proceso de PHP que lee php.ini al inicio.

Ubicación de php.ini:

El servidor buscará php.ini en un orden específico. Las ubicaciones comunes en Linux son:

  • /etc/php/<version>/<sapi>/php.ini (donde <version> es la versión de PHP y <sapi> es el SAPI, como apache2, fpm, cli).
  • El directorio de instalación de PHP.
  • Directorios especificados en la variable de entorno PHPRC.

Es crucial asegurarse de que el servidor está leyendo el php.ini correcto. Los problemas más comunes con PHP a menudo se deben a una configuración incorrecta o a tener el archivo mal ubicado o duplicado. Si realizas un cambio en php.ini y no ves el efecto, verifica la sintaxis, asegúrate de haber reiniciado el servidor correctamente y confirma que está leyendo el php.ini deseado.

Para verificar la configuración de PHP en tiempo de ejecución, es altamente recomendable tener una página con la función phpinfo():

<?php
phpinfo();
?>

Guarda este código en un archivo como info.php en tu directorio web y accéde a él desde el navegador para ver la configuración activa de PHP.

Los dos versiones de php.ini

En las distribuciones de PHP, encontrarás php.ini-production y php.ini-development. Ambos contienen las mismas directivas, pero con valores predeterminados diferentes:

  • php.ini-production: Más estricto en seguridad y optimizado para rendimiento en entornos en vivo. Desactiva la visualización de errores en pantalla y establece límites de recursos más conservadores.
  • php.ini-development: Más permisivo y útil para depuración. Muestra errores en pantalla, lo que facilita la identificación de problemas durante el desarrollo.

Las Directivas

A continuación, exploraremos algunas de las directivas más importantes de php.ini. Es una buena práctica dejar los valores predeterminados, a menos que sepas exactamente lo que estás haciendo. Los valores que se indican son solo ejemplos y pueden variar según tus necesidades.

Nota: Aunque php.ini establece la configuración global de PHP, muchas directivas pueden ser sobrescritas o modificadas dinámicamente desde el propio script PHP utilizando funciones como ini_set() para establecer valores en tiempo de ejecución, o ini_get() para leer la configuración actual. Sin embargo, no todas las directivas permiten ser cambiadas desde el script; algunas solo pueden ser alteradas a nivel de php.ini o la configuración del servidor web.

Opciones de Lenguaje

Esta sección contiene instrucciones generales sobre el funcionamiento de PHP:

  • engine = On: Activa la interpretación de scripts PHP. Si PHP está cargado como módulo de Apache/Nginx, esta directiva, junto con la configuración del servidor web, permite habilitar o deshabilitar PHP en directorios específicos.
  • short_open_tag = Off: Controla si se pueden usar las etiquetas PHP abreviadas (<? ... ?>). Se recomienda Off para una mayor portabilidad del código, obligando al uso de <?php ... ?>. Esta directiva NO afecta al uso del atajo para imprimir variables (<%= $valor %>), que puede seguir usándose.
  • precision = 14: Número máximo de decimales visualizados para números de punto flotante.
  • output_buffering = 4096: Habilita el almacenamiento en búfer de la salida. Si está On (o con un tamaño en bytes como 4096), PHP no envía las cabeceras HTTP al inicio de la ejecución del script, sino que las almacena temporalmente. Esto permite modificar o añadir cabeceras HTTP durante la ejecución del script, que se enviarán solo al finalizar. Deshabilitar esto puede mejorar ligeramente el rendimiento, pero limita la flexibilidad para enviar cabeceras.
  • output_handler =: Permite redirigir toda la salida de tus scripts a una función PHP. Es preferible no habilitar esta opción globalmente y establecerla si es necesario en scripts específicos.
  • zlib.output_compression = Off: Habilita la compresión de la salida de los scripts utilizando la librería zlib. Puedes indicar Off | On o precisar el tamaño del búfer (por defecto es 4 KB). Esto puede reducir el tamaño de los datos transferidos, mejorando la velocidad de carga de la página.
  • ;zlib.output_handler =: Si zlib.output_compression está activada, no puedes usar output_handler; esta directiva ofrece una funcionalidad similar.
  • implicit_flush = Off: Intenta enviar el contenido del búfer de salida al cliente después de cada echo, print o bloque HTML. Es desaconsejable su activación, siendo preferible usar la función flush() explícitamente cuando sea necesario para un control más preciso.
  • unserialize_callback_func =: Relacionado con las funciones serialize(). Define una función de callback que se llamará si una clase no está definida al unserializar un objeto.
  • open_basedir =: Limita los archivos que PHP puede abrir a un árbol de directorios específico. Si un script intenta abrir un archivo fuera de este árbol, PHP se negará. Los enlaces simbólicos se resuelven para evitar evadir esta restricción.
    • En Linux, los directorios se separan con dos puntos (:). Ejemplo: open_basedir = /var/www/html:/tmp.
    • En Windows, los directorios se separan con punto y coma (;).
    • El valor especial . indica que el directorio base será aquel en el que reside el script.
  • disable_functions =: Permite inhabilitar funciones PHP específicas de forma global. Las funciones se listan separadas por comas (,). Ejemplo: disable_functions = exec,system,shell_exec,passthru. Esto es una medida de seguridad importante.
  • highlight.*: Permiten especificar los colores a utilizar por el coloreador de sintaxis interno de PHP (usado por highlight_string() y highlight_file()).
  • expose_php = On: Determina si PHP revela su presencia en el servidor, por ejemplo, incluyendo información en las cabeceras HTTP del servidor (ej. X-Powered-By: PHP/X.Y.Z). Se recomienda ponerlo en Off en producción por razones de seguridad, ya que oculta la versión de PHP, dificultando ataques dirigidos a vulnerabilidades conocidas de versiones específicas.

Límites al Empleo de Recursos

Estas directivas controlan el consumo de recursos por parte de los scripts:

  • max_execution_time = 30: Fija el tiempo máximo en segundos que se le permite usar a un script antes de ser finalizado por el intérprete. Evita que scripts mal escritos o bucles infinitos bloqueen el servidor.
  • max_input_time = 60: Tiempo máximo en segundos que el script puede invertir en analizar datos recibidos (por ejemplo, de un POST).
  • memory_limit = 128M: Fija el tamaño máximo de memoria en bytes que se permite reclamar a un script. Evita que scripts mal escritos consuman toda la memoria disponible del servidor. Los valores comunes son 64M, 128M, 256M.

Gestión y Archivo de Errores

Estas directivas controlan cómo PHP reporta y registra los errores:

  • error_reporting = E_ALL: Fija el nivel (detalle) con el que PHP informa de errores.
    • Durante el desarrollo, se recomienda E_ALL para ver todos los errores y advertencias.
    • En producción, se recomienda deshabilitar la visualización de errores en pantalla y activar el registro de errores en un archivo, para evitar revelar información sensible.
    • Valores comunes:
      • E_ALL: Todos los errores y advertencias.
      • E_ALL & ~E_NOTICE & ~E_DEPRECATED: Todos los errores críticos, excluyendo avisos y advertencias de funciones obsoletas que no impiden la ejecución.
      • E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR: Solo errores fatales.
  • display_errors = Off: Determina si los errores se visualizan en pantalla como parte de la salida HTML. En producción, siempre debe estar en Off para seguridad.
  • display_startup_errors = Off: Incluso con display_errors On, por defecto PHP no muestra los errores que detecta en la secuencia de encendido. Con esta directiva puedes mostrar estos errores. Desaconsejado activarla en producción.
  • log_errors = On: Guarda los mensajes de error en un archivo. Normalmente, el registro de errores del servidor web o un archivo específico. En producción, siempre debe estar en On y display_errors en Off.
  • log_errors_max_len = 1024: Especifica el tamaño máximo de cada entrada de error en el error_log. Un valor de 0 significa sin restricción.
  • ignore_repeated_errors = Off: Si está activado, no registra mensajes de error repetidos que provengan de la misma línea de código.
  • ignore_repeated_source = Off: Si está activado, considera repetidos los mensajes de error iguales, incluso si provienen de distinta línea o script.
  • report_memleaks = On: Muestra o no informes sobre "memory leaks" (scripts que no liberan la memoria utilizada). Útil para depuración.
  • track_errors = Off: Si se activa, el último mensaje de error/advertencia se almacena en la variable $php_errormsg.
  • html_errors = Off: Si está activo, los mensajes de error se formatearán con etiquetas HTML. Se recomienda Off si los errores se registran en un archivo de texto plano.
  • docref_root = /phpmanual/ y docref_ext = .html: Si html_errors está activado, PHP puede incluir enlaces en el mensaje de error que te dirigen a la página del manual que explica la función implicada. Puedes indicar la ubicación local de una copia del manual.
  • error_prepend_string = "<font color=ff0000>" y error_append_string = "</font>": Cadenas a añadir antes y después de cada mensaje de error cuando html_errors está On.
  • ;error_log = /var/log/php_errors.log: Nombre del archivo para registrar los errores de un script. Si se utiliza el valor especial syslog, los errores se envían al registro de errores del sistema (ej. journalctl en sistemas systemd). Se recomienda especificar una ruta absoluta a un archivo de registro con permisos de escritura para el usuario del servidor web.

Gestión de Datos

  • ;arg_separator.output = "&amp;": El carácter que se empleará en las URLs generadas por PHP para separar argumentos. & es el separador por defecto. Se recomienda &amp; para URLs válidas en HTML.
  • ;arg_separator.input = ";&": Separadores que usará PHP cuando analice una URL suministrada para almacenar sus valores en variables.
  • variables_order = "GPCS": Fija el orden de precedencia en que PHP registra e interpreta las variables superglobales (de izquierda a derecha). Los valores posibles son:
    • G: $_GET
    • P: $_POST
    • C: $_COOKIE
    • E: $_ENV (variables de entorno)
    • S: $_SERVER (variables del servidor)
    Por ejemplo, GP haría que PHP ignorara las cookies y sobrescribiera las variables de GET con las de POST si tienen el mismo nombre.
  • register_argc_argv = Off: Esta directiva instruye a PHP si debe declarar las variables $argv y $argc (arrays predefinidos que almacenan los parámetros pasados a un script en la línea de comandos y su número, respectivamente). Útil para scripts CLI.
  • post_max_size = 8M: Tamaño máximo de los datos que PHP aceptará por el método POST. Este límite es importante para la subida de archivos y el envío de formularios grandes. Debe ser igual o mayor que upload_max_filesize.

Más Directivas de Gestión de Datos

  • auto_prepend_file = y auto_append_file =: Permiten indicar la ruta y el nombre de un archivo que se incluirá automáticamente antes o después (respectivamente) de todos los archivos PHP que se ejecuten. El valor especial none desactiva esta adición automática. Útil para incluir archivos de configuración o de inicialización global.
  • ;default_charset = "UTF-8": Por defecto, el juego de caracteres indicado por PHP en la cabecera de salida. Se recomienda UTF-8 para la mayoría de las aplicaciones web modernas.
  • default_mimetype = "text/html": Por defecto, el tipo MIME de salida de datos.

Rutas y Directorios

  • include_path = ".:/path/to/your/php/libraries": Permite especificar una lista de directorios en los que las funciones require(), include() y fopen() buscarán los archivos requeridos. El formato es una lista de directorios separados por dos puntos (:) en Linux o punto y coma (;) en Windows.
    • Ejemplo Linux: include_path = ".:/usr/share/php:/var/www/html/lib"
    • El valor por defecto . (solo el directorio actual) es común.
  • doc_root =: Indica el "directorio raíz" donde se encuentran tus páginas PHP en el servidor. Solo se usa si no está vacío. Si PHP se configura con open_basedir, las páginas PHP situadas fuera de este directorio no se interpretarán.
  • user_dir =: El directorio raíz para los archivos PHP bajo el directorio inicial de un usuario (ej. ~/public_html). Normalmente se deja vacío, a menos que se configure un servidor web para permitir directorios de usuario.
  • extension_dir = "/usr/lib/php/20xxxxxx": En qué directorio debe buscar PHP las extensiones dinámicas a cargar. La ruta exacta varía según la versión de PHP y la distribución de Linux (ej. /usr/lib/php/20190902 para PHP 7.4). En Windows, por defecto, se buscarían en C:\php\ext\.
  • enable_dl = Off: Esta directiva sólo es útil en la versión del PHP como módulo del Apache. Puede habilitar o deshabilitar para un servidor virtual o para un directorio la carga dinámica de extensiones de PHP mediante dl(). Por razones de seguridad, se recomienda mantenerla en Off en producción, ya que dl() puede ignorar las restricciones de open_basedir.
  • cgi.force_redirect = 1: Importante directiva de seguridad que debes activar si ejecutas PHP como CGI/FastCGI con Apache. No es necesaria si tienes PHP como módulo de Apache o si usas IIS de Microsoft.
  • ;cgi.redirect_status_env =: En conjunción con cgi.force_redirect y servidores distintos de Apache o iPlanet.
  • ;fastcgi.impersonate = 1: En conjunción con IIS y FastCGI, permite la suplantación de identidad para que PHP se ejecute bajo la cuenta de usuario del usuario anónimo o autenticado.

Subir Ficheros

  • file_uploads = On: Permitir o no subir (upload) ficheros vía HTTP.
  • upload_tmp_dir = /tmp: Carpeta o directorio utilizable para guardar temporalmente archivos subidos por PHP. Si no se especifica, usará el directorio temporal del sistema. El usuario que ejecuta el script (el usuario del servidor web, como www-data en Debian/Ubuntu o apache en CentOS/RHEL) debe tener permisos de escritura en este directorio.
  • upload_max_filesize = 2M: Tamaño máximo de archivos que pueden subirse. Ajusta este valor según tus necesidades. Debe ser menor o igual que post_max_size.

Directivas Relacionadas con fopen

  • allow_url_fopen = On: Permite pasar URLs (HTTP, FTP) a funciones como fopen(), file_get_contents(), etc., en lugar de la ubicación física del archivo. Esto permite a PHP interactuar directamente con recursos remotos.
  • ;from="john@doe.com": Define el correo electrónico a usar como contraseña para FTP anónimo cuando se usa allow_url_fopen.
  • ;user_agent="PHP": Define la "firma" (User-Agent) que PHP enviará al servidor remoto del cual obtiene archivos.
  • default_socket_timeout = 60: Tiempo de espera en segundos para la apertura de sockets.
  • ;auto_detect_line_endings = Off: Si activo, PHP detectará automáticamente el carácter que indica fin de línea (distinto en windows, linux y windows).

Extensiones Dinámicas

  • extension=: Qué extensiones dinámicas debe cargar PHP cuando arranca. Debes elegir el archivo que corresponde a tu sistema operativo: por ejemplo extension=mysqli.so para Linux, extension=php_mysqli.dll para Windows.
    • Importante: Solo se indica el nombre del archivo de la extensión, no su ubicación. Los archivos DEBEN estar en el directorio especificado más arriba con extension_dir.
    • Muchas extensiones populares (como MySQLi, PDO, GD) ya están compiladas por defecto en las versiones modernas de PHP o se habilitan fácilmente a través de los paquetes de la distribución (ej. sudo apt install php-mysql en Debian/Ubuntu).

Configuración de Módulos de PHP

  • define_syslog_variables = Off: Permite definir variables del sistema relacionadas con el registro de syslog. Recomendado Off.
  • ;browscap = extra/browscap.ini: El archivo browscap.ini es un archivo de texto que contiene información sobre las cadenas de identificación que usa cada navegador. Mediante esta directiva indicas a PHP donde tienes browscap.ini; se usa conjuntamente con la función get_browser().

Directivas de Configuración de Correo

La forma en que PHP envía correo electrónico varía según el sistema operativo.

  • En Linux: PHP generalmente delega el envío de correo a un agente de transporte de correo (MTA) como sendmail, Postfix o Exim, que deben estar instalados y configurados en el sistema.
    • sendmail_path = /usr/sbin/sendmail -t -i: Especifica la ruta al ejecutable de sendmail (o un enlace a tu MTA configurado) y sus argumentos.
  • En Windows: PHP no tiene un MTA integrado y debe configurarse para usar un servidor SMTP externo.
    • SMTP = localhost: La dirección del servidor SMTP (correo saliente). Podría ser smtp.miservidor.com o una IP.
    • smtp_port = 25: El puerto del servidor SMTP.
    • sendmail_from = webmaster@misitio.com: La dirección del remitente ("De:") para los correos enviados desde PHP bajo Windows.

Sesiones

Esta sección es crucial para gestionar sesiones de usuario en aplicaciones web.

  • session.save_handler = files: Define cómo se guardan los datos de la sesión. files es el valor por defecto, guardando las sesiones en archivos. Otros valores pueden ser memcached, redis, database, etc.
  • session.save_path = "/var/lib/php/sessions": Directorio donde se guardarán los archivos de sesión. Este directorio debe tener permisos de escritura para el usuario del servidor web. Es crucial que este directorio no sea accesible públicamente desde el navegador.
  • session.use_cookies = 1: Indica si PHP usará cookies para gestionar los IDs de sesión. Se recomienda 1 (On).
  • session.use_only_cookies = 1: Si está en 1, fuerza el uso de cookies para el ID de sesión y previene que los IDs de sesión se pasen por URL, lo que mejora la seguridad. Recomendado en 1.
  • session.name = PHPSESSID: El nombre de la cookie de sesión. Puedes cambiarlo para ocultar el hecho de que estás usando PHP.
  • session.auto_start = 0: Si está en 1, una sesión se iniciará automáticamente en cada solicitud. Generalmente se prefiere 0 (Off) y llamar a session_start() explícitamente cuando sea necesario.
  • session.cookie_lifetime = 0: La vida útil de la cookie de sesión en segundos. 0 significa que la cookie expirará cuando el navegador se cierre.
  • session.cookie_path = /: La ruta en el dominio donde la cookie estará disponible.
  • session.cookie_domain =: El dominio para el que la cookie es válida.
  • session.cookie_secure = Off: Si está en On, la cookie de sesión solo se enviará sobre conexiones HTTPS. Recomendado On en producción con HTTPS.
  • session.cookie_httponly = Off: Si está en On, la cookie de sesión solo será accesible a través del protocolo HTTP y no a través de scripts (como JavaScript). Esto ayuda a mitigar ataques de scripting entre sitios (XSS). Recomendado On.
  • session.gc_probability = 1 y session.gc_divisor = 1000: Juntos, controlan la probabilidad de que se inicie el recolector de basura de sesión para limpiar las sesiones antiguas. En este ejemplo, hay una probabilidad de 1 en 1000 de que el recolector se ejecute.
  • session.gc_maxlifetime = 1440: El tiempo en segundos después del cual los datos de sesión se consideran "basura" y potencialmente se eliminarán por el recolector de basura.

Valores recomendados en php.ini

Estos son algunos ajustes comunes que conviene adaptar según el entorno. En desarrollo se prioriza la visibilidad de errores y la flexibilidad; en producción, la seguridad y el rendimiento.

Directiva Desarrollo Producción Notas
display_errors On Off No mostrar errores en producción: es información sensible
log_errors On On Debe estar siempre activo
error_reporting E_ALL E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT Más detallado en desarrollo
display_startup_errors On Off Mostrar errores al iniciar PHP (útil en desarrollo)
memory_limit 512M 128M Depende de la carga del proyecto
post_max_size 100M 8M Ajusta según necesidad de subida de formularios
upload_max_filesize 100M 8M Igual que el anterior
max_execution_time 300 30 Tiempo máximo de ejecución del script
max_input_time 300 60 Tiempo máximo para recibir datos
session.cookie_httponly On On Protege las cookies de sesión (ambos entornos)
session.cookie_secure Off On Solo usar cookies en HTTPS en producción
expose_php On Off No revelar versión de PHP
TOP