Nginx es un servidor web de arquitectura orientada a eventos que sirve contenido estático con muy poco consumo de memoria y se usa mucho como proxy inverso y balanceador delante de aplicaciones. En este tutorial instalarás Nginx en Ubuntu 24.04, abrirás el firewall, publicarás un sitio en su propio server block, ajustarás la configuración global, activarás compresión y cabeceras de seguridad y lo protegerás con un certificado de Let's Encrypt.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo.
  • UFW activo con SSH permitido (sudo ufw allow OpenSSH).
  • Para el paso de HTTPS: un dominio (en esta guía, your_domain) con un registro DNS A que apunte a la IP pública del servidor, y opcionalmente otro para www.your_domain.
  • Ningún otro servidor web (por ejemplo Apache) escuchando en los puertos 80 y 443.

Paso 1: Instalar Nginx

La versión de Nginx de los repositorios de Ubuntu 24.04 (1.24) es estable y recibe parches de seguridad durante todo el ciclo de vida de la distribución. Es la opción recomendada para la mayoría de servidores:

sudo apt update
sudo apt install nginx

El servicio arranca y queda habilitado en el inicio. Compruébalo:

sudo systemctl status nginx --no-pager
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-09-24 10:20:41 UTC; 8s ago
nginx -v
nginx version: nginx/1.24.0 (Ubuntu)

Alternativa: repositorio oficial de nginx.org

Si necesitas una versión más reciente (por ejemplo para usar la directiva http2 on; o HTTP/3), puedes usar el repositorio de nginx.org en lugar del paquete de Ubuntu. Hazlo antes de instalar nginx o desinstala primero el paquete de Ubuntu.

sudo apt install curl gnupg2 ca-certificates lsb-release
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/nginx.gpg
echo "deb [signed-by=/etc/apt/keyrings/nginx.gpg] http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx

Paso 2: Abrir el firewall

Nginx registra tres perfiles de UFW: Nginx HTTP (puerto 80), Nginx HTTPS (443) y Nginx Full (ambos). Permite los dos puertos:

sudo ufw allow 'Nginx Full'
sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx Full                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx Full (v6)            ALLOW       Anywhere (v6)

Comprueba que el servidor responde:

curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Content-Type: text/html

Desde el navegador, http://your_server_ip muestra la página "Welcome to nginx!".

Paso 3: Conocer la estructura de configuración

RutaContenido
/etc/nginx/nginx.confConfiguración global: procesos, bloque http, includes
/etc/nginx/sites-available/Un archivo por sitio (server block)
/etc/nginx/sites-enabled/Enlaces simbólicos a los sitios activos
/etc/nginx/conf.d/Fragmentos que se cargan dentro del bloque http
/etc/nginx/snippets/Fragmentos reutilizables, como fastcgi-php.conf
/var/www/html/Raíz web del sitio por defecto
/var/log/nginx/access.log y error.log

La configuración de Nginx se organiza en contextos anidados: main (el nivel superior de nginx.conf), events, http, server (un sitio) y location (una ruta dentro del sitio). Una directiva definida en http se hereda en todos los server salvo que la redefinas.

Paso 4: Ajustar la configuración global

Abre el archivo principal:

sudo nano /etc/nginx/nginx.conf

Los valores de Ubuntu ya son razonables: worker_processes auto; crea un proceso por núcleo de CPU y worker_connections 768; limita las conexiones por proceso. Dentro del bloque http { ... }, cambia o añade estas directivas:

server_tokens off;
client_max_body_size 20m;
server_names_hash_bucket_size 64;
  • server_tokens off; oculta la versión en la cabecera Server y en las páginas de error.
  • client_max_body_size sube el límite de subida por defecto (1 MB), que provoca errores 413 en formularios con archivos.
  • server_names_hash_bucket_size 64; evita el error could not build server_names_hash con nombres de dominio largos. En Ubuntu ya aparece comentada: basta con quitar el #.

En el mismo bloque http, Ubuntu trae gzip on; pero con el resto de opciones comentadas, así que solo comprime HTML. Descomenta o añade estas líneas para comprimir también CSS, JavaScript, JSON y SVG:

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;

Guarda, comprueba la sintaxis y recarga:

sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Paso 5: Crear un server block para tu dominio

Crea el directorio del sitio con una página de prueba:

sudo mkdir -p /var/www/your_domain/html
sudo chown -R $USER:$USER /var/www/your_domain
nano /var/www/your_domain/html/index.html
<!DOCTYPE html>
<html lang="es">
<head><meta charset="utf-8"><title>your_domain</title></head>
<body><h1>El server block de your_domain funciona</h1></body>
</html>

Crea el archivo del sitio:

