Un servidor web con nginx
Módulo 7: Dominio, servidor web y https · Tiempo de lectura: 12 minutos
Objetivo de aprendizaje: Después de esta lección podrá instalar nginx, configurar un sitio web y un proxy inverso con un server block, probar y recargar una configuración de forma segura y ajustar correctamente los permisos de su webroot.
Conceptos clave: nginx, server block, sites-available y sites-enabled, conf.d, listen, server_name, root, index, try_files, default server, nginx -t, reload, proxy inverso, proxy_pass, Host, X-Forwarded-For, X-Forwarded-Proto, webroot, PHP-FPM
Qué hace un servidor web
Un servidor web escucha en el puerto 80 (http) y 443 (https), recibe las peticiones de los navegadores y devuelve algo: un archivo del disco (un sitio estático) o la respuesta de un programa que funciona detrás (PHP, una aplicación Node.js, un contenedor). En el segundo caso, el servidor web se denomina proxy inverso (reverse proxy): está delante, se encarga del https y pasa la petición a la aplicación, que solo escucha en 127.0.0.1.
En Linux, nginx y Apache son los servidores web más conocidos, y Caddy (lección 7.4) es una alternativa moderna que gestiona los certificados por sí misma. Esta lección utiliza nginx: está en todas las distribuciones, consume poca memoria y es el estándar en muchas guías.
Instalación y primer vistazo
anna@web1:~$ sudo apt install nginx
anna@web1:~$ systemctl status nginx
anna@web1:~$ curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.26.3
Content-Type: text/html(El número de versión es un ejemplo.) No olvide el firewall: los puertos 80 y 443 deben estar abiertos (lección 5.2). Si ahora visita http://192.0.2.10, verá la página de bienvenida de nginx.
La configuración se encuentra en /etc/nginx/:
| Ruta | Qué contiene |
|---|---|
nginx.conf | archivo principal; normalmente no se toca |
sites-available/ | un archivo por sitio (Debian y Ubuntu) |
sites-enabled/ | enlaces (symlinks) a los sitios activos |
conf.d/*.conf | ajustes sueltos que siempre se cargan |
snippets/ | fragmentos que reutiliza en varios sitios |
sites-available y sites-enabled son una costumbre de Debian y Ubuntu: así activa o desactiva un sitio creando o quitando un enlace, sin borrar el archivo.
Un primer sitio
Cree una carpeta para el sitio y una página de prueba:
anna@web1:~$ sudo mkdir -p /var/www/example.com
anna@web1:~$ echo '<h1>Het werkt</h1>' | sudo tee /var/www/example.com/index.htmlDespués cree un server block: la descripción de un sitio.
# /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}Léalo así:
listen 80;ylisten [::]:80;hacen que nginx escuche en IPv4 y también en IPv6. Si olvida la segunda línea, su registro AAAA no funcionará (lección 7.1).server_nameindica para qué nombres vale este bloque. En cada petición, nginx mira el nombre que pide el navegador (la cabecera Host) y elige el bloque que corresponde.rootes la carpeta con los archivos yindexel archivo que se muestra para una carpeta.try_filesintenta servir el archivo solicitado, luego una carpeta, y si no, devuelve un 404. Sin una línea así, una configuración incorrecta puede mostrar más de lo que usted desea.- Tener archivos de registro propios por sitio facilita mucho la búsqueda (lección 6.2).
Active el sitio, quite el sitio predeterminado, pruebe y recargue:
anna@web1:~$ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
anna@web1:~$ sudo rm /etc/nginx/sites-enabled/default
anna@web1:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
anna@web1:~$ sudo systemctl reload nginx
anna@web1:~$ curl -I http://example.com
HTTP/1.1 200 OKConvierta nginx -t antes de cada recarga en un hábito fijo. Si hay un error, le indica qué archivo y qué línea, y su sitio en funcionamiento no se ve afectado. Si reinicia sin probar, nginx no volverá a arrancar con un error y todos sus sitios quedarán caídos (lección 6.1).
El default server: ¿qué recibe un nombre desconocido?
¿Qué ocurre si alguien solicita su servidor con un nombre que no figura en ningún server_name, o simplemente con la dirección IP? En ese caso nginx elige el default server: el bloque que tiene default_server detrás de listen o, si no lo hay, el primer bloque que encontró. Si no lo piensa, será por tanto uno de sus sitios reales.
Es más limpio un bloque aparte que rechace esas peticiones:
# /etc/nginx/sites-available/000-default
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}444 es un código especial de nginx: la conexión se cierra sin respuesta. Así, los escáneres que recorren direcciones IP no ven nada. Para https (puerto 443), un default server funciona algo distinto porque necesita un certificado; volverá sobre ello en la lección 7.3.
nginx como proxy inverso
Si hay una aplicación en 127.0.0.1:3000 (lección 6.3) o un contenedor en 127.0.0.1:3001 (lección 9.3), nginx la publica hacia fuera:
server {
listen 80;
listen [::]:80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Las cuatro líneas proxy_set_header son importantes. Sin Host, la aplicación no sabe con qué nombre se la visita. Sin X-Forwarded-For, la aplicación ve que cada visita viene de 127.0.0.1 (el proxy) en lugar de la dirección real del visitante. Sin X-Forwarded-Proto, la aplicación cree que todo va por http y a veces genera enlaces o cookies para http, aunque su sitio funcione con https. Muchas aplicaciones tienen un ajuste para confiar en estas cabeceras («trusted proxy»); ponga ahí solo 127.0.0.1, porque de lo contrario cualquier visitante podría enviar una dirección falsa.
Las aplicaciones que usan websockets (actualizaciones en directo, como Uptime Kuma) necesitan dos líneas más: proxy_http_version 1.1; y el reenvío de Upgrade y Connection. La documentación de la aplicación suele indicar exactamente cuáles.
Permisos del webroot
En Debian y Ubuntu, nginx ejecuta sus procesos de trabajo como el usuario www-data. Este debe poder leer sus archivos, pero no debe poder escribirlos. Una buena distribución (lección 3.1):
anna@web1:~$ sudo chown -R anna:www-data /var/www/example.com
anna@web1:~$ sudo find /var/www/example.com -type d -exec chmod 750 {} \;
anna@web1:~$ sudo find /var/www/example.com -type f -exec chmod 640 {} \;Usted (anna) gestiona los archivos, el grupo www-data puede leer y el resto, nada. Si el sitio necesita escribir en algún sitio, como una carpeta de subidas, dé permisos de escritura a www-data solo en esa carpeta. Nunca chmod 777 (lección 10.2). Si recibe un 403 Forbidden, consulte el registro de errores del sitio: allí aparece permission denied con la ruta.
Algunos hábitos más:
- Nada de secretos en el webroot. Las copias de seguridad (
site.zip), los archivos.envy las carpetas.gitno deben estar ahí; si se colocan por error, cualquiera puede solicitarlos. Una red de seguridad adicional:location ~ /\. { deny all; }bloquea todos los archivos que empiezan por un punto (salvo lo que permita expresamente, como/.well-known/, véanse las lecciones 7.3 y 7.4). - Ocultar la versión.
server_tokens off;ennginx.confelimina el número de versión de la cabeceraServery de las páginas de error. No es seguridad real, pero da menos información a los escáneres.
PHP, en breve
Para sitios PHP (como WordPress), nginx se comunica con PHP-FPM, un servicio aparte. En Debian instala php-fpm y añade en el server block un bloque location ~ \.php$ con include snippets/fastcgi-php.conf; y fastcgi_pass unix:/run/php/php8.4-fpm.sock; (el número de versión varía según la versión de la distribución). El curso de WordPress profundiza en ello.
En AlmaLinux y Rocky Linux
Allí no existe sites-available: cada sitio se coloca como archivo propio en /etc/nginx/conf.d/<naam>.conf. nginx se ejecuta como el usuario nginx en lugar de www-data, y el webroot predeterminado es /usr/share/nginx/html. SELinux no permite por defecto que nginx se conecte con una aplicación detrás de proxy_pass; actívelo con setsebool -P httpd_can_network_connect 1. Los archivos fuera de las carpetas habituales necesitan una etiqueta SELinux (semanage fcontext y restorecon).
Resumen
- nginx sirve archivos o, como proxy inverso, pasa las peticiones a una aplicación en
127.0.0.1. - Un server block por sitio en
sites-available, activado con un enlace ensites-enabled; escuche en80y también en[::]:80. - Siempre
nginx -tantes desystemctl reload nginx. - Un default server propio con
return 444evita que un nombre desconocido o la dirección IP sola muestre uno de sus sitios. - Como proxy inverso, reenvíe
Host,X-Forwarded-ForyX-Forwarded-Proto; el webroot debe ser legible parawww-data, no modificable y sin secretos.
Cuestionario
Ejercicio
Ejercicio O7.2: Su primer sitio. Instale nginx (o use Caddy de la lección 7.4) y cree un server block para un (sub)dominio que apunte a su servidor, con listen para IPv4 e IPv6, archivos de registro propios y un default server propio. Pruebe con nginx -t, recargue y compruebe con curl -I por IPv4 e IPv6. Ajuste los permisos del webroot como en la lección. Rellene la lista de comprobación y pegue su server block.
Ejercicio O7.2: Su primer sitio
Este ejercicio lo hace usted mismo; nadie lo revisa. Marque lo que haya hecho y señale el ejercicio como realizado.
En la IP sin nombre, nada (conexión cerrada) o una página neutra, nunca el sitio de un cliente. Solo una carpeta de subidas con permiso de escritura para www-data, el resto de solo lectura. Detrás de un proxy: Host, X-Real-IP, X-Forwarded-For y X-Forwarded-Proto.
Sus marcas y notas se quedan solo en este navegador; no las enviamos a ningún sitio. Si ha iniciado sesión, en Mis cursos solo guardamos que ha realizado el ejercicio.
Para saber más
- Prohibido (403): No tiene permiso para acceder a / en este servidor
- Documentación de nginx, How nginx processes a request (server_name y default server): https://nginx.org/en/docs/http/request_processing.html
- Documentación de nginx, Beginner's Guide: https://nginx.org/en/docs/beginners_guide.html
- Documentación de nginx,
ngx_http_proxy_module: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
