Nginx Proxy Manager pone una interfaz web sobre Nginx y Certbot para que publiques tus servicios con HTTPS sin editar un solo fichero de configuración. En esta guía lo levantas con un único docker-compose.yml acompañado de su base de datos, entras por primera vez con la contraseña por defecto, creas un host proxy con certificado de Let’s Encrypt en unos clics y lo comparas con Traefik para saber cuándo conviene cada uno. La misma explicación está disponible en inglés.

Puntos clave

  • Nginx Proxy Manager (NPM) es un proxy inverso de código abierto (licencia MIT) que se describe a sí mismo como "un contenedor Docker para gestionar hosts proxy de Nginx con una interfaz sencilla y potente", con más de 33.000 estrellas en GitHub.
  • Por debajo usa OpenResty (Nginx con Lua) y Certbot, así que gestiona los certificados de Let’s Encrypt y su renovación automática sin que tú toques la línea de comandos.
  • Publica tres puertos: el 80 para HTTP, el 443 para HTTPS y el 81 para su panel de administración web.
  • El primer acceso usa siempre las credenciales por defecto admin@example.com / changeme, y NPM te obliga a cambiarlas nada más entrar.
  • Fija una versión concreta de la imagen como jc21/nginx-proxy-manager:2.15.1 (la estable actual, publicada el 3 de junio de 2024) en lugar de :latest; así controlas tú cuándo saltas de versión.

¿Qué es Nginx Proxy Manager?

Nginx Proxy Manager es una capa de administración web construida sobre Nginx que te permite exponer varios servicios internos a través de un único punto de entrada, cada uno con su propio dominio y su certificado TLS. En lugar de escribir bloques server { ... } a mano y lanzar Certbot desde la terminal, defines todo desde un panel: qué dominio apunta a qué contenedor, en qué puerto y con qué certificado. Es la puerta de entrada favorita de mucha gente que empieza en el self-hosting, precisamente porque esconde la complejidad de Nginx tras formularios sencillos.

Por dentro, NPM empaqueta OpenResty (una distribución de Nginx con el intérprete Lua incorporado) y Certbot, el cliente oficial de Let’s Encrypt. Cuando creas un host proxy y pides un certificado, NPM genera el fichero de configuración de Nginx, ejecuta el reto de validación de Let’s Encrypt y recarga el servidor por ti. La configuración vive en una base de datos y los certificados en el volumen /etc/letsencrypt, de modo que sobreviven a reinicios y actualizaciones del contenedor.

El proyecto lo mantiene la comunidad bajo licencia MIT y acumula más de 33.000 estrellas en GitHub, lo que da una idea de su popularidad en el mundo del homelab. Si vienes de otras guías de esta serie, NPM es el paso natural para sacar a Internet con seguridad servicios como Vaultwarden o cualquier panel que hayas montado, sin exponer puertos raros.

¿Cómo es el docker-compose.yml con base de datos?

Antes de nada necesitas una máquina Linux con Docker y el plugin Compose; si aún no los tienes, sigue primero la guía para instalar Docker en Ubuntu 24.04. NPM puede funcionar con una base de datos SQLite embebida (la opción más sencilla), pero para un despliegue serio conviene usar MariaDB en un contenedor aparte, que es lo que hacemos aquí. Crea una carpeta para el proyecto y guarda dentro este docker-compose.yml:

services:
  app:
    image: jc21/nginx-proxy-manager:2.15.1
    container_name: npm
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "81:81"
    environment:
      DB_MYSQL_HOST: db
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: npm
      DB_MYSQL_PASSWORD: cambia_esta_clave
      DB_MYSQL_NAME: npm
    volumes:
      - npm_data:/data
      - npm_letsencrypt:/etc/letsencrypt
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "/usr/bin/check-health"]
      interval: 30s
      timeout: 5s
      retries: 5

  db:
    image: mariadb:11.8
    container_name: npm-db
    restart: unless-stopped
    environment:
      MARIADB_ROOT_PASSWORD: cambia_esta_clave_root
      MARIADB_DATABASE: npm
      MARIADB_USER: npm
      MARIADB_PASSWORD: cambia_esta_clave
    volumes:
      - npm_db:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 30s
      timeout: 5s
      retries: 5

volumes:
  npm_data:
  npm_letsencrypt:
  npm_db:

Repasa los detalles importantes. El servicio app es NPM: publica el 80 y el 443 para el tráfico real y el 81 para el panel. Las variables DB_MYSQL_* le dicen cómo conectarse a MariaDB, cuyas credenciales deben coincidir con las MARIADB_* del servicio db. Cambia cambia_esta_clave y cambia_esta_clave_root por contraseñas reales; si prefieres no escribirlas en el fichero, léelas desde variables de entorno y secretos. Los volúmenes npm_data y npm_letsencrypt guardan la configuración y los certificados, y npm_db los datos de la base de datos. El depends_on con condition: service_healthy evita que NPM arranque antes de que MariaDB esté lista, un patrón que puedes repasar en la guía de instalar MariaDB con Docker.

Con el archivo listo, arranca la pila en segundo plano y observa los registros:

mkdir nginx-proxy-manager
cd nginx-proxy-manager
docker compose up -d
docker compose ps
docker compose logs -f app

La primera vez NPM tarda un par de minutos en construir su configuración inicial. Cuando el contenedor aparezca como healthy, el panel estará listo en el puerto 81.

¿Cuál es el primer acceso y la contraseña por defecto?

Abre http://192.168.1.10:81 en el navegador (sustituye la IP por la de tu servidor). NPM crea siempre un usuario administrador con las credenciales por defecto admin@example.com como correo y changeme como contraseña. Introdúcelas y, en cuanto entres, la aplicación te pedirá inmediatamente que rellenes tu nombre real y tu correo y que definas una contraseña nueva. Esas credenciales por defecto solo valen para el primer acceso: no puedes dejarlas puestas.

