Servidor web · 11 min read · Oct 04, 2025

Cómo instalar Nginx con PHP y MySQL (LEMP Stack) en CentOS 7.6

Este tutorial muestra cómo puedes instalar Nginx en un servidor CentOS 7 con soporte para PHP (a través de PHP-FPM) y soporte para MySQL (MariaDB).

¿Qué es LEMP?

Nginx (pronunciado “engine x”) es un servidor HTTP de alto rendimiento, gratuito y de código abierto. Nginx es conocido por su estabilidad, conjunto de características ricas, configuración simple y bajo consumo de recursos.

Requisitos previos de LEMP

En este tutorial, usaré el nombre de host server1.example.com con la dirección IP 192.168.1.100. Estas configuraciones pueden diferir para ti, así que debes reemplazarlas donde sea apropiado.

Usaré el editor nano en este tutorial para editar archivos de configuración. Nano se puede instalar así.

yum -y install nano

Recomiendo tener un firewall instalado. Si aún no tienes firewalld instalado y deseas usar un firewall, instálalo con estos comandos:

yum -y install firewalld

inicia el firewall y habilítalo para que se inicie al arrancar el sistema.

systemctl start firewalld.service  
systemctl enable firewalld.service

A continuación, abre tu puerto SSH para asegurarte de que podrás conectarte al servidor por SSH.

firewall-cmd --permanent --zone=public --add-service=ssh  
firewall-cmd --reload

Habilitando Repositorios Adicionales de CentOS

La última versión de Nginx no está disponible en los repositorios oficiales de CentOS, así que incluimos el repositorio del proyecto Nginx para instalarlo:

nano /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

Instalando MySQL (MariaDB)

Primero, instalamos MariaDB como reemplazo de MySQL. MariaDB es un fork gratuito de MySQL. Ejecuta este comando en la terminal para instalar el servidor de base de datos MariaDB:

yum -y install mariadb mariadb-server net-tools

Luego creamos los enlaces de inicio del sistema para MariaDB (para que se inicie automáticamente cada vez que arranque el sistema) y comenzamos el servidor MariaDB:

systemctl enable mariadb.service  
systemctl start mariadb.service

Ahora verifica que la red esté habilitada. Ten en cuenta que el servicio MraiDB se llama mysql ya que es un servidor de base de datos compatible. Ejecuta

netstat -tap | grep mysql

Debería mostrar algo como esto:

[root@server1 ~]# netstat -tap | grep mysql  
tcp 0 0 0.0.0.0:mysql 0.0.0.0:* LISTEN 19842/mysqld 

Ejecuta:

mysql_secure_installation

para establecer una contraseña para el usuario root (de lo contrario, ¡cualquiera puede acceder a tu base de datos MySQL!):

[root@example ~]# mysql_secure_installation  
/usr/bin/mysql_secure_installation: line 379: find_mysql_client: command not found
NOTA: ¡SE RECOMIENDA EJECUTAR TODAS LAS PARTES DE ESTE SCRIPT PARA TODOS LOS SERVIDORES MariaDB EN USO DE PRODUCCIÓN! ¡LEA CADA PASO CUIDADOSAMENTE!
Para iniciar sesión en MariaDB y asegurarla, necesitaremos la contraseña actual para el usuario root. Si acabas de instalar MariaDB, y no has establecido la contraseña de root aún, la contraseña estará en blanco, así que solo debes presionar enter aquí.
Introduce la contraseña actual para root (presiona enter si no hay):  
OK, se utilizó la contraseña correctamente, continuando...
Establecer la contraseña de root asegura que nadie pueda iniciar sesión en el usuario root de MariaDB sin la autorización adecuada.
¿Establecer contraseña de root? [Y/n] <-- ENTER  
Nueva contraseña: <-- tucontraseñaderootsql  
Reingresa la nueva contraseña: <-- tucontraseñaderootsql  
¡Contraseña actualizada con éxito!  
Recargando tablas de privilegios..  
... ¡Éxito!
Por defecto, una instalación de MariaDB tiene un usuario anónimo, permitiendo que cualquiera inicie sesión en MariaDB sin tener que tener una cuenta de usuario creada para ellos. Esto está destinado solo para pruebas, y para hacer que la instalación sea un poco más fluida. Debes eliminarlos antes de pasar a un entorno de producción.
¿Eliminar usuarios anónimos? [Y/n] <-- ENTER  
... ¡Éxito!
Normalmente, solo se debería permitir que root se conecte desde 'localhost'. Esto asegura que alguien no pueda adivinar la contraseña de root desde la red.
¿Deshabilitar el inicio de sesión remoto de root? [Y/n] <-- ENTER  
... ¡Éxito!
Por defecto, MariaDB viene con una base de datos llamada 'test' a la que cualquiera puede acceder. Esto también está destinado solo para pruebas, y debe ser eliminado antes de pasar a un entorno de producción.
¿Eliminar la base de datos de prueba y el acceso a ella? [Y/n] <-- ENTER  
- Eliminando base de datos de prueba...  
... ¡Éxito!  
- Eliminando privilegios en la base de datos de prueba...  
... ¡Éxito!
Recargar las tablas de privilegios asegurará que todos los cambios realizados hasta ahora surtan efecto de inmediato.
¿Recargar tablas de privilegios ahora? [Y/n] <-- ENTER  
... ¡Éxito!
Limpiando...
¡Todo listo! Si has completado todos los pasos anteriores, tu instalación de MariaDB debería estar ahora segura.
¡Gracias por usar MariaDB!  
[root@example ~]#

