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

Markdown

¿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 -t y 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)

  1. 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_invalido antes de tocar nada.
  2. Se rechaza un dominio que ya es de otra empresa (dominio_ocupado).
  3. Sin host_port, el destino es el nginx del VPS: si falta la redirección al 443, se crea cerrada a internet. Con host_port, tiene que ser el puerto del host de una redirección de ESTE VPS.
  4. 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).
  5. 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 corre nginx -t y se recarga; si la prueba falla, lo recién escrito se borra.
  6. 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

  1. 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.
  2. Si ya existe /etc/nginx/sites-available/<dominio>.conf, se guarda una copia .backup.
  3. Se escribe el contenido completo (reemplaza el archivo, no lo mezcla) y se crea el enlace en /etc/nginx/sites-enabled/.
  4. Se corre nginx -t. Si falla, se borran archivo y enlace, se restaura la copia y se recrea el enlace anterior: la respuesta es Nginx configuration test failed - changes reverted.
  5. Se reinicia nginx (systemctl restart nginx). Si no arranca, se hace la misma vuelta atrás y se responde Nginx reload failed - changes reverted.
  6. 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>.conf y su enlace /etc/nginx/sites-enabled/<dominio>.conf.
  • Los logs /var/log/nginx/<dominio>_access.log y /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

TramoPuertoProtocoloNotas
Internet → host80 / 443HTTP / HTTPS (TLS 1.2 y 1.3, HTTP/2)Con use_ssl, el 80 responde 301 a HTTPS
Host → VPShost_portHTTP planoRedirección de puerto asignada sola; no es pública
nginx del VPS443HTTP planolisten 443; sin ssl; reparte por server_name
nginx del VPS → serviciopuerto del servicioHTTPLo 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-Host y X-Forwarded-Port.
  • Soporte de WebSocket (Upgrade y Connection).
  • client_max_body_size 100M y 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 ssl ni 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 como http://dominio:443/blog/ y el navegador no llega.
  • Los logs con el nombre <dominio>_access.log y <dominio>_error.log son los que lee ver_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): el host_port enviado no es una redirección de este VPS. La respuesta trae valid_host_ports y vps_nginx_host_port. host_port no 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 (campos used_by, linked_to_repo y puerto_in_vps).

Esquema

  1. Navegador: pide https://app.ejemplo.com
  2. Cloudflare: solo subdominios de la zona de ArduMaker, con proxy
  3. nginx del host :443: TLS y certificado; proxy_pass al host_port
  4. Redirección de puerto: host_port → 443 del VPS, cerrada a internet
  5. nginx del VPS :443: HTTP plano; elige el server block por server_name
  6. Servicio: 127.0.0.1:<puerto> dentro del VPS
Cómo llega una visita a tu servicio — Con un dominio propio sin proxy, la visita llega directo al host. Si al activar se elige un host_port de una redirección a otro puerto, el tráfico salta el nginx del VPS (via: direct).

Resultado esperado

  • activar_dominio_vps devuelve nginx (success, domain, host_port, exit_code), certificate y target (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_vps muestra cada dominio con server_name, proxy_pass, puerto, puerto_in_vps y linked_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/blog

Errores y resolución

SíntomaCausaQué hacer
502 o el sitio por defecto después de activarNo hay server block en el VPS, o el servicio no escucha en el puerto del proxy_passEscribir el server block; revisar el log de error del dominio y el estado del servicio
Nginx configuration test failed - changes revertednginx -t rechazó la configuración; quedó la versión anteriorCorregir el contenido (viene en nginx_test_error) y reenviar
Nginx reload failed - changes revertednginx no pudo reiniciar, por ejemplo por un puerto ocupadoLeer ver_logs_systemd_vps con el servicio nginx
nginx_invalidoEl nginx del host rechazó la configuración del dominio; no se publicó nada. El detalle queda en el log del servidorReintentar; si se repite, reportarlo
certificado_del_host_ausenteEl host no tiene certificado para ese dominioActivar con create_cert=true, o con use_ssl=false
redireccion_fallidaEl host no pudo abrir el puerto hacia el nginx del VPSReintentar
Domain is not pointing to the host IP / Domain could not be resolvedEl DNS todavía no apunta al VPSRevisar con verificar_dominio_vps y esperar la propagación
Una carpeta redirige a http://dominio:443/...El server block arma redirecciones absolutasAgregar absolute_redirect off;
Access log file not found for domainEl server block no declara un log con el nombre esperadoDeclarar access_log y error_log como en el ejemplo
Config file not found or unreadableEse dominio no tiene server block en el VPSCrearlo 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.

HerramientaTipoQué hace
verificar_dominio_vpsLecturaComprueba si el DNS ya llega al host del VPS
listar_dominios_vpsLecturaDominios del VPS y su destino
ver_nginx_dominio_vpsLecturaLee el server block del VPS
ver_logs_nginx_vpsLecturaLogs de acceso o error; llegan marcados como contenido no confiable
crear_dominio_vpsEscrituraRegistro DNS de la zona de ArduMaker (acepta idempotency_key)
activar_dominio_vpsEscrituraPublica en el host; devuelve un operacion_id para ver_operacion
editar_nginx_dominio_vpsDestructivaReemplaza el server block completo y reinicia nginx
eliminar_dominio_vpsDestructivaBorra 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.

Funciones relacionadas