Tutoriales de VPS
Instalar Nginx Proxy Manager en un VPS (2026): Docker, HTTPS de dominio, proxy inverso y configuración de seguridad
Despliega Nginx Proxy Manager 2.15.1 en un VPS con Docker Compose, configura el proxy inverso por dominio, Let's Encrypt HTTPS, WebSocket, Access List y Cloudflare, y aprende sobre MariaDB, copias de seguridad y actualizaciones, refuerzo de seguridad y solución de problemas 502/certificados.

Instalar Nginx Proxy Manager en un VPS (2026): Docker, HTTPS de dominio, proxy inverso y configuración de seguridad
Después de tener Uptime Kuma, Jellyfin, n8n, un blog y varias aplicaciones Docker en un solo VPS, lo más problemático normalmente no es arrancar los contenedores, sino asignar un dominio a cada servicio, obtener HTTPS, gestionar WebSocket y recordar decenas de fragmentos de configuración de Nginx.
Nginx Proxy Manager, o NPM para abreviar, convierte este trabajo en una interfaz de gestión web. Puedes apuntar status.example.com a un panel de monitorización, media.example.com a un servidor multimedia y solicitar un certificado Let's Encrypt independiente para cada dominio, sin tener que escribir a mano un Server Block completo de Nginx cada vez.
Este artículo usa la versión estable actual Nginx Proxy Manager 2.15.1 y MariaDB 11.4.12. Un recordatorio especial: muchos tutoriales antiguos en internet todavía usan [email protected] / changeme, pero la versión actual entra por defecto en un asistente de inicialización en el primer arranque, por lo que no deberías seguir confiando en ese conjunto antiguo de credenciales.
NPM encaja bien en las siguientes necesidades:
- Varios servicios web en un VPS que necesitan enrutarse por subdominio;
- No quieres escribir a mano la configuración de Nginx para cada aplicación;
- Quieres solicitar, renovar y revisar certificados HTTPS a través de una interfaz web;
- Un laboratorio doméstico o un equipo pequeño necesita gestión unificada del proxy inverso;
- Las aplicaciones Docker se añaden, migran o cambian de puerto con frecuencia;
- Necesitas Basic Auth, Access List o soporte de WebSocket sencillos.
Las siguientes situaciones no requieren necesariamente NPM:
- Solo tienes un sitio web y dos o tres líneas de configuración de Caddy son suficientes;
- Toda la configuración se gestiona con Git, Ansible o CI/CD y no quieres modificarla en una interfaz web;
- Necesitas gobernanza de tráfico compleja, descubrimiento dinámico de servicios o Kubernetes Ingress;
- Esperas que sustituya directamente a Cloudflare WAF, la autenticación de aplicaciones o una pasarela de confianza cero;
- Lo que gestionas no son servicios HTTP/HTTPS, sino una gran cantidad de protocolos de capa 4 complejos.
El núcleo de NPM sigue siendo Nginx. La interfaz web reduce la barrera de configuración, pero no resuelve automáticamente los problemas de permisos, vulnerabilidades, copias de seguridad de la base de datos y control de acceso de la propia aplicación.
| Opción | Ventajas | Desventajas | Para quién es más adecuada |
|---|---|---|---|
| Nginx Proxy Manager | Interfaz gráfica, gestión de certificados intuitiva, inicio rápido | Un backend de administración y una base de datos adicionales | Múltiples aplicaciones, laboratorios domésticos, equipos pequeños |
| Caddy | Configuración corta, HTTPS automático, mantenimiento sencillo | Gestión gráfica débil | Quienes prefieren archivos de configuración y tienen pocos servicios |
| Nginx nativo | Flexible, ecosistema maduro, detalles controlables | Mayor coste de aprendizaje y mantenimiento | Configuraciones de producción complejas y operaciones automatizadas |
Si estás acostumbrado a los archivos de configuración y solo haces proxy de tres a cinco servicios, la Guía completa de proxy inverso con Caddy en un VPS suele ser más ligera. Si necesitas que compañeros que no son de operaciones puedan añadir dominios, o los servicios cambian con frecuencia, NPM te ahorrará muchos problemas.
NPM en sí no es pesado; lo que realmente consume recursos son las aplicaciones que proxya.
| Escenario | Configuración recomendada | Notas |
|---|---|---|
| Hasta 5 aplicaciones ligeras | 1 núcleo, 1GB, 20GB SSD | Solo ejecutar NPM y unos pocos servicios de bajo tráfico |
| 10–30 aplicaciones | 2 núcleos, 2GB, 40GB SSD | Dejar margen para MariaDB, registros y certificados |
| Base de datos y aplicaciones de negocio en la misma máquina | 2–4 núcleos, 4GB+ | Elegir la configuración según la carga real de las aplicaciones de negocio |
| Sitio web de alto tráfico | CPU dedicada, ancho de banda amplio | Fijarse en las aplicaciones upstream y la red, no solo en NPM |
Se necesitan tres puertos:
80/tcp: HTTP y validación HTTP-01 de Let's Encrypt;443/tcp: tráfico HTTPS público;81/tcp: backend de administración de NPM.
Este artículo abre 80 y 443 a la internet pública, pero vincula 81 solo a 127.0.0.1. Se accede al backend de administración mediante un túnel SSH para evitar exponerlo directamente a la internet pública.
Antes de poner en marcha, comprueba si los puertos ya están ocupados:
sudo ss -lntp | grep -E ':(80|81|443)\b' || true
Si Nginx, Apache, Caddy u otro proxy ya ocupa 80/443, primero decide quién se hace cargo del punto de entrada; no inicies dos servicios peleando por el mismo puerto. Para una solución de problemas detallada, consulta Qué hacer cuando un puerto del VPS está ocupado.
Este artículo usa dos redes Docker:
npm-internal: conecta solo NPM y MariaDB, de modo que la base de datos no se expone a la internet pública;proxy: compartida por NPM y las aplicaciones Docker proxadas, accediendo a los upstreams por nombre de contenedor.
La ruta de las solicitudes externas es aproximadamente:
用户浏览器
↓ 80/443
Nginx Proxy Manager
↓ Docker proxy 网络
应用容器:内部端口
Si la aplicación no está en Docker, también puedes apuntar el Proxy Host a la dirección interna del VPS o a la IP privada de otro servidor.
Primero confirma que Docker y Compose están disponibles:
docker version
docker compose version
Si no están instalados, puedes leer primero la Guía práctica de despliegue con Docker. Para servidores de producción se recomienda instalar desde el repositorio oficial de Docker, en lugar de usar a largo plazo el Compose desactualizado de la distribución.
Crea el directorio y la red compartida:
sudo mkdir -p /opt/nginx-proxy-manager/data
sudo mkdir -p /opt/nginx-proxy-manager/letsencrypt
sudo mkdir -p /opt/nginx-proxy-manager/mariadb
sudo chown -R "$USER":"$USER" /opt/nginx-proxy-manager
docker network create proxy
Si la red proxy ya existe, Docker mostrará un conflicto de nombres y no necesitas crearla de nuevo. Puedes confirmarlo con el siguiente comando:
docker network inspect proxy
No uses directamente como contraseña los npm, password o nombres de dominio de los ejemplos. Genera dos conjuntos de valores aleatorios:
openssl rand -base64 36
openssl rand -base64 36
Guárdalos en /opt/nginx-proxy-manager/.env:
NPM_DB_ROOT_PASSWORD=替换为第一组随机密码
NPM_DB_PASSWORD=替换为第二组随机密码
Restringe los permisos del archivo:
chmod 600 /opt/nginx-proxy-manager/.env
Si la contraseña contiene espacios, saltos de línea o caracteres especiales de interpolación de Compose, el análisis puede fallar. Usar openssl rand -hex 32 genera contraseñas hexadecimales puras que son más fáciles de poner en .env.
Crea /opt/nginx-proxy-manager/compose.yaml:
services:
app:
image: jc21/nginx-proxy-manager:2.15.1
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80/tcp"
- "443:443/tcp"
- "127.0.0.1:81:81/tcp"
environment:
TZ: Asia/Shanghai
DB_MYSQL_HOST: db
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: npm
DB_MYSQL_PASSWORD: ${NPM_DB_PASSWORD}
DB_MYSQL_NAME: npm
volumes:
- /opt/nginx-proxy-manager/data:/data
- /opt/nginx-proxy-manager/letsencrypt:/etc/letsencrypt
networks:
- npm-internal
- proxy
depends_on:
db:
condition: service_healthy
db:
image: linuxserver/mariadb:11.4.12
container_name: nginx-proxy-manager-db
restart: unless-stopped
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: ${NPM_DB_ROOT_PASSWORD}
MYSQL_DATABASE: npm
MYSQL_USER: npm
MYSQL_PASSWORD: ${NPM_DB_PASSWORD}
volumes:
- /opt/nginx-proxy-manager/mariadb:/config
networks:
- npm-internal
healthcheck:
test: ["CMD-SHELL", "mariadb-admin ping -h 127.0.0.1 -uroot -p\"$${MYSQL_ROOT_PASSWORD}\" --silent"]
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
networks:
npm-internal:
internal: true
proxy:
external: true
Aquí se fijan las versiones de NPM y MariaDB para evitar una actualización accidental de versión mayor durante un docker compose pull. El proyecto oficial también admite SQLite, que ciertamente es más sencillo para pruebas personales; pero con múltiples proxies, certificados y operación a largo plazo, una base de datos independiente es más fácil de respaldar, inspeccionar y restaurar.
Revisa la configuración final para asegurarte de que las contraseñas se leen correctamente:
cd /opt/nginx-proxy-manager
docker compose config --quiet
No pegues la salida completa de docker compose config en un ticket público; puede expandir la contraseña de la base de datos en .env.
Inicia los servicios:
cd /opt/nginx-proxy-manager
docker compose up -d
docker compose ps
El primer arranque genera el secreto JWT, inicializa la base de datos y la estructura de tablas, y puede tardar uno o dos minutos. Consulta los registros:
docker compose logs --tail=150 app
docker compose logs --tail=100 db
Confirma el puerto del backend local:
curl -I http://127.0.0.1:81
Si devuelve un fallo justo después del arranque, espera a que pase la comprobación de estado de la base de datos y vuelve a revisar los registros. No borres el directorio de datos y reinstales solo porque la primera conexión falló.
Como 81 solo escucha en localhost, necesitas establecer un túnel SSH desde tu propio ordenador:
ssh -L 8181:127.0.0.1:81 your_user@your_vps_ip
Mantén la conexión del terminal abierta y luego visita en el navegador:
http://127.0.0.1:8181
La versión actual muestra por defecto un asistente de inicialización que te permite crear el primer administrador. Usa un correo electrónico real que pueda recibir notificaciones y una contraseña aleatoria independiente.
El siguiente conjunto de credenciales, habitual en artículos antiguos, ya no es adecuado como flujo predeterminado para el tutorial actual:
[email protected]
changeme
Si actualizas desde un directorio de datos antiguo, la cuenta original se conservará; si ves la interfaz de la cuenta antigua en una instalación nueva, comprueba si reutilizaste un /data o una base de datos anteriores.
Supongamos que quieres proxear app.example.com a una aplicación:
- Crea un registro A en tu proveedor de DNS apuntando a la IPv4 pública del VPS;
- Si tienes IPv6, crea también un registro AAAA y confirma que los puertos 80/443 del VPS también están abiertos en el firewall de IPv6;
- Espera a que la resolución surta efecto;
- Comprueba el resultado de la resolución localmente.
dig +short app.example.com A
dig +short app.example.com AAAA
Si el AAAA apunta al servidor equivocado, Let's Encrypt y algunos usuarios pueden fallar al acceder por IPv6. Si por ahora no usas IPv6, eliminar el AAAA incorrecto es más seguro que dejarlo apuntando siempre al lugar equivocado.
Después de entrar en NPM, selecciona Hosts → Proxy Hosts → Add Proxy Host.
Ejemplo de configuración básica:
| Campo | Ejemplo | Notas |
|---|---|---|
| Domain Names | app.example.com | Un dominio ya resuelto al VPS |
| Scheme | http | Úsalo cuando la aplicación upstream no tiene TLS habilitado |
| Forward Hostname / IP | my-app | El nombre del contenedor en la misma red Docker |
| Forward Port | 3000 | El puerto en el que escucha internamente el contenedor de la aplicación |
| Cache Assets | Desactivado por defecto | No lo actives a ciegas en aplicaciones dinámicas |
| Block Common Exploits | Se puede activar | No es un WAF completo; aún hay que probar la compatibilidad |
| Websockets Support | Actívalo según la aplicación | Los paneles en tiempo real, terminales y notificaciones suelen necesitarlo |
Antes de guardar, prueba el upstream dentro del contenedor NPM:
docker exec nginx-proxy-manager getent hosts my-app
docker exec nginx-proxy-manager curl -I http://my-app:3000
Si no se puede resolver el nombre del contenedor, los dos contenedores no están unidos a la misma red proxy.
El Compose propio de la aplicación puede escribirse así:
services:
my-app:
image: your-app-image:固定版本
restart: unless-stopped
expose:
- "3000"
networks:
- proxy
networks:
proxy:
external: true
expose solo declara el puerto interno del contenedor y no publica 3000 directamente a la internet pública. Los usuarios externos solo pueden acceder a través de los puertos 80/443 de NPM, reduciendo la superficie de ataque.
Los contenedores que ya están en ejecución pueden unirse temporalmente a la red:
docker network connect proxy my-app
Pero después de recrear el contenedor, la conexión manual puede perderse. La configuración a largo plazo debe escribirse en el archivo Compose de la aplicación.
Si la aplicación se ejecuta directamente en el host del VPS y no en Docker, no rellenes 127.0.0.1 en NPM. El 127.0.0.1 dentro del contenedor NPM apunta al propio contenedor NPM, no al host.
Puedes usar uno de los siguientes enfoques:
- Hacer que la aplicación escuche en la dirección privada del host y luego rellenar esa dirección;
- Añadir una asignación
host-gatewayen el Compose de Linux; - Usar la IP privada de otro servidor en la misma LAN;
- Migrar también la aplicación a la red Docker compartida.
Ejemplo de host-gateway:
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
Después puedes intentar usar host.docker.internal como Forward Hostname. El firewall del host y la dirección de escucha de la aplicación todavía deben permitir conexiones desde el puente Docker.
En la página SSL del Proxy Host:
- Selecciona
Request a new SSL Certificate; - Activa
Force SSL; - Para sitios web normales puedes activar
HTTP/2 Support; - Rellena el correo electrónico y acepta los términos de Let's Encrypt;
- Después de guardar, comprueba el estado del certificado.
La validación HTTP-01 requiere:
- Que los registros A/AAAA del dominio apunten correctamente al VPS actual;
- Que el puerto 80 sea accesible desde la internet pública;
- Que el firewall en la nube, UFW y los grupos de seguridad permitan 80/443;
- Que el puerto 80 no esté ocupado por otro proxy inverso;
- Que Cloudflare u otro proxy no envíe las solicitudes al origen equivocado.
Si la emisión del certificado falla, no hagas clic una docena de veces seguidas. Let's Encrypt tiene límites de frecuencia; corrige primero el DNS y los puertos y vuelve a solicitarlo.
Muchos paneles de administración, aplicaciones de chat, terminales en línea y herramientas de desarrollo necesitan WebSocket. Lo primero que hay que hacer es activar Websockets Support en el Proxy Host.
Si sigue desconectándose:
- Confirma la ruta WebSocket de la aplicación upstream;
- Busca 400, 403 o 502 en las herramientas de desarrollo del navegador;
- Comprueba si la aplicación requiere un proxy de confianza o la URL externa correcta;
- Confirma los límites de WebSocket y de tiempo de espera de Cloudflare;
- Revisa las solicitudes Upgrade en los registros de NPM y de la aplicación.
No empieces pegando grandes bloques de configuración de Nginx de origen desconocido en Advanced. NPM ya genera las cabeceras de proxy habituales, y la configuración duplicada puede causar conflictos.
La Access List de NPM puede aplicar dos tipos de restricciones básicas:
- HTTP Basic Auth con nombre de usuario y contraseña;
- Permitir o denegar el acceso por IP o subred.
Es adecuada para sitios de demostración temporales, herramientas internas sencillas o una segunda barrera de acceso, pero no equivale a un sistema de identidad completo. No dependas solo de Basic Auth en los siguientes escenarios:
- Backends que gestionan cuentas en la nube, contraseñas o información de pago;
- Colaboración entre varias personas que requiere auditoría e inicio de sesión único;
- API públicas, Webhooks o clientes móviles;
- Escenarios que requieren MFA, políticas de dispositivos y permisos granulares.
Los backends más sensibles pueden colocarse detrás de WireGuard, Tailscale, Headscale o Cloudflare Access. Al gestionar el propio NPM, un túnel SSH suele ser más directo que exponer el puerto 81.
Técnicamente puedes proxear npm.example.com al puerto de administración, pero esto expone la superficie de inicio de sesión a la internet pública. Si realmente necesitas inicio de sesión web remoto, al menos haz todo lo siguiente:
- Usa un subdominio independiente;
- Activa HTTPS;
- Configura una Access List o una pasarela de identidad externa;
- Haz que los administradores usen contraseñas largas únicas;
- No abras directamente el puerto 81;
- Configura alertas de inicio de sesión y revisa los registros periódicamente;
- Al restringir las regiones o IP de origen permitidas, prepara primero un método de recuperación.
Si eres el único que gestiona un solo VPS, sigue usando un túnel SSH; no hay necesidad de añadir un punto de entrada público solo para "parecer cómodo".
Al integrar Cloudflare, se recomienda usar primero la nube gris "solo DNS" para completar la validación de NPM y del certificado, confirmar que el acceso directo al origen funciona y luego activar el proxy de nube naranja.
Puntos habituales a tener en cuenta:
- Usa
Full (strict)para el modo SSL/TLS, no Flexible; - El NPM de origen sigue necesitando un certificado HTTPS válido;
- Flexible provoca fácilmente bucles de redirección HTTP/HTTPS;
- Cloudflare 521/522 normalmente indica un problema de puerto de origen, firewall o conexión;
- La IP real del cliente requiere configuración de proxy de confianza; no confíes a ciegas en cualquier
X-Forwarded-For; - Las cargas de archivos grandes, las conexiones largas y el streaming deben comprobarse con los límites del plan y los términos de servicio de Cloudflare.
Para bucles de redirección, consulta Solución de bucles de redirección HTTPS; para 521/522, consulta Solución de problemas de origen Cloudflare 521/522.
Si la aplicación admite archivos grandes pero obtienes 413 Request Entity Too Large al subirlos a través de NPM, puedes configurar lo siguiente en Advanced del Proxy Host correspondiente según sea necesario:
client_max_body_size 2g;
proxy_request_buffering off;
No lo configures en decenas de GB sin criterio. Comprueba también de forma sincronizada:
- El límite de carga de la propia aplicación;
- Los límites de PHP, Node.js o del framework de backend;
- El límite de carga de Cloudflare;
- El espacio en disco del VPS y el directorio temporal;
- Los tiempos de espera de las solicitudes y la red del cliente.
Después de modificarlo, verifícalo con un archivo de prueba controlable; no uses tu único archivo grande para la primera prueba.
Primero mira la salida del contenedor:
cd /opt/nginx-proxy-manager
docker compose logs --tail=200 app
docker compose logs --tail=100 db
Los registros persistentes y la configuración generada de NPM se guardan en /opt/nginx-proxy-manager/data. Durante la solución de problemas puedes revisar:
sudo find /opt/nginx-proxy-manager/data -maxdepth 3 -type f | sort | tail -n 50
No edites a mano sin cuidado los archivos de configuración de Nginx generados automáticamente. La próxima vez que guardes un Proxy Host en la interfaz web, los cambios manuales pueden sobrescribirse. La personalización a largo plazo debe ir en las ubicaciones Advanced o de configuración personalizada compatibles con NPM, y verificarse antes de actualizar.
Como mínimo, respalda:
/opt/nginx-proxy-manager/data: usuarios, configuración, secreto JWT y datos de la aplicación;/opt/nginx-proxy-manager/letsencrypt: certificados e información de la cuenta;/opt/nginx-proxy-manager/mariadb: archivos de la base de datos;compose.yamly.env;- Las versiones actuales de las imágenes y las instrucciones de recuperación.
Copiar archivos directamente mientras la base de datos está en ejecución no garantiza necesariamente una copia de seguridad coherente. Se recomienda exportar primero la base de datos:
cd /opt/nginx-proxy-manager
docker compose exec -T db mariadb-dump \
-unpm \
-p"$NPM_DB_PASSWORD" \
npm > npm-$(date +%F).sql
El Shell anterior requiere cargar primero .env:
set -a
. /opt/nginx-proxy-manager/.env
set +a
El SQL exportado, el directorio de configuración y .env deben cifrarse y copiarse a otra máquina o a un almacenamiento de objetos. Mantener las copias de seguridad solo en el mismo disco del VPS no sirve ante un fallo del disco o la suspensión de la cuenta.
Antes de actualizar, revisa las imágenes actuales y haz una copia de seguridad:
cd /opt/nginx-proxy-manager
docker inspect nginx-proxy-manager --format '{{.Config.Image}}'
docker compose config > compose.before-upgrade.yaml
Lee las Release Notes de la versión de destino, confirma los cambios de base de datos y arquitectura, y luego modifica las etiquetas de imagen en compose.yaml:
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=200 app
Después de actualizar, prueba al menos:
- El inicio de sesión del administrador;
- Un upstream HTTP normal;
- Una aplicación WebSocket;
- El estado del certificado HTTPS;
- Las Access Lists;
- Los registros de la base de datos y de renovación de certificados.
No saltes varias versiones mayores desde una versión muy antigua sin copia de seguridad. Revertir la imagen no equivale a revertir la base de datos; si el esquema de la base de datos ya se ha migrado, también debes restaurar los datos previos a la actualización.
Este artículo vincula deliberadamente 81 a 127.0.0.1, por lo que acceder a http://服务器IP:81 desde la internet pública fallará por diseño. Establece primero el túnel SSH y luego accede a http://127.0.0.1:8181 local.
Comprobación en el servidor:
sudo ss -lntp | grep ':81'
curl -I http://127.0.0.1:81
Las causas más habituales son una dirección upstream incorrecta, usar el puerto del host como puerto, que el contenedor no esté en la red compartida, o que la aplicación solo escuche en 127.0.0.1.
Prueba dentro del contenedor NPM:
docker exec nginx-proxy-manager getent hosts my-app
docker exec nginx-proxy-manager curl -v http://my-app:3000
Para una comprobación más sistemática, consulta la Lista de verificación para solucionar 502/504 Bad Gateway en VPS.
Confirma en orden:
dig +short app.example.com A
dig +short app.example.com AAAA
sudo ss -lntp | grep -E ':(80|443)\b'
docker compose logs --tail=200 app
Comprueba también el firewall en la nube y UFW. Si el DNS se acaba de cambiar, puedes esperar a que el TTL surta efecto antes de solicitar, para evitar activar fallos repetidamente.
Normalmente no es que NPM borre automáticamente, sino que se cambió la base de datos, se montó en un nuevo directorio vacío o Compose no leyó el .env original. Comprueba los montajes reales del contenedor:
docker inspect nginx-proxy-manager --format '{{json .Mounts}}'
docker inspect nginx-proxy-manager-db --format '{{json .Mounts}}'
Antes de restaurar, conserva una copia del directorio actual; no sobrescribas directamente tus únicos datos.
Revisa los registros de MariaDB y el disco:
docker compose logs --tail=200 db
df -h
df -i
Las causas habituales incluyen variables de contraseña inconsistentes, permisos incorrectos en el directorio de la base de datos antigua, disco lleno o una actualización que abarca demasiadas versiones. No sigas borrando /config y reintentando, o también borrarás datos recuperables.
Activa primero Websockets Support y luego confirma la URL externa, el proxy de confianza, el heartbeat y la configuración de tiempos de espera de la aplicación. Si delante también hay Cloudflare, un balanceador de carga u otra capa de Nginx, debes confirmar capa por capa qué segmento está cerrando la conexión.
- 80/443 solo están ocupados por un proxy de entrada;
- 81 solo está vinculado a localhost, una VPN o una red de gestión de confianza;
- Los administradores usan contraseñas aleatorias únicas, no reutilizadas con las de la base de datos;
- MariaDB no mapea puertos públicos;
- Los contenedores de aplicaciones prefieren
exposey redes compartidas, y no publican directamente puertos de administración; - Los permisos de
.envse establecen en 600 y no se suben a repositorios públicos; - Los Proxy Hosts solo proxean servicios que tienes derecho a gestionar;
- Basic Auth no sustituye el inicio de sesión propio de la aplicación ni el MFA;
- Cloudflare usa Full (strict), evitando Flexible;
- Revisa periódicamente los registros de certificados, inicio de sesión, proxy y base de datos;
- Fija las versiones antes de actualizar, respalda la base de datos y prueba la recuperación;
- Cierra los Proxy Hosts, certificados y registros DNS que ya no se usen;
- No trates NPM como un WAF, un escáner de vulnerabilidades o un sistema completo de confianza cero.
No. Admite oficialmente SQLite, MySQL/MariaDB y PostgreSQL. Las pruebas personales o un pequeño número de proxies pueden usar SQLite; para la operación a largo plazo y cuando necesitas copias de seguridad y migración claras de la base de datos, una base de datos independiente es más fácil de gestionar.
Sí, pero no pueden vincularse al mismo 80/443 del host al mismo tiempo. El enfoque más claro es mantener solo un proxy de entrada público y poner otros paneles y aplicaciones en puertos internos o en redes Docker.
No. Él mismo se ejecuta en el origen. Si necesitas ocultar el origen, proporcionar acceso por identidad o evitar abrir puertos de entrada, debes evaluar por separado Cloudflare Tunnel, una VPN o un proxy de borde independiente. En el sitio hay una Guía de despliegue de Cloudflare Tunnel para comparar.
NPM gestiona la renovación de certificados de Let's Encrypt, pero solo con la premisa de que el DNS, los puertos, el directorio de certificados y el estado de ejecución del contenedor sigan siendo normales. Se recomienda configurar una monitorización externa de caducidad HTTPS; no confíes solo en que "en teoría se renovará automáticamente".
Sí. Usa un subdominio y un Proxy Host independientes para cada servicio, y activa WebSocket, límites de carga y configuración de proxy de confianza según la aplicación. El streaming y los archivos grandes también deben tener en cuenta el ancho de banda del VPS, los límites de Cloudflare y los términos de servicio.
En el primer despliegue, añade solo una aplicación de prueba poco importante. Confirma que DNS, HTTP, HTTPS, WebSocket y los registros funcionan correctamente antes de migrar los servicios de producción. No cambies una docena de dominios al nuevo proxy el mismo día, de lo contrario, cuando surjan problemas, será difícil saber si es DNS, NPM, la red Docker o la configuración de la aplicación.
Para individuos y equipos pequeños, el mayor valor de NPM no es "un rendimiento más potente que Nginx", sino la gestión centralizada de dominios, certificados y configuración del proxy. La verdadera clave de la estabilidad sigue siendo: mantener un solo punto de entrada, tener una red upstream clara, no dejar el backend de administración expuesto, fijar las versiones y hacer que las copias de seguridad sean recuperables.