[root@server1 ~]# mysql_secure_installation

Instalando Nginx

Nginx está disponible como un paquete de nginx.org que podemos instalar así:

yum -y install nginx

Luego creamos los enlaces de inicio del sistema para nginx y lo iniciamos:

systemctl enable nginx.service  
systemctl start nginx.service

Hay posibilidades de que obtengas un error de que el puerto 80 ya está en uso, el mensaje de error será algo como esto:

[root@server1 ~]# service nginx start  
Iniciando nginx: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)  
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)  
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)  
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)  
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)  
nginx: [emerg] aún no se pudo bind()  
                                                           [FALLIDO]  
[root@server1 ~]#

Esto significa que otro servidor web (probablemente Apache) ya está en funcionamiento en este servidor. Detén el servicio de Apache y luego inicia el servicio para NGINX:

systemctl stop httpd.service  
yum remove httpd  
systemctl disable httpd.service

Luego intenta iniciar Nginx nuevamente.

systemctl start nginx.service

Abre los puertos HTTP y HTTPS en el firewall

firewall-cmd --permanent --zone=public --add-service=http  
firewall-cmd --permanent --zone=public --add-service=https  
firewall-cmd --reload

La salida resultante en la terminal se verá así:

[root@example ~]# firewall-cmd --permanent --zone=public --add-service=http  
success  
[root@example ~]# firewall-cmd --permanent --zone=public --add-service=https  
success  
[root@example ~]# firewall-cmd --reload  
success  
[root@example ~]#