Este primer paso es también el punto donde más gente se atasca. Si el formulario rechaza admin@example.com / changeme, casi siempre es porque el contenedor no terminó de arrancar o porque no logró conectar con la base de datos; revisa docker compose logs -f app en busca de errores de conexión a MariaDB. Una vez dentro y con la contraseña cambiada, el panel muestra cuatro secciones: hosts proxy, listas de acceso, certificados SSL y usuarios. A partir de aquí ya no vuelves a tocar la terminal para el trabajo diario.

¿Cómo crear un host proxy con SSL de Let’s Encrypt?

Supón que tienes un servicio web escuchando en otro contenedor, por ejemplo un panel en http://192.168.1.10:9000, y un dominio panel.midominio.com cuyo registro DNS apunta a la IP pública de tu servidor. Para publicarlo con HTTPS, entra en Hosts y pulsa Add Proxy Host. En la pestaña Details escribe el dominio (panel.midominio.com), indica el destino (Forward Hostname con la IP o el nombre del contenedor y Forward Port con el 9000) y activa Block Common Exploits.

El certificado se pide en la pestaña SSL. Despliega SSL Certificate, elige Request a new SSL Certificate, marca Force SSL y HTTP/2 Support, acepta los términos de Let’s Encrypt y guarda. NPM lanza el reto de validación, obtiene el certificado y recarga Nginx en unos segundos; a partir de ese momento https://panel.midominio.com responde con candado y se renueva solo cada 90 días. Para que la validación funcione, los puertos 80 y 443 de tu router deben estar redirigidos al servidor, porque Let’s Encrypt necesita alcanzar el dominio desde fuera. Si el servicio de destino corre en Docker, conéctalo a la misma red que NPM y usa el nombre del contenedor en lugar de la IP; así no dependes de puertos publicados en el anfitrión.

¿NPM o Traefik: cuándo elegir cada uno?

Nginx Proxy Manager y Traefik resuelven el mismo problema (un proxy inverso con TLS automático), pero con filosofías opuestas. NPM es una herramienta centrada en la interfaz gráfica: configuras cada host desde el navegador, guardas en una base de datos y ves los certificados en una tabla. Traefik, en cambio, es configuración como código: descubre los contenedores solo, leyendo etiquetas en el propio docker-compose.yml, sin panel de escritura y sin base de datos.

  • Elige NPM si empiezas, si prefieres pulsar botones antes que escribir YAML, o si gestionas unos pocos dominios que cambian de vez en cuando. Su curva de aprendizaje es mínima y en cinco minutos tienes tu primer HTTPS.
  • Elige Traefik si automatizas tu infraestructura, si levantas y tiras contenedores a menudo o si quieres que todo viva en el repositorio (GitOps). Traefik reconfigura las rutas al instante cuando arranca un contenedor con las etiquetas adecuadas, sin pasar por ninguna interfaz.

La diferencia clave es el estado: en NPM la fuente de la verdad es su base de datos, que tienes que respaldar; en Traefik es tu docker-compose.yml, versionado en Git. No son excluyentes: mucha gente empieza con NPM por comodidad y migra a Traefik cuando su homelab crece y el clic manual empieza a estorbar.

Preguntas frecuentes

¿Necesita Nginx Proxy Manager una base de datos aparte?

No es obligatorio. NPM puede usar una base de datos SQLite embebida, y de hecho es lo que trae por defecto si no le pasas las variables DB_MYSQL_*: en ese caso basta con montar el volumen /data. La opción con MariaDB, la que muestra esta guía, es preferible para instalaciones grandes o con muchos hosts, porque una base de datos cliente-servidor rinde mejor bajo carga y se respalda con las herramientas habituales. Para empezar, SQLite es perfectamente válido.

¿Puedo usar Nginx Proxy Manager si el puerto 80 ya está ocupado?

El puerto 80 tiene que estar libre en el anfitrión, porque Let’s Encrypt lo usa para validar los dominios por el método HTTP. Si otro servicio lo ocupa, tienes dos caminos: parar ese servicio y ponerlo detrás del propio NPM, o cambiar a la validación por DNS, que NPM también admite para proveedores compatibles y no necesita el puerto 80 abierto. El puerto 81 del panel, en cambio, puedes cambiarlo sin problema en la sección ports.

¿Es seguro exponer el panel de administración a Internet?

No conviene. El puerto 81 da acceso total a la configuración del proxy, así que lo recomendable es dejarlo accesible solo desde tu red local o a través de una VPN. Si necesitas administrarlo desde fuera, ponlo tú mismo detrás de un host proxy de NPM con HTTPS y una lista de acceso (autenticación básica), en lugar de publicar el 81 tal cual. La misma prudencia vale para cualquier servicio sin inicio de sesión propio.

Conclusión

Con un único docker-compose.yml y su base de datos tienes un proxy inverso completo y manejable desde el navegador: publicas servicios con HTTPS, pides certificados de Let’s Encrypt en unos clics y te olvidas de editar Nginx a mano. Recuerda fijar la versión de la imagen, cambiar la contraseña por defecto en el primer acceso y no exponer el puerto 81 a Internet. El siguiente paso lógico es sacar detrás de NPM tus servicios sensibles, como Vaultwarden, y, cuando tu homelab crezca, valorar el salto a Traefik para gestionarlo todo como código.

Fuentes

  1. Documentación oficial de Nginx Proxy Manager
  2. Repositorio de Nginx Proxy Manager en GitHub
  3. Imagen de NPM en Docker Hub

Ruta: Redes y acceso remoto seguro con Docker