> La lista completa de artículos está en [llms.txt](https://docs.f3cloud.com/llms.txt). Cada página tiene versión en Markdown, basta con añadir .md a su dirección. Esta página en Markdown: [https://docs.f3cloud.com/es/software-setup/nginx-installation.md](https://docs.f3cloud.com/es/software-setup/nginx-installation.md).

# Cómo instalar Nginx con PHP-FPM y SSL en Ubuntu y Debian

Cómo instalar Nginx en un VPS con Ubuntu o Debian, crear un sitio, conectar PHP-FPM y un certificado SSL gratuito de Let's Encrypt. Comprobación de la configuración, solución de los errores 502, 403 y 413 y desinstalación de Nginx.

**Nginx** es un servidor web rápido en el que funciona una enorme parte de los sitios de internet. Sirve páginas y archivos a los visitantes, pasa los scripts PHP para que se ejecuten y cifra la conexión por HTTPS.

En esta guía instalaremos Nginx, crearemos un sitio, le conectaremos PHP y emitiremos un certificado SSL gratuito. Hemos probado todos los comandos en Debian 12, y en Ubuntu funcionan igual.

> **Qué necesitas.**
>
> Para empezar necesitas un VPS con Ubuntu o Debian y acceso a él por SSH, por ejemplo con [Termius](https://docs.f3cloud.com/es/vps/termius-connection.md). Para HTTPS también te hará falta un dominio cuyo registro A apunte a la dirección IP del servidor.

***

### 1. Instala Nginx

```bash
# Actualizamos la lista de paquetes e instalamos Nginx
apt update && apt install -y nginx

# Comprobamos que Nginx se ha iniciado
systemctl status nginx
```

Si en la línea **Active** aparece en verde `active (running)`, Nginx funciona y a partir de ahora se iniciará solo cada vez que se reinicie el servidor.

<figure><img src="https://docs.f3cloud.com/img/nginx-status.png" alt="Salida de systemctl status nginx con el estado active (running)"><figcaption><p>Nginx está instalado y en marcha</p></figcaption></figure>

Abre en el navegador `http://IP-de-tu-servidor`. Debería aparecer la página de bienvenida de Nginx.

<figure><img src="https://docs.f3cloud.com/img/nginx-welcome.png" alt="Página de bienvenida Welcome to nginx" width="460"><figcaption><p>Página de bienvenida de Nginx</p></figcaption></figure>

> **¿No se abre la página?.**
>
> Si el servidor tiene activado un cortafuegos, abre en él los puertos **80** y **443**. Te explicamos cómo hacerlo en el artículo [sobre el cortafuegos](https://docs.f3cloud.com/es/client-area/protect-vps-from-unauthorised-access/firewall.md).

***

### 2. Crea la carpeta del sitio

Lo más cómodo es guardar los archivos de cada sitio en una carpeta propia dentro de `/var/www`. Vamos a crear la carpeta y una página sencilla para comprobar que todo va bien. Aquí y en adelante, sustituye `example.com` por tu dominio.

```bash
# Creamos la carpeta para los archivos del sitio
mkdir -p /var/www/example.com

# Ponemos dentro una página de prueba
echo '<h1>¡El sitio funciona!</h1>' > /var/www/example.com/index.html

# Damos la carpeta al usuario www-data, con el que se ejecuta Nginx
chown -R www-data:www-data /var/www/example.com
```

***

### 3. Configura el sitio en Nginx

La configuración de los sitios se guarda en la carpeta `/etc/nginx/sites-available`. Crea en ella un archivo para tu sitio.

```bash
nano /etc/nginx/sites-available/example.com
```

Pega dentro la configuración de abajo y cambia el dominio por el tuyo. Para guardar el archivo en nano pulsa <kbd>Ctrl</kbd> + <kbd>O</kbd> y luego <kbd>Enter</kbd>.\
Para salir del editor pulsa <kbd>Ctrl</kbd> + <kbd>X</kbd>.

```nginx
server {
    # Aceptamos peticiones HTTP normales por IPv4 e IPv6
    listen 80;
    listen [::]:80;

    # Dominio del sitio, con www y sin www
    server_name example.com www.example.com;

    # Carpeta con los archivos del sitio y página principal
    root /var/www/example.com;
    index index.html index.php;

    # Registros propios para este sitio
    access_log /var/log/nginx/example.com-access.log;
    error_log  /var/log/nginx/example.com-error.log;

    # Tamaño máximo de archivo que se puede subir al sitio
    client_max_body_size 100M;

    location / {
        # Servimos el archivo o la carpeta y, si no existen, un error 404
        try_files $uri $uri/ =404;
    }
}
```

Un archivo en `sites-available` no hace nada por sí solo. Nginx solo lee la carpeta `sites-enabled`, así que activa el sitio con un enlace al archivo. De paso, desactiva el sitio por defecto de Nginx para que al entrar por la dirección IP se abra el tuyo.

```bash
# Activamos nuestro sitio
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

# Desactivamos el sitio por defecto con la página de bienvenida
rm /etc/nginx/sites-enabled/default

# Comprobamos que la configuración no tiene errores
nginx -t
```

Si `nginx -t` muestra `syntax is ok` y `test is successful`, no hay errores.

<figure><img src="https://docs.f3cloud.com/img/nginx-test.png" alt="Comprobación correcta de la configuración con nginx -t"><figcaption><p>La comprobación de la configuración ha ido bien</p></figcaption></figure>

Aplica la configuración. El comando `reload` vuelve a leer la configuración sin detener el sitio.

```bash
systemctl reload nginx
```

Ahora, en la dirección del servidor se abrirá tu página «¡El sitio funciona!».

> **Comprueba siempre la configuración antes de recargar.**
>
> Acostúmbrate a ejecutar `nginx -t` después de cada cambio en la configuración. Si el archivo tiene un error, Nginx no podrá reiniciarse y el sitio dejará de abrirse.

***

### 4. Conecta PHP

Para sitios hechos en PHP, como WordPress, instala **PHP-FPM**. Es el servicio que ejecuta los scripts PHP cuando Nginx se lo pide.

```bash
# Instalamos PHP-FPM
apt install -y php-fpm

# Vemos la versión de PHP
php -v

# Vemos cómo se llama el archivo para comunicarse con PHP
ls /run/php/
```

<figure><img src="https://docs.f3cloud.com/img/nginx-php-fpm.png" alt="Versión de PHP y archivos de la carpeta /run/php"><figcaption><p>PHP 8.2 está instalado y la comunicación va por php8.2-fpm.sock</p></figcaption></figure>

En Debian 12 se instala PHP 8.2, y en las versiones recientes de Ubuntu será más nueva. Apunta el nombre del archivo que termina en `.sock`, por ejemplo `php8.2-fpm.sock`.

Abre la configuración del sitio con `nano /etc/nginx/sites-available/example.com` y añade dos bloques antes de la última llave de cierre `}`.

```nginx
    # Pasamos los archivos PHP a PHP-FPM para que los ejecute.
    # Indica el nombre del archivo .sock que mostró el comando ls /run/php/
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }

    # Bloqueamos el acceso a los archivos de servicio .htaccess
    location ~ /\.ht {
        deny all;
    }
```

Comprueba la configuración y aplícala.

```bash
nginx -t && systemctl reload nginx
```

Para asegurarte de que PHP funciona, crea un archivo de prueba.

```bash
# Creamos una página con información sobre PHP
echo '<?php phpinfo();' > /var/www/example.com/info.php
```

Abre `http://IP-de-tu-servidor/info.php`. Debería aparecer una página con la versión de PHP, y en la línea **Server API** pondrá `FPM/FastCGI`.

<figure><img src="https://docs.f3cloud.com/img/nginx-phpinfo.png" alt="Página phpinfo con la versión PHP 8.2"><figcaption><p>PHP funciona a través de PHP-FPM</p></figcaption></figure>

> **Borra el archivo de prueba.**
>
> La página `info.php` muestra detalles del servidor que no conviene dejar a la vista de todos. Cuando termines la comprobación, bórrala con `rm /var/www/example.com/info.php`.

La mayoría de los sitios necesitan módulos de PHP adicionales. Por ejemplo, para WordPress instala estos.

```bash
# Módulos para bases de datos MySQL y para trabajar con imágenes, archivos comprimidos y peticiones
apt install -y php-mysql php-curl php-gd php-mbstring php-xml php-zip

# Reiniciamos PHP-FPM para que se carguen los módulos
systemctl restart php8.2-fpm
```

***

### 5. Conecta un certificado SSL

El certificado gratuito de Let's Encrypt lo emite el programa **Certbot**. Antes de empezar, asegúrate de que el registro A del dominio ya apunta a la dirección IP del servidor y de que el sitio se abre con el dominio por `http://`.

```bash
# Instalamos Certbot y su módulo para Nginx
apt install -y certbot python3-certbot-nginx

# Emitimos el certificado para el dominio con www y sin www
certbot --nginx -d example.com -d www.example.com
```

Certbot te pedirá un correo para los avisos y que aceptes las condiciones de Let's Encrypt. Después emitirá el certificado él solo, añadirá HTTPS a la configuración del sitio y activará la redirección de `http://` a `https://`.

<figure><img src="https://docs.f3cloud.com/img/ssl-nginx-issue.png" alt="Emisión correcta del certificado con certbot --nginx"><figcaption><p>El certificado está emitido y conectado a Nginx</p></figcaption></figure>

Los certificados de Let's Encrypt duran poco, pero no hace falta renovarlos a mano. Certbot ya ha configurado la renovación automática, y puedes comprobarla con el comando de abajo.

```bash
# Renovación de prueba, el certificado no cambia
certbot renew --dry-run
```

Explicamos con más detalle cómo emitir certificados, también para Apache, en un [artículo aparte](https://docs.f3cloud.com/es/software-setup/lets-encrypt-ssl-nginx-apache.md).

***

### Si en el servidor hay Apache

Nginx y Apache no pueden funcionar a la vez en el puerto 80. Comprueba qué programa lo está usando.

```bash
# Mostramos quién escucha en el puerto 80
ss -tlnp | grep ':80 '
```

Si en la respuesta aparece `apache2` y no necesitas Apache, detenlo y desinstálalo, y luego inicia Nginx.

```bash
# Detenemos Apache y lo desinstalamos junto con su configuración
systemctl stop apache2
apt purge -y apache2

# Iniciamos Nginx
systemctl start nginx
```

***

### Cómo desinstalar Nginx

```bash
# Detenemos Nginx
systemctl stop nginx

# Desinstalamos Nginx junto con su configuración
apt purge -y nginx nginx-common

# Eliminamos los paquetes que ya no hacen falta
apt autoremove -y
```

Los archivos de los sitios en la carpeta `/var/www` se quedarán donde están.

***

### Preguntas frecuentes

<details>

<summary>nginx -t dice test failed</summary>

Hay un error en la configuración, y Nginx te indica dónde exactamente. Por ejemplo, el mensaje `invalid number of arguments in "root" directive in /etc/nginx/sites-enabled/example.com:7` significa que en la línea 7 del archivo algo falla en la directiva `root`. Lo más habitual es que falte un punto y coma al final de una línea o que sobre una llave.

</details>

<details>

<summary>En lugar de mi sitio se abre la página de bienvenida de Nginx</summary>

Lo más probable es que el sitio por defecto no esté desactivado o que el dominio en `server_name` no esté escrito igual que como lo abres en el navegador. Comprueba que en la carpeta `/etc/nginx/sites-enabled` no hay ningún archivo `default` y ejecuta `nginx -t && systemctl reload nginx`.

</details>

<details>

<summary>Error 502 Bad Gateway</summary>

Nginx no consigue pasar la petición a PHP-FPM. Comprueba que el servicio funciona con `systemctl status php8.2-fpm` y compara el nombre del archivo en `fastcgi_pass` con lo que muestra `ls /run/php/`. Los detalles del error están en el registro del sitio, por ejemplo `/var/log/nginx/example.com-error.log`.

</details>

<details>

<summary>Error 403 Forbidden</summary>

Nginx no ha encontrado la página principal o no puede leer los archivos. Asegúrate de que en la carpeta del sitio hay un `index.html` o un `index.php` y restablece los permisos con `chown -R www-data:www-data /var/www/example.com`.

</details>

<details>

<summary>Error 413 Request Entity Too Large al subir un archivo</summary>

El archivo supera el tamaño permitido.\
Aumenta `client_max_body_size` en la configuración del sitio.\
En los sitios con PHP, sube también `upload_max_filesize` y `post_max_size` en el archivo `/etc/php/8.2/fpm/php.ini`, porque por defecto solo permiten 2 y 8 MB. Después reinicia PHP-FPM y Nginx.

</details>

<details>

<summary>El navegador descarga el archivo PHP en vez de abrir la página</summary>

En la configuración del sitio falta el bloque `location ~ \.php$` o se te ha olvidado aplicar los cambios. Añade el bloque del paso 4 y ejecuta `nginx -t && systemctl reload nginx`. Después borra la caché del navegador.

</details>

***

### Nuestros recursos

**Canal de Telegram:** [https://t.me/f3cloud_news](https://t.me/f3cloud_news)\
**Web del hosting:** [https://f3cloud.com](https://f3cloud.com/es)