Escribe la dirección IP o el nombre de host de tu servidor web en un navegador (por ejemplo, http://192.168.1.100), y deberías ver la página de bienvenida de Nginx:

La página de bienvenida de Nginx.

Instalando PHP

Podemos hacer que PHP 5 funcione con Nginx a través de PHP-FPM (FastCGI Process Manager). PHP-FPM es una implementación alternativa de PHP FastCGI con algunas características adicionales útiles para sitios de cualquier tamaño, especialmente sitios más concurridos. Podemos instalar php-fpm junto con php-cli y algunos módulos de PHP5 como php-mysql que necesitas si deseas usar MySQL desde tus scripts PHP de la siguiente manera:

yum -y install php-fpm php-cli php-mysql php-gd php-ldap php-odbc php-pdo php-pecl-memcache php-pear php-mbstring php-xml php-xmlrpc php-mbstring php-snmp php-soap

APC es un caché de opcodes de PHP gratuito y de código abierto para almacenar en caché y optimizar el código intermedio de PHP. Es similar a otros cachés de opcodes de PHP, como eAccelerator y Xcache. Se recomienda encarecidamente tener uno de estos instalados para acelerar tu página PHP.

Instalaré APC desde el repositorio PECL de PHP. PECL requiere que se instalen las herramientas de desarrollo de Centos para compilar el paquete APC.

yum -y install php-devel  
yum -y groupinstall 'Development Tools'

y luego instalar APC:

pecl install apc
[root@example ~]# pecl install apc  
downloading APC-3.1.13.tgz ...  
Iniciando la descarga de APC-3.1.13.tgz (171,591 bytes)  
.................hecho: 171,591 bytes  
55 archivos fuente, construyendo  
corriendo: phpize  
Configurando para:  
Versión de API de PHP: 20100412  
Número de API de módulo Zend: 20100525  
Número de API de extensión Zend: 220100525  
Habilitar depuración interna en APC [no] : <-- ENTER  
Habilitar información de archivo por solicitud sobre archivos utilizados desde la caché de APC [no] : <-- ENTER  
Habilitar bloqueos de giro (EXPERIMENTAL) [no] : <-- ENTER  
Habilitar protección de memoria (EXPERIMENTAL) [no] : <-- ENTER  
Habilitar mutexes pthread (predeterminado) [no] : <-- ENTER  
Habilitar bloqueos de lectura/escritura pthread (EXPERIMENTAL) [yes] : <-- ENTER  
construyendo en /var/tmp/pear-build-rootVrjsuq/APC-3.1.13  
......

Luego abre /etc/php.ini y establece cgi.fix_pathinfo=0:

nano /etc/php.ini
[...]
; cgi.fix_pathinfo proporciona soporte *real* para PATH_INFO/PATH_TRANSLATED para CGI.  El comportamiento anterior de PHP era establecer PATH_TRANSLATED en SCRIPT_FILENAME, y no entender qué es PATH_INFO.  Para más información sobre PATH_INFO, consulta las especificaciones de cgi.  Establecer esto en 1 hará que PHP CGI corrija sus rutas para ajustarse a la especificación.  Un valor de cero hace que PHP se comporte como antes.  El valor predeterminado es 1.  Debes corregir tus scripts para usar SCRIPT_FILENAME en lugar de PATH_TRANSLATED.
; http://www.php.net/manual/en/ini.core.php#ini.cgi.fix-pathinfo
cgi.fix_pathinfo=0
[...]

(Consulta http://wiki.nginx.org/Pitfalls para averiguar por qué deberías hacer esto.)

y agrega la línea:

[...]
extension=apc.so

al final del archivo /etc/php.ini.

Además de eso, para evitar errores de zona horaria como

[28-Junio-2016 14:21:01] PHP Warning: phpinfo(): No es seguro confiar en la configuración de zona horaria del sistema. Se *requiere* que uses la configuración date.timezone o la función date_default_timezone_set(). En caso de que hayas usado alguno de esos métodos y aún estés recibiendo esta advertencia, lo más probable es que hayas escrito mal el identificador de zona horaria. Seleccionamos 'Europa/Berlín' para 'CEST/2.0/DST' en su lugar en /usr/share/nginx/html/info.php en la línea 2

… en /var/log/php-fpm/www-error.log cuando llamas a un script PHP en tu navegador, debes establecer date.timezone en /etc/php.ini:

[...]
[Date]
; Define la zona horaria predeterminada utilizada por las funciones de fecha
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone
date.timezone = "Europe/Berlin"
[...]

Puedes averiguar la zona horaria correcta para tu sistema ejecutando:

cat /etc/sysconfig/clock

[root@server1 nginx]# cat /etc/sysconfig/clock
ZONE=”Europe/Berlin”
[root@server1 nginx]#

A continuación, crea los enlaces de inicio del sistema para php-fpm y inícialo:

systemctl enable php-fpm.service  
systemctl start php-fpm.service

PHP-FPM es un proceso daemon (con el script de inicio /etc/init.d/php-fpm) que ejecuta un servidor FastCGI en el puerto 9000.

Configurando Nginx

La configuración de nginx está en /etc/nginx/nginx.conf que abrimos ahora:

nano /etc/nginx/nginx.conf

Primero (esto es opcional) puedes aumentar el número de procesos de trabajo y establecer el keepalive_timeout a un valor razonable:

[...]
worker_processes  4;
[...]
    keepalive_timeout  2;
[...]

Los hosts virtuales se definen en contenedores server {} en el directorio /etc/nginx/conf.d. Vamos a modificar el vhost predeterminado (en /etc/nginx/conf.d/default.conf) de la siguiente manera:

nano /etc/nginx/conf.d/default.conf
[...]
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm index.php;
    }

    #error_page  404              /404.html;

    # redirigir páginas de error del servidor a la página estática /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy los scripts PHP a Apache escuchando en 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pasar los scripts PHP al servidor FastCGI escuchando en 127.0.0.1:9000
    #

    location ~ \.php$ {
        root           /usr/share/nginx/html;
        try_files $uri =404;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
    
    # denegar acceso a archivos .htaccess, si la raíz del documento de Apache
    # coincide con la de nginx
    #
    location ~ /\.ht {
        deny  all;
    }
}

servername ; hace de este un vhost predeterminado que captura todo (por supuesto, también puedes especificar un nombre de host aquí como www.example.com).

En la parte location /, he agregado index.php a la línea de índice. root /usr/share/nginx/html; significa que la raíz del documento es el directorio /usr/share/nginx/html.

La parte importante para PHP es la estrofa location ~ .php$ {}. Descoméntala para habilitarla. Cambia la línea root a la raíz del documento del sitio web (por ejemplo, root /usr/share/nginx/html;). Ten en cuenta que he agregado la línea try_files $uri =404; para prevenir exploits de día cero (consulta http://wiki.nginx.org/Pitfalls#Passing_Uncontrolled_Requests_to_PHP y http://forum.nginx.org/read.php?2,88845,page=3). Asegúrate de cambiar la línea fastcgi_param a fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; porque de lo contrario, el intérprete de PHP no encontrará el script PHP que llamas en tu navegador ( $document_root se traduce a /usr/share/nginx/html porque eso es lo que hemos establecido como nuestra raíz del documento).

PHP-FPM está escuchando en el puerto 9000 en 127.0.0.1 por defecto, por lo tanto, le decimos a Nginx que se conecte a 127.0.0.1:9000 con la línea fastcgi_pass 127.0.0.1:9000;. También es posible hacer que PHP-FPM use un socket Unix - describiré esto en el capítulo 7.

Ahora guarda el archivo y recarga Nginx:

systemctl restart nginx.service

Ahora crea el siguiente archivo PHP en la raíz del documento /usr/share/nginx/html…

nano /usr/share/nginx/html/info.php

Ahora llamamos a ese archivo en un navegador (por ejemplo, http://192.168.1.100/info.php):

La información de PHP de nuestro servidor nginx.

Como ves, PHP 5 está funcionando, y está funcionando a través de FPM/FastCGI, como se muestra en la línea Server API. Si desplazas hacia abajo, verás todos los módulos que ya están habilitados en PHP5, incluido el módulo MySQL:

El controlador MySQL ha sido activado en PHP.

Haciendo que PHP-FPM use un Socket Unix

Por defecto, PHP-FPM está escuchando en el puerto 9000 en 127.0.0.1. También es posible hacer que PHP-FPM use un socket Unix que evita la sobrecarga de TCP. Para hacer esto, abre /etc/php-fpm.d/www.conf…

nano /etc/php-fpm.d/www.conf

… y haz que la línea listen se vea así:

[...]
;listen = 127.0.0.1:9000
listen = /var/run/php-fpm/php5-fpm.sock
[...]

Luego recarga PHP-FPM:

systemctl restart php-fpm.service

A continuación, revisa tu configuración de Nginx y todos tus vhosts y cambia la línea fastcgi_pass 127.0.0.1:9000; a fastcgi_pass unix:/tmp/php5-fpm.sock;, por ejemplo, así:

vi /etc/nginx/conf.d/default.conf
[...]
    location ~ \.php$ {
        root           /usr/share/nginx/html;
        try_files $uri =404;
        fastcgi_pass   unix:/var/run/php-fpm/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
[...]

Finalmente, recarga Nginx:

systemctl restart nginx.service

Descarga este servidor CentOS 7 como una máquina virtual

Esta configuración está disponible como una descarga de máquina virtual en formato ova/ovf (compatible con VMWare y Virtualbox) para suscriptores de howtoforge.

Detalles de inicio de sesión para la VM

  • La contraseña de root es: howtoforge
  • La contraseña del usuario “administrador” es: howtoforge

Por favor, cambia ambas contraseñas en el primer inicio de sesión.

  • La dirección IP de la VM es 192.168.1.100

Enlaces

Share: X/Twitter LinkedIn

Recibe nuevas publicaciones en tu bandeja de entrada.

No spam. Cancela la suscripción en cualquier momento.