Hosting Equipo Avantys 4 min

Proxy Inverso con Nginx: Múltiples Apps en un VPS

Configura Nginx como proxy inverso para servir múltiples aplicaciones. Node.js, Python, Docker, subdominios y SSL centralizado.

// Compartir

Proxy Inverso con Nginx: Múltiples Apps en un VPS

Un proxy inverso te permite servir múltiples aplicaciones en diferentes puertos a través de un único punto de entrada. Nginx es perfecto para esto.

Qué es un proxy inverso

Arquitectura de proxy inverso
Internet → Nginx (80/443) → App1 (:3000)
                          → App2 (:4000)
                          → App3 (:5000)

Nginx recibe todo el tráfico y lo redirige a la app correcta según el dominio o ruta.

Ventajas

BeneficioDescripción
SSL centralizadoUn certificado por dominio en Nginx
Un puerto expuestoSolo 80/443 abiertos
CachéNginx cachea respuestas
Load balancingDistribuir entre backends
HeadersAñadir seguridad centralizada

Configuración básica

Estructura

/etc/nginx/
├── nginx.conf
├── sites-available/
│   ├── app1.tudominio.com
│   ├── app2.tudominio.com
│   └── api.tudominio.com
└── sites-enabled/
    └── (symlinks)

Proxy a aplicación Node.js

# /etc/nginx/sites-available/app.tudominio.com
server {
    listen 80;
    server_name app.tudominio.com;

    location / {
        proxy_pass http://localhost: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;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}
sudo ln -s /etc/nginx/sites-available/app.tudominio.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Múltiples apps por subdominios

Casos de uso proxy inverso

app1.tudominio.com → Node.js (:3000)

server {
    listen 80;
    server_name app1.tudominio.com;

    location / {
        proxy_pass http://localhost:3000;
        include /etc/nginx/proxy_params;
    }
}

app2.tudominio.com → Python (:8000)

server {
    listen 80;
    server_name app2.tudominio.com;

    location / {
        proxy_pass http://localhost:8000;
        include /etc/nginx/proxy_params;
    }
}

api.tudominio.com → Go (:4000)

server {
    listen 80;
    server_name api.tudominio.com;

    location / {
        proxy_pass http://localhost:4000;
        include /etc/nginx/proxy_params;
    }
}

Archivo común de params

# /etc/nginx/proxy_params
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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 90;

Múltiples apps por ruta

Un dominio, diferentes rutas

server {
    listen 80;
    server_name tudominio.com;

    # Frontend (React/Vue)
    location / {
        proxy_pass http://localhost:3000;
        include /etc/nginx/proxy_params;
    }

    # API
    location /api/ {
        proxy_pass http://localhost:4000/;
        include /etc/nginx/proxy_params;
    }

    # Admin panel
    location /admin/ {
        proxy_pass http://localhost:5000/;
        include /etc/nginx/proxy_params;
    }

    # WebSocket
    location /ws/ {
        proxy_pass http://localhost:6000/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

SSL con Let’s Encrypt

# Obtener certificados para todos los subdominios
sudo certbot --nginx \
    -d app1.tudominio.com \
    -d app2.tudominio.com \
    -d api.tudominio.com

Certbot modifica automáticamente las configuraciones para HTTPS.

Proxy a contenedores Docker

Docker Compose

# docker-compose.yml
version: '3'
services:
  frontend:
    image: mi-frontend
    ports:
      - "3000:3000"
  
  api:
    image: mi-api
    ports:
      - "4000:4000"
  
  admin:
    image: mi-admin
    ports:
      - "5000:5000"

Nginx apuntando a Docker

server {
    listen 80;
    server_name tudominio.com;

    location / {
        proxy_pass http://localhost:3000;  # frontend
        include /etc/nginx/proxy_params;
    }

    location /api/ {
        proxy_pass http://localhost:4000/;  # api
        include /etc/nginx/proxy_params;
    }
}

Red Docker interna (mejor)

# docker-compose.yml
version: '3'
services:
  nginx:
    image: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - frontend
      - api

  frontend:
    image: mi-frontend
    # Sin ports expuestos

  api:
    image: mi-api
    # Sin ports expuestos
# nginx.conf dentro de Docker
upstream frontend {
    server frontend:3000;
}

upstream api {
    server api:4000;
}

server {
    listen 80;
    
    location / {
        proxy_pass http://frontend;
    }
    
    location /api/ {
        proxy_pass http://api/;
    }
}

Load Balancing

Múltiples backends

upstream api_servers {
    least_conn;  # Menos conexiones
    server localhost:4000 weight=5;
    server localhost:4001 weight=5;
    server localhost:4002 backup;  # Solo si otros fallan
}

server {
    listen 80;
    server_name api.tudominio.com;

    location / {
        proxy_pass http://api_servers;
        include /etc/nginx/proxy_params;
    }
}

Caché en proxy

# Definir zona de caché
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;

server {
    listen 80;
    server_name tudominio.com;

    location / {
        proxy_pass http://localhost:3000;
        
        # Activar caché
        proxy_cache my_cache;
        proxy_cache_valid 200 1h;
        proxy_cache_valid 404 1m;
        add_header X-Cache-Status $upstream_cache_status;
    }

    # No cachear API
    location /api/ {
        proxy_pass http://localhost:4000/;
        proxy_cache off;
    }
}

Headers de seguridad

server {
    # ... proxy config ...

    # Headers de seguridad centralizados
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self';" always;
}

Preguntas frecuentes

¿Por qué usar proxy inverso en lugar de exponer cada app?

Seguridad (solo 80/443 expuestos), SSL centralizado, headers consistentes, y posibilidad de load balancing y caché. Es la práctica estándar en producción.

¿Nginx o Apache como proxy inverso?

Nginx es más eficiente para proxy inverso. Usa menos memoria, maneja más conexiones concurrentes, y su configuración de proxy es más limpia.

¿Cómo paso la IP real a mi aplicación?

Usa los headers X-Real-IP y X-Forwarded-For. En tu app, lee estos headers en lugar de la IP de conexión directa.

¿Puedo usar Nginx como proxy para WebSockets?

Sí. Necesitas los headers Upgrade y Connection configurados correctamente. El ejemplo de WebSocket en esta guía muestra cómo.

¿Afecta el rendimiento usar proxy inverso?

El overhead es mínimo. De hecho, con caché de Nginx puedes mejorar rendimiento. La latencia añadida es típicamente <1ms.

Nuestra recomendación

Para cualquier app en producción:

  • Nginx como proxy inverso
  • SSL en Nginx (no en cada app)
  • Headers de seguridad centralizados
  • Logs centralizados

Para múltiples apps:

  • Subdominio por app (más limpio)
  • O rutas si quieres un solo dominio

¿Necesitas ayuda configurando proxy? Los VPS gestionados de Avantys incluyen configuración profesional de Nginx.


Conclusión

El proxy inverso con Nginx es esencial para cualquier VPS con múltiples aplicaciones. Una vez configurado, simplifica enormemente la gestión de SSL, seguridad y routing.

Empieza con la configuración básica y añade caché y load balancing según necesites.


¿Quieres que lo hagamos por ti?

En Avantys gestionamos tu web, hosting y crecimiento digital de punta a punta. Tú a lo importante.

Hablar con Avantys
// Boletín

Suscríbete al boletín

Guías nuevas, sin spam. Cancela cuando quieras.