sudo nano /etc/nginx/sites-available/your_domain
server {
    listen 80;
    listen [::]:80;

    server_name your_domain www.your_domain;
    root /var/www/your_domain/html;
    index index.html;

    access_log /var/log/nginx/your_domain.access.log;
    error_log /var/log/nginx/your_domain.error.log;

    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ /\.(?!well-known) {
        deny all;
    }

    location ~* \.(css|js|png|jpg|jpeg|gif|svg|webp|woff2)$ {
        expires 30d;
        access_log off;
    }
}

Qué hace cada parte:

  • try_files busca el archivo o directorio pedido y devuelve 404 si no existe.
  • La location con /\. bloquea archivos ocultos como .git o .env, pero deja pasar /.well-known/, que Let's Encrypt necesita.
  • La última location indica al navegador que guarde en caché los recursos estáticos durante 30 días.

Activa el sitio con un enlace simbólico, desactiva el sitio por defecto y recarga:

sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

Comprueba la respuesta aunque el DNS no haya propagado todavía:

curl -i --resolve your_domain:80:127.0.0.1 http://your_domain
HTTP/1.1 200 OK
Server: nginx
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin

<h1>El server block de your_domain funciona</h1>

La cabecera Server ya no muestra la versión gracias a server_tokens off;.

Paso 6: Limitar la tasa de peticiones (opcional)

Si el sitio tiene un formulario de login o una API, limitar las peticiones por IP frena los ataques de fuerza bruta. Define una zona compartida en el contexto http creando un archivo en conf.d:

sudo nano /etc/nginx/conf.d/ratelimit.conf
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

Aplica el límite solo a la ruta sensible dentro del server block de your_domain:

location = /login {
    limit_req zone=login burst=5 nodelay;
    limit_req_status 429;
    try_files $uri $uri/ =404;
}

Sustituye try_files por lo que sirva realmente esa ruta en tu sitio (por ejemplo un proxy_pass o fastcgi_pass). Tras sudo nginx -t y sudo systemctl reload nginx, las peticiones que superen 5 por minuto (más una ráfaga de 5) recibirán un 429 Too Many Requests.

Paso 7: Añadir HTTPS con Let's Encrypt

Instala Certbot y su plugin para Nginx:

sudo apt install certbot python3-certbot-nginx

Solicita el certificado. Certbot localiza el server block por server_name, añade la configuración TLS y crea la redirección de HTTP a HTTPS:

sudo certbot --nginx -d your_domain -d www.your_domain

Comprueba la redirección y el acceso por HTTPS:

curl -I http://your_domain
curl -I https://your_domain
HTTP/1.1 301 Moved Permanently
Location: https://your_domain/

HTTP/1.1 200 OK
Server: nginx

El temporizador certbot.timer renueva el certificado antes de que caduque. Simula una renovación para confirmar que funcionará:

sudo certbot renew --dry-run

Paso 8: Revisar los logs

Sigue las peticiones del sitio en tiempo real:

sudo tail -f /var/log/nginx/your_domain.access.log

Consulta los errores recientes:

sudo tail -n 50 /var/log/nginx/your_domain.error.log

Para ver la configuración completa que Nginx está usando, con todos los include resueltos, ejecuta sudo nginx -T. Es la forma más rápida de encontrar una directiva duplicada.

Solución de problemas

nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use): otro servicio, normalmente Apache, ocupa el puerto. Compruébalo con sudo ss -tlnp | grep ':80 ' y detén ese servicio (sudo systemctl disable --now apache2) si no lo necesitas.

conflicting server name "your_domain" on 0.0.0.0:80, ignored: el mismo server_name aparece en dos server blocks activos. Búscalo con grep -r "server_name" /etc/nginx/sites-enabled/ y deja solo uno.

403 Forbidden: no hay archivo índice en el directorio o el usuario www-data no puede leer los archivos. namei -l /var/www/your_domain/html/index.html muestra los permisos de cada directorio de la ruta.

413 Request Entity Too Large: la subida supera client_max_body_size. Súbelo en el bloque http o solo en el server block afectado.

502 Bad Gateway: Nginx no puede conectar con el backend (PHP-FPM o una aplicación en proxy_pass). Comprueba que el servicio está activo y que la ruta del socket o el puerto coinciden; el log de errores indica cuál intentó usar.

Conclusión

Has instalado Nginx en Ubuntu 24.04, abierto el firewall, ajustado la configuración global, publicado un sitio con compresión, caché de estáticos y cabeceras de seguridad, y activado HTTPS con renovación automática. Como siguientes pasos puedes:

  • Alojar varios dominios en el mismo servidor siguiendo la guía de server blocks en Nginx.
  • Instalar PHP-FPM (php8.3-fpm) para servir aplicaciones PHP.
  • Usar Nginx como proxy inverso delante de una aplicación Node.js, Python o un contenedor Docker.