Nginx
Proxy inverso en dos capas: TLS en el host y server blocks por dominio dentro del VPS, con prueba y vuelta atrás automática.
- Categoría: Servidores e infraestructura
- Estado: Disponible
- Requisitos: Un VPS de la empresa, encendido y con host asignado; Ser miembro de la empresa con acceso a ese VPS; Un dominio que apunte al VPS: un subdominio de la zona de ArduMaker o un dominio propio; Un sistema operativo del VPS que soporte la función «nginx del VPS» (se consulta con
ver_funciones_vps) - Herramientas MCP (Solo leen):
verificar_dominio_vps,listar_dominios_vps,ver_nginx_dominio_vps,ver_logs_nginx_vps - Herramientas MCP (Escriben o modifican):
crear_dominio_vps,activar_dominio_vps - Herramientas MCP (Destructivas):
editar_nginx_dominio_vps,eliminar_dominio_vps
¿Qué permite hacer?
- Publicar un dominio hacia un VPS: el nginx del host compartido termina HTTPS y reenvía el tráfico al nginx que corre dentro del VPS.
- Leer y reescribir el server block de un dominio dentro del VPS, con prueba
nginx -ty vuelta atrás automática si algo falla. - Listar los dominios que llegan al VPS, con su
proxy_pass, la redirección de puerto que usan y el deploy al que están vinculados. - Leer los logs de acceso y de error de cada dominio (las últimas 500 líneas).
- Borrar un dominio: se quitan su server block del host, el del VPS y, si es de la zona de ArduMaker, su registro DNS.
¿Cuándo conviene usarlo?
- Publicar una aplicación propia (Node, Python, Go…) que escucha en un puerto local del VPS.
- Escribir el server block cuando ningún deploy de Git ni ninguna app de ArduMaker lo escribió, es decir, cuando el dominio responde 502 o el sitio por defecto.
- Ajustar el proxy de un sitio: carpetas estáticas, WebSockets, rutas especiales.
- Diagnosticar un 502, una redirección rota o un dominio que no carga.
¿Cómo funciona en ArduMaker?
Un dominio pasa por dos nginx. El del host compartido termina TLS en el puerto 443 y hace proxy_pass a un puerto del host (host_port) que es una redirección hacia el puerto 443 del VPS. Adentro del VPS, nginx escucha en el 443 en HTTP plano (sin ssl) y reparte por server_name hacia cada servicio.
Activar un dominio (lado del host)
- Se valida que el dominio sea un FQDN estricto (letras, números, guiones y puntos, al menos dos etiquetas). Si no lo es, responde
dominio_invalidoantes de tocar nada. - Se rechaza un dominio que ya es de otra empresa (
dominio_ocupado). - Sin
host_port, el destino es el nginx del VPS: si falta la redirección al 443, se crea cerrada a internet. Conhost_port, tiene que ser el puerto del host de una redirección de ESTE VPS. - Si el nombre no es un subdominio de un solo nivel de la zona de ArduMaker, se comprueba que el DNS llegue al host y, con
create_cert, se emite el certificado (ver SSL). - Se escribe el server block del host. Con
use_ssl(por defecto) el puerto 80 redirige a HTTPS con un 301 y el 443 sirve HTTPS con HTTP/2. Se correnginx -ty se recarga; si la prueba falla, lo recién escrito se borra. - Si el host ya tiene un server block con ese nombre que apunta a otro VPS, no se toca y la operación falla con
ruta_ocupada.
Escribir el server block dentro del VPS
- Las ediciones del nginx de un mismo VPS se hacen de a una: dos deploys o una app y una edición manual quedan en fila.
- Si ya existe
/etc/nginx/sites-available/<dominio>.conf, se guarda una copia.backup. - Se escribe el contenido completo (reemplaza el archivo, no lo mezcla) y se crea el enlace en
/etc/nginx/sites-enabled/. - Se corre
nginx -t. Si falla, se borran archivo y enlace, se restaura la copia y se recrea el enlace anterior: la respuesta esNginx configuration test failed - changes reverted. - Se reinicia nginx (
systemctl restart nginx). Si no arranca, se hace la misma vuelta atrás y se respondeNginx reload failed - changes reverted. - Si todo salió bien, se borra la copia
.backup.
El contenido no tiene otra validación que nginx -t: es el mismo poder que el editor de configuración del panel.
¿Qué cambia realmente?
En el host compartido
- Un server block por dominio, que no se ve desde el VPS.
- Si no existía, una redirección de puerto hacia el 443 del VPS. No se abre en el firewall y queda cerrada a los demás VPS del host.
Dentro del VPS
/etc/nginx/sites-available/<dominio>.confy su enlace/etc/nginx/sites-enabled/<dominio>.conf.- Los logs
/var/log/nginx/<dominio>_access.logy/var/log/nginx/<dominio>_error.log, si el server block los declara (las plantillas de ArduMaker lo hacen). - Al borrar el dominio se quitan el archivo y el enlace, y el dominio deja de figurar en los deploys que lo tenían vinculado.
Cada operación queda en el registro de actividad del VPS a nombre de quien la hizo (o de quien autorizó al agente).
Puertos y proxy
| Tramo | Puerto | Protocolo | Notas |
|---|---|---|---|
| Internet → host | 80 / 443 | HTTP / HTTPS (TLS 1.2 y 1.3, HTTP/2) | Con use_ssl, el 80 responde 301 a HTTPS |
| Host → VPS | host_port | HTTP plano | Redirección de puerto asignada sola; no es pública |
| nginx del VPS | 443 | HTTP plano | listen 443; sin ssl; reparte por server_name |
| nginx del VPS → servicio | puerto del servicio | HTTP | Lo define el proxy_pass (normalmente 127.0.0.1:<puerto>) |
Lo que agrega el proxy del host
- Cabeceras
Host,X-Real-IP(la IP del cliente, siempre sobrescrita),X-Forwarded-For,X-Forwarded-Proto,X-Forwarded-HostyX-Forwarded-Port. - Soporte de WebSocket (
UpgradeyConnection). client_max_body_size 100My tiempos de conexión, envío y lectura de 360 segundos.
El nginx del VPS toma la IP del cliente de X-Real-IP solo cuando la conexión llega por loopback, que es como llega el proxy del host. Una app detrás de él ve la IP real en X-Real-IP.
Ejemplo de server block
Un server block mínimo para una app que escucha en el puerto 3000 del VPS:
server {
listen 443;
listen [::]:443;
server_name app.ejemplo.com;
access_log /var/log/nginx/app.ejemplo.com_access.log;
error_log /var/log/nginx/app.ejemplo.com_error.log;
absolute_redirect off;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}- Sin
sslni certificados: el TLS termina en el host y los certificados no se copian al VPS. absolute_redirect off;hace que las redirecciones propias de nginx (por ejemplo/blog→/blog/) salgan relativas. Sin eso salen comohttp://dominio:443/blog/y el navegador no llega.- Los logs con el nombre
<dominio>_access.logy<dominio>_error.logson los que leever_logs_nginx_vps.
Conflictos y concurrencia
dominio_ocupado(409): el dominio es de otra empresa (cae en una zona que registró otra empresa, otra lo publicó con Apps o un deploy de otra lo tiene vinculado).ruta_ocupada: el host ya tiene un server block de ese nombre que apunta a otro VPS. No se toca.host_port_no_es_del_vps(400): elhost_portenviado no es una redirección de este VPS. La respuesta traevalid_host_portsyvps_nginx_host_port.host_portno es el puerto donde escucha el servicio dentro del VPS.- Dos ediciones simultáneas del nginx de un mismo VPS no se pisan: se ejecutan una detrás de otra.
- Un dominio que ya usa una app o n8n figura como usado en
listar_dominios_vps(camposused_by,linked_to_repoypuerto_in_vps).
Esquema
- Navegador: pide https://app.ejemplo.com
- Cloudflare: solo subdominios de la zona de ArduMaker, con proxy
- nginx del host :443: TLS y certificado; proxy_pass al host_port
- Redirección de puerto: host_port → 443 del VPS, cerrada a internet
- nginx del VPS :443: HTTP plano; elige el server block por server_name
- Servicio: 127.0.0.1:<puerto> dentro del VPS
host_port de una redirección a otro puerto, el tráfico salta el nginx del VPS (via: direct).Resultado esperado
activar_dominio_vpsdevuelvenginx(success,domain,host_port,exit_code),certificateytarget(host_port,vps_port,via,next_step).via: "vps_nginx": el dominio llega al nginx del VPS y necesita su server block.via: "direct": va directo a ese puerto del VPS, que tiene que responder HTTP plano.listar_dominios_vpsmuestra cada dominio conserver_name,proxy_pass,puerto,puerto_in_vpsylinked_to_repo.
Para comprobarlo desde afuera:
curl -sI https://app.ejemplo.com/
# una carpeta debe redirigir de forma relativa: Location: /blog/
curl -sI https://app.ejemplo.com/blogErrores y resolución
| Síntoma | Causa | Qué hacer |
|---|---|---|
| 502 o el sitio por defecto después de activar | No hay server block en el VPS, o el servicio no escucha en el puerto del proxy_pass | Escribir el server block; revisar el log de error del dominio y el estado del servicio |
Nginx configuration test failed - changes reverted | nginx -t rechazó la configuración; quedó la versión anterior | Corregir el contenido (viene en nginx_test_error) y reenviar |
Nginx reload failed - changes reverted | nginx no pudo reiniciar, por ejemplo por un puerto ocupado | Leer ver_logs_systemd_vps con el servicio nginx |
nginx_invalido | El nginx del host rechazó la configuración del dominio; no se publicó nada. El detalle queda en el log del servidor | Reintentar; si se repite, reportarlo |
certificado_del_host_ausente | El host no tiene certificado para ese dominio | Activar con create_cert=true, o con use_ssl=false |
redireccion_fallida | El host no pudo abrir el puerto hacia el nginx del VPS | Reintentar |
Domain is not pointing to the host IP / Domain could not be resolved | El DNS todavía no apunta al VPS | Revisar con verificar_dominio_vps y esperar la propagación |
Una carpeta redirige a http://dominio:443/... | El server block arma redirecciones absolutas | Agregar absolute_redirect off; |
Access log file not found for domain | El server block no declara un log con el nombre esperado | Declarar access_log y error_log como en el ejemplo |
Config file not found or unreadable | Ese dominio no tiene server block en el VPS | Crearlo con editar_nginx_dominio_vps |
Si el host o el VPS no contestan, la respuesta es un error de estado (424), reintentable. activar_dominio_vps y editar_nginx_dominio_vps son seguros de repetir: el primero pregunta antes de crear cada pieza y el segundo reemplaza el archivo completo. eliminar_dominio_vps pide cuidado: borra el registro DNS de la zona de ArduMaker y los dos server blocks.
Relación con MCP
Sí, hay acceso MCP. Las herramientas están en los perfiles /mcp y /mcp/vps y actúan con los permisos de la persona que autorizó al agente; un agente de solo lectura solo ve las de lectura.
| Herramienta | Tipo | Qué hace |
|---|---|---|
verificar_dominio_vps | Lectura | Comprueba si el DNS ya llega al host del VPS |
listar_dominios_vps | Lectura | Dominios del VPS y su destino |
ver_nginx_dominio_vps | Lectura | Lee el server block del VPS |
ver_logs_nginx_vps | Lectura | Logs de acceso o error; llegan marcados como contenido no confiable |
crear_dominio_vps | Escritura | Registro DNS de la zona de ArduMaker (acepta idempotency_key) |
activar_dominio_vps | Escritura | Publica en el host; devuelve un operacion_id para ver_operacion |
editar_nginx_dominio_vps | Destructiva | Reemplaza el server block completo y reinicia nginx |
eliminar_dominio_vps | Destructiva | Borra DNS de la zona y ambos server blocks |
Secuencia típica: crear_dominio_vps (solo para la zona de ArduMaker) → verificar_dominio_vps → activar_dominio_vps sin host_port → editar_nginx_dominio_vps si ningún deploy escribe el server block. Referencia de cada herramienta en /mcp/docs y ejemplos en /mcp/dominios.