Cada vez que escribes una dirección en tu navegador, como “todoplantas.net”, ocurre una conversación invisible entre tu ordenador y un servidor web en algún lugar del mundo. Ese servidor es un programa que escucha en el puerto 80 (HTTP) o 443 (HTTPS), recibe la petición, busca el archivo solicitado o ejecuta un programa, y devuelve una respuesta (con el contenido HTML, imágenes, CSS, JavaScript). El protocolo HTTP define el formato de ese diálogo: verbos como GET o POST, códigos de estado como 200 OK, 404 Not Found o 500 Internal Server Error. Te explico cómo funciona por dentro un servidor web, las diferencias entre Apache y Nginx, y cómo se procesa una petición PHP o Python.
¿Qué es un servidor web? Hardware vs software
En el mundo de las redes, “servidor” puede referirse a dos cosas: la máquina física (un ordenador potente con muchos núcleos y RAM) o el software que corre en esa máquina y sirve contenido web. El servidor web es el programa (Apache, Nginx, IIS, Caddy, Lighttpd) que acepta peticiones HTTP de los clientes (navegadores, APIs, bots) y responde con el contenido solicitado (archivos estáticos o respuestas dinámicas).
Componentes clave:
- Dirección IP y puerto: el servidor web se “enlaza” a una o varias direcciones IP y a un puerto (80 para HTTP, 443 para HTTPS). Escucha permanentemente conexiones TCP entrantes.
- Directorio raíz (DocumentRoot): carpeta en el sistema de archivos donde residen los archivos públicos del sitio web (index.html, styles.css, etc.).
- Módulos o extensión: para soportar lenguajes dinámicos (PHP, Python), compresión, seguridad, etc.
- Archivos de configuración: definen reglas de reescritura de URL, autenticación, virtual hosts, redirecciones, etc.
El hardware subyacente puede ser un servidor dedicado (físico) en un centro de datos, una máquina virtual en la nube (AWS EC2, Google Compute Engine), o incluso un ordenador de escritorio (para pruebas locales). En producción, se usan servidores robustos con muchas CPUs, RAM y almacenamiento rápido (SSD).
Virtual Hosting (alojamiento virtual)
Un mismo servidor web puede alojar múltiples sitios web en la misma IP gracias a los “virtual hosts” (Apache) o “server blocks” (Nginx). El servidor identifica qué sitio se está pidiendo por el nombre de dominio en la cabecera “Host” de la petición. Por eso puedes tener todoplantas.net y otrodominio.com en el mismo servidor.
Protocolo HTTP: peticiones GET y POST, cabeceras, cuerpo
HTTP (HyperText Transfer Protocol) es un protocolo de capa de aplicación basado en TCP/IP. Funciona con un modelo petición-respuesta. El cliente (navegador) envía una petición al servidor; el servidor envía una respuesta. Todo el intercambio es texto plano (aunque HTTPS lo cifra).
Una petición HTTP típica (versión 1.1) tiene este formato:
GET /carpeta/archivo.html HTTP/1.1 Host: www.todoplantas.net User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Accept: text/html,application/xhtml+xml,... Accept-Language: es-ES,es;q=0.9 Connection: keep-alive (una línea en blanco)
El método más común es GET (solicitar un recurso). También existe POST (enviar datos al servidor, por ejemplo, desde un formulario), PUT, DELETE, etc. La línea de petición incluye: método, ruta y versión HTTP. Las cabeceras (Host, User-Agent, Accept, etc.) proporcionan metadatos. Si la petición lleva datos (POST), después de la línea en blanco viene el cuerpo (body).
Ejemplo de respuesta HTTP:
HTTP/1.1 200 OK Date: Mon, 28 Apr 2025 10:00:00 GMT Server: Apache/2.4.41 (Ubuntu) Content-Type: text/html; charset=utf-8 Content-Length: 1234 (una línea en blanco) <!DOCTYPE html>...
La respuesta también tiene una línea de estado con código y frase (200 OK), cabeceras, cuerpo HTML (o contenido binario).
Códigos de estado HTTP: 200, 301, 404, 500 y sus familias
Los códigos de estado indican el resultado de la petición. Se agrupan en familias:
- 1xx (Informativo): raramente vistos por el usuario (100 Continue).
- 2xx (Éxito): 200 OK (petición exitosa), 201 Created (recurso creado), 204 No Content (sin cuerpo).
- 3xx (Redirección): 301 Moved Permanently (redirección permanente), 302 Found (temporal), 304 Not Modified (caché válida).
- 4xx (Error del cliente): 400 Bad Request (petición mal formada), 403 Forbidden (acceso denegado), 404 Not Found (recurso no existe), 429 Too Many Requests (límite de tasa).
- 5xx (Error del servidor): 500 Internal Server Error (ej. fallo de script), 502 Bad Gateway (servidor upstream falló), 503 Service Unavailable (sobrecarga o mantenimiento).
Los servidores web pueden configurar páginas de error personalizadas (p.ej. una página HTML amigable para 404).
Apache HTTP Server: el servidor modular que dominó la web
Apache, lanzado en 1995, es el servidor web más popular durante décadas (aunque desde ~2016 Nginx superó Apache en número de sitios activos). Su arquitectura se basa en procesos o hilos: cada conexión entrante recibe un proceso hijo o un hilo (modelo MPM: prefork (procesos), worker (híbrido), event).
Apache es altamente configurable mediante módulos dinámicos que se cargan en tiempo real en httpd.conf o .htaccess. Módulos comunes:
- mod_rewrite: reglas de reescritura de URL (para crear URLs amigables).
- mod_proxy: actuar como proxy inverso o forward.
- mod_ssl: habilitar HTTPS con OpenSSL.
- mod_php (o PHP-FPM): procesar scripts PHP.
- mod_security: firewall de aplicaciones web.
Ventajas de Apache: flexibilidad, soporte masivo de documentación, .htaccess (permite cambios por directorio sin reiniciar). Desventaja: consumo de memoria por cada proceso, lo que limita el número de conexiones simultáneas (muchos procesos pesados).
Apache se utiliza a menudo con un proxy detrás de Nginx (Nginx como frontend que maneja las conexiones y Apache procesa el contenido dinámico).
Nginx: arquitectura asíncrona y alto rendimiento para miles de conexiones
Nginx (pronunciado “Engine X”) fue creado por Igor Sysoev en 2004 para resolver el problema C10K (manejar 10.000 conexiones simultáneas). Su arquitectura es asíncrona, manejada por eventos (similar a Node.js). En lugar de un proceso por conexión, Nginx usa un número fijo de trabajadores (workers), cada uno usando un bucle de eventos que atiende muchas conexiones concurrentes de manera no bloqueante. Esto hace que consuma muy poca memoria incluso con decenas de miles de conexiones.
Nginx es ideal para servir archivos estáticos (HTML, CSS, JS, imágenes) y como proxy inverso (balanceador de carga) ante servidores de aplicaciones (Apache, Gunicorn, Node.js, PHP-FPM). También funciona como load balancer, cache de contenidos (caché de respuestas), y TLS terminator.
Configuración típica en Nginx (/etc/nginx/nginx.conf y bloques server). Soporta reescritura, autenticación básica, limitación de tasa, etc. No permite .htaccess (toda la configuración está en archivos centrales), pero ofrece muy alto rendimiento.
Otros servidores menos comunes: Lighttpd (similar a Nginx), Caddy (con HTTPS automático), IIS (de Microsoft, para .NET), OpenLiteSpeed.
Proxy inverso: ¿qué es y para qué sirve?
Un proxy inverso es un servidor que está delante de otros servidores. El cliente se conecta al proxy, este reenvía la petición al servidor de backend (Tomcat, Express, Gunicorn, etc.), obtiene la respuesta y la devuelve al cliente. Beneficios: balanceo de carga, terminar conexiones TLS, caché, compresión, ocultar la infraestructura interna. Nginx es excelente para esto.
Flujo de una petición: desde el socket hasta la respuesta
Vamos a ver paso a paso qué sucede dentro cuando un servidor web recibe una petición:
El servidor web también registra la transacción en un archivo log (access.log) y si hubo errores, en error.log.
Servidores dinámicos: CGI, PHP-FPM, WSGI, y cómo se conectan con Apache/Nginx
Para generar contenido dinámico (PHP, Python, Ruby, Node.js), el servidor web necesita comunicarse con un intérprete o un proceso externo. Los mecanismos más usados:
- CGI (Common Gateway Interface): antiguo, el servidor web lanza un proceso por cada petición, lo que es muy ineficiente. Hoy casi no se usa.
- PHP-FPM (FastCGI Process Manager): protocolo FastCGI. Un proceso permanente (pool de trabajadores) escucha en un socket Unix o TCP. Apache mediante
mod_proxy_fcgio Nginx confastcgi_passenvían la petición a PHP-FPM. PHP-FPM ejecuta el script y devuelve la salida. Es eficiente y soporta opcache. - WSGI (Web Server Gateway Interface) en Python: aplicaciones Python (Django, Flask) se ejecutan con servidores WSGI como Gunicorn, uWSGI o mod_wsgi. Nginx/Apache hacen proxy a Gunicorn (socket).
- Proxy inverso a Node.js: Nginx redirige las solicitudes de una ubicación específica (ej. /api) al puerto donde escucha Node.js (Express), que genera la respuesta.
Ejemplo de configuración Nginx con PHP-FPM:
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
Para Python (Gunicorn):
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
}