Documentación completa de NGINX Proxy Manager en español

2025-11-29 17:16:45 +01:00
commit b59ece3b58
4 changed files with 1393 additions and 0 deletions

464
Backup.md Normal file

@@ -0,0 +1,464 @@
# Backup y Restauración
## ¿Qué se Respalda?
NGINX Proxy Manager almacena datos en dos volúmenes Docker:
### `npm_data` (`/data`)
- 📊 **Base de datos SQLite** (o configuración de DB externa)
- ⚙️ **Configuración de proxy hosts, redirects, streams**
- 🔑 **Access lists, usuarios, permisos**
- 📝 **Logs de acceso y errores**
- 🔧 **Configuraciones NGINX custom**
### `npm_letsencrypt` (`/etc/letsencrypt`)
- 🔒 **Certificados SSL de Let's Encrypt**
- 🔑 **Claves privadas**
- 📜 **Configuración de renovación automática**
⚠️ **Crítico**: Ambos volúmenes contienen información sensible. Protege los backups adecuadamente.
## Backup Manual
### Método 1: Backup de Volúmenes (Recomendado)
```bash
# Detener NPM (opcional, para consistencia)
docker compose down
# Backup de npm_data
docker run --rm \
-v npm_data:/data:ro \
-v $(pwd):/backup \
alpine \
tar czf /backup/npm_data-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
# Backup de npm_letsencrypt
docker run --rm \
-v npm_letsencrypt:/letsencrypt:ro \
-v $(pwd):/backup \
alpine \
tar czf /backup/npm_letsencrypt-$(date +%Y%m%d-%H%M%S).tar.gz -C /letsencrypt .
# Reiniciar NPM
docker compose up -d
```
### Método 2: Backup en Caliente
Sin detener el servicio:
```bash
# Backup de npm_data (servicio corriendo)
docker run --rm \
-v npm_data:/data:ro \
-v $(pwd):/backup \
alpine \
tar czf /backup/npm_data-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
# Backup de npm_letsencrypt
docker run --rm \
-v npm_letsencrypt:/letsencrypt:ro \
-v $(pwd):/backup \
alpine \
tar czf /backup/npm_letsencrypt-$(date +%Y%m%d-%H%M%S).tar.gz -C /letsencrypt .
```
⚠️ **Nota**: Backups en caliente pueden tener inconsistencias en la base de datos si hay escrituras durante la copia.
### Método 3: Backup de Carpetas Locales
Si usas bind mounts en lugar de volúmenes:
```yaml
# docker-compose.yaml con bind mounts
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
```
```bash
# Backup simple
tar czf npm-backup-$(date +%Y%m%d-%H%M%S).tar.gz data/ letsencrypt/
# O con rsync
rsync -av data/ /ruta/backup/npm/data/
rsync -av letsencrypt/ /ruta/backup/npm/letsencrypt/
```
## Restauración
### Restaurar desde Backup
```bash
# 1. Detener NPM si está corriendo
docker compose down
# 2. Eliminar volúmenes existentes (⚠️ cuidado!)
docker volume rm npm_data npm_letsencrypt
# 3. Crear volúmenes nuevos
docker volume create npm_data
docker volume create npm_letsencrypt
# 4. Restaurar npm_data
docker run --rm \
-v npm_data:/data \
-v $(pwd):/backup \
alpine \
tar xzf /backup/npm_data-YYYYMMDD-HHMMSS.tar.gz -C /data
# 5. Restaurar npm_letsencrypt
docker run --rm \
-v npm_letsencrypt:/letsencrypt \
-v $(pwd):/backup \
alpine \
tar xzf /backup/npm_letsencrypt-YYYYMMDD-HHMMSS.tar.gz -C /letsencrypt
# 6. Verificar permisos
docker run --rm \
-v npm_data:/data \
alpine \
chown -R root:root /data
# 7. Reiniciar NPM
docker compose up -d
```
### Verificar Restauración
```bash
# Ver logs
docker logs -f nginx-proxy-manager
# Debería ver:
# [setup ] Starting backend
# [nginx ] Starting nginx
# Acceder a UI
# http://IP:81
```
## Backup Automatizado
### Script de Backup
Crear `backup-npm.sh`:
```bash
#!/bin/bash
# Configuración
BACKUP_DIR="/var/backups/nginx-proxy-manager"
RETENTION_DAYS=30
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
# Crear directorio si no existe
mkdir -p "$BACKUP_DIR"
echo "[$(date)] Iniciando backup de NGINX Proxy Manager..."
# Backup de volúmenes
docker run --rm \
-v npm_data:/data:ro \
-v "$BACKUP_DIR":/backup \
alpine \
tar czf "/backup/npm_data-$TIMESTAMP.tar.gz" -C /data .
docker run --rm \
-v npm_letsencrypt:/letsencrypt:ro \
-v "$BACKUP_DIR":/backup \
alpine \
tar czf "/backup/npm_letsencrypt-$TIMESTAMP.tar.gz" -C /letsencrypt .
# Verificar backups
if [ -f "$BACKUP_DIR/npm_data-$TIMESTAMP.tar.gz" ] && [ -f "$BACKUP_DIR/npm_letsencrypt-$TIMESTAMP.tar.gz" ]; then
SIZE_DATA=$(du -h "$BACKUP_DIR/npm_data-$TIMESTAMP.tar.gz" | cut -f1)
SIZE_LE=$(du -h "$BACKUP_DIR/npm_letsencrypt-$TIMESTAMP.tar.gz" | cut -f1)
echo "[$(date)] Backup completado:"
echo " - npm_data: $SIZE_DATA"
echo " - npm_letsencrypt: $SIZE_LE"
else
echo "[$(date)] ERROR: Backup falló"
exit 1
fi
# Limpiar backups antiguos
echo "[$(date)] Limpiando backups antiguos (>$RETENTION_DAYS días)..."
find "$BACKUP_DIR" -name "npm_*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "[$(date)] Proceso completado"
```
Hacer ejecutable:
```bash
chmod +x backup-npm.sh
./backup-npm.sh
```
### Programar con Cron
Backup diario a las 3:00 AM:
```bash
crontab -e
# Añadir línea:
0 3 * * * /ruta/a/backup-npm.sh >> /var/log/npm-backup.log 2>&1
```
Ver logs:
```bash
tail -f /var/log/npm-backup.log
```
## Backup a Almacenamiento Remoto
### rsync a Servidor Remoto
```bash
#!/bin/bash
BACKUP_FILE="npm-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
# Crear backup local
docker run --rm \
-v npm_data:/data:ro \
-v npm_letsencrypt:/letsencrypt:ro \
-v $(pwd):/backup \
alpine \
sh -c "tar czf /backup/$BACKUP_FILE -C / data letsencrypt"
# Copiar a servidor remoto
rsync -avz --progress "$BACKUP_FILE" usuario@servidor-backup:/backups/npm/
# Opcional: eliminar backup local
rm "$BACKUP_FILE"
```
### S3 / MinIO con rclone
```bash
# Configurar rclone (una vez)
rclone config
# Script de backup a S3
BACKUP_FILE="npm-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
docker run --rm \
-v npm_data:/data:ro \
-v npm_letsencrypt:/letsencrypt:ro \
-v $(pwd):/backup \
alpine \
sh -c "tar czf /backup/$BACKUP_FILE -C / data letsencrypt"
rclone copy "$BACKUP_FILE" s3-remote:bucket-name/npm-backups/
rm "$BACKUP_FILE"
```
### Backup a NFS/CIFS
```bash
# Montar share NFS
mount -t nfs servidor.local:/backups /mnt/backups
# Backup directo a share
docker run --rm \
-v npm_data:/data:ro \
-v npm_letsencrypt:/letsencrypt:ro \
-v /mnt/backups:/backup \
alpine \
tar czf /backup/npm-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C / data letsencrypt
```
## Migración a Nuevo Servidor
### En el Servidor Antiguo
```bash
# Crear backup completo
docker run --rm \
-v npm_data:/data:ro \
-v npm_letsencrypt:/letsencrypt:ro \
-v $(pwd):/backup \
alpine \
tar czf /backup/npm-migration.tar.gz -C / data letsencrypt
# Copiar a nuevo servidor
scp npm-migration.tar.gz usuario@nuevo-servidor:/tmp/
```
### En el Servidor Nuevo
```bash
# 1. Clonar repositorio
git clone https://git.ictiberia.com/groales/npm
cd npm
# 2. Crear volúmenes
docker volume create npm_data
docker volume create npm_letsencrypt
# 3. Restaurar backup
docker run --rm \
-v npm_data:/data \
-v npm_letsencrypt:/letsencrypt \
-v /tmp:/backup \
alpine \
tar xzf /backup/npm-migration.tar.gz -C /
# 4. Iniciar NPM
docker compose up -d
# 5. Verificar
docker logs -f nginx-proxy-manager
```
## Exportar/Importar Configuración
### Solo Base de Datos (SQLite)
```bash
# Exportar solo DB
docker exec nginx-proxy-manager \
sqlite3 /data/database.sqlite .dump > npm-database-$(date +%Y%m%d).sql
# Importar DB
cat npm-database-YYYYMMDD.sql | docker exec -i nginx-proxy-manager \
sqlite3 /data/database.sqlite
```
## Reset de Contraseña Admin
Si olvidaste la contraseña:
```bash
# Método 1: Resetear a credenciales por defecto
docker compose down
# Ejecutar container temporal con script reset
docker run --rm \
-v npm_data:/data \
jc21/nginx-proxy-manager:latest \
npx knex migrate:latest --env production && npx knex seed:run --env production
docker compose up -d
# Login con:
# Email: admin@example.com
# Password: changeme
```
Método 2: SQL directo (solo SQLite):
```bash
docker exec -it nginx-proxy-manager /bin/bash
# Dentro del contenedor
sqlite3 /data/database.sqlite
-- Resetear password a 'changeme'
UPDATE auth SET secret = '$2a$10$YSwA4rB7M/xE8N1n8YCfCuYZ.9cNrwMr/L/PkZ.qXHfEqNkFN7XCy' WHERE id = 1;
.exit
exit
# Reiniciar
docker restart nginx-proxy-manager
```
## Verificación de Integridad
### Test de Restauración
```bash
# 1. Crear volúmenes de test
docker volume create npm_data_test
docker volume create npm_letsencrypt_test
# 2. Restaurar en volúmenes test
docker run --rm \
-v npm_data_test:/data \
-v npm_letsencrypt_test:/letsencrypt \
-v $(pwd):/backup \
alpine \
sh -c "tar xzf /backup/npm_data-BACKUP.tar.gz -C /data && tar xzf /backup/npm_letsencrypt-BACKUP.tar.gz -C /letsencrypt"
# 3. Iniciar NPM temporal
docker run -d \
-p 18081:81 \
--name npm-test \
-v npm_data_test:/data \
-v npm_letsencrypt_test:/etc/letsencrypt \
jc21/nginx-proxy-manager:latest
# 4. Verificar en http://localhost:18081
# 5. Limpiar
docker stop npm-test
docker rm npm-test
docker volume rm npm_data_test npm_letsencrypt_test
```
### Validar Tar
```bash
# Verificar integridad
tar tzf npm_data-YYYYMMDD-HHMMSS.tar.gz > /dev/null
echo $? # Debe devolver 0
# Ver contenido
tar tzf npm_data-YYYYMMDD-HHMMSS.tar.gz | head -20
```
## Best Practices
### Estrategia 3-2-1
-**3 copias** de datos (original + 2 backups)
-**2 tipos de medios** (local + remoto)
-**1 copia offsite** (cloud, otro datacenter)
### Frecuencia Recomendada
| Uso | Frecuencia |
|-----|------------|
| Producción crítica | Cada 6 horas |
| Producción | Diario |
| Personal/Home | Semanal |
### Retención
Ejemplo:
- Diarios: 7 días
- Semanales: 4 semanas
- Mensuales: 12 meses
### Encriptación
Para backups sensibles:
```bash
# Backup encriptado con GPG
BACKUP_FILE="npm-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
# Crear backup
docker run --rm ... tar czf /backup/$BACKUP_FILE ...
# Encriptar
gpg --symmetric --cipher-algo AES256 "$BACKUP_FILE"
# Resultado: npm-backup-YYYYMMDD-HHMMSS.tar.gz.gpg
rm "$BACKUP_FILE"
```
Desencriptar:
```bash
gpg --decrypt npm-backup-YYYYMMDD-HHMMSS.tar.gz.gpg > npm-backup.tar.gz
```
---
**Volver a**: [Página Principal](Home) | [Configuración Avanzada](Configuracion)

341
Configuracion.md Normal file

@@ -0,0 +1,341 @@
# Configuración Avanzada
## Base de Datos Externa
### MySQL / MariaDB
Para mayor rendimiento y escalabilidad, usa MySQL/MariaDB en lugar de SQLite:
```yaml
services:
app:
image: jc21/nginx-proxy-manager:latest
environment:
TZ: "Europe/Madrid"
DB_MYSQL_HOST: "db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm_password"
DB_MYSQL_NAME: "npm"
depends_on:
- db
db:
image: jc21/mariadb-aria:latest
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: "root_password"
MYSQL_DATABASE: "npm"
MYSQL_USER: "npm"
MYSQL_PASSWORD: "npm_password"
MARIADB_AUTO_UPGRADE: "1"
volumes:
- mysql_data:/var/lib/mysql
volumes:
npm_data:
npm_letsencrypt:
mysql_data:
```
### PostgreSQL
```yaml
services:
app:
environment:
DB_POSTGRES_HOST: "db"
DB_POSTGRES_PORT: "5432"
DB_POSTGRES_USER: "npm"
DB_POSTGRES_PASSWORD: "npm_password"
DB_POSTGRES_NAME: "npm"
depends_on:
- db
db:
image: postgres:17
environment:
POSTGRES_USER: "npm"
POSTGRES_PASSWORD: "npm_password"
POSTGRES_DB: "npm"
volumes:
- postgres_data:/var/lib/postgresql
volumes:
npm_data:
npm_letsencrypt:
postgres_data:
```
## Docker Secrets
Para mayor seguridad, usa secrets en lugar de variables de entorno en texto plano:
```yaml
secrets:
mysql_pwd:
file: ./secrets/mysql_password.txt
services:
app:
environment:
DB_MYSQL_HOST: "db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD__FILE: /run/secrets/mysql_pwd
DB_MYSQL_NAME: "npm"
secrets:
- mysql_pwd
```
## Redes Docker
### Conectar NPM con Otros Servicios
Crear red compartida:
```bash
docker network create proxy_network
```
NPM:
```yaml
services:
app:
networks:
- proxy_network
- npm_network
networks:
npm_network:
name: npm_network
proxy_network:
external: true
```
Otros servicios:
```yaml
services:
mi_app:
networks:
- proxy_network
networks:
proxy_network:
external: true
```
Configurar Proxy Host:
- **Forward Hostname**: `mi_app` (nombre del contenedor)
- **Forward Port**: Puerto interno (no necesitas publicarlo con `-p`)
## Configuraciones NGINX Personalizadas
NPM permite insertar configuración NGINX personalizada en diferentes ubicaciones.
### Ubicaciones de Archivos Custom
Crear directorio: `./data/nginx/custom/` (se monta desde volumen `npm_data`)
Archivos disponibles:
- `root_top.conf` - Top de nginx.conf
- `root.conf` - Final de nginx.conf
- `http_top.conf` - Top del bloque http
- `http.conf` - Final del bloque http
- `events.conf` - Final del bloque events
- `stream.conf` - Final del bloque stream
- `server_proxy.conf` - Final de cada servidor proxy
- `server_redirect.conf` - Final de cada servidor de redirección
- `server_stream.conf` - Final de cada stream
- `server_dead.conf` - Final de cada servidor 404
### Ejemplo: Rate Limiting Global
```bash
# Acceder al contenedor
docker exec -it nginx-proxy-manager /bin/bash
# Crear archivo custom
cat > /data/nginx/custom/http_top.conf << 'EOF'
# Rate limiting
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_status 429;
EOF
# Salir y recargar NGINX
exit
docker exec nginx-proxy-manager nginx -s reload
```
Aplicar en Proxy Host (pestaña Advanced):
```nginx
limit_req zone=general burst=20 nodelay;
```
### Ejemplo: Módulo GeoIP2
Habilitar módulo:
```bash
docker exec -it nginx-proxy-manager /bin/bash
cat > /data/nginx/custom/root_top.conf << 'EOF'
load_module /usr/lib/nginx/modules/ngx_http_geoip2_module.so;
load_module /usr/lib/nginx/modules/ngx_stream_geoip2_module.so;
EOF
exit
docker exec nginx-proxy-manager nginx -s reload
```
## Variables de Entorno Avanzadas
### Ejecutar como Usuario No-Root
```yaml
environment:
PUID: 1000
PGID: 1000
```
⚠️ Puede causar problemas con puertos < 1024. Solución: usar `--cap-add=NET_BIND_SERVICE`.
### Deshabilitar IPv6
```yaml
environment:
DISABLE_IPV6: 'true'
```
### Deshabilitar IP Ranges Fetch
Para entornos con acceso limitado a Internet:
```yaml
environment:
IP_RANGES_FETCH_ENABLED: 'false'
```
### Header X-FRAME-OPTIONS
```yaml
environment:
X_FRAME_OPTIONS: "sameorigin" # o "deny", "allow-from https://example.com"
```
### Usuario Admin Automático
Saltarse el setup inicial:
```yaml
environment:
INITIAL_ADMIN_EMAIL: admin@tudominio.com
INITIAL_ADMIN_PASSWORD: tu_password_segura
```
⚠️ Cambiar la contraseña inmediatamente después del primer login.
## Healthcheck
Añadir healthcheck al servicio:
```yaml
services:
app:
healthcheck:
test: ["CMD", "/usr/bin/check-health"]
interval: 10s
timeout: 3s
retries: 3
```
## Logrotate Personalizado
Por defecto NPM rota logs semanalmente (access: 4 archivos, error: 10 archivos).
Personalizar:
```bash
# logrotate.custom
/data/logs/*.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
docker exec nginx-proxy-manager nginx -s reopen
endscript
}
```
Montar en compose:
```yaml
volumes:
- npm_data:/data
- npm_letsencrypt:/etc/letsencrypt
- ./logrotate.custom:/etc/logrotate.d/nginx-proxy-manager
```
## Migración desde Otra Instancia
### Exportar desde origen
```bash
# Backup volúmenes
docker run --rm \
-v npm_data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/npm_data_backup.tar.gz -C /data .
docker run --rm \
-v npm_letsencrypt:/letsencrypt \
-v $(pwd):/backup \
alpine tar czf /backup/npm_letsencrypt_backup.tar.gz -C /letsencrypt .
```
### Importar en destino
```bash
# Crear volúmenes
docker volume create npm_data
docker volume create npm_letsencrypt
# Restaurar
docker run --rm \
-v npm_data:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/npm_data_backup.tar.gz -C /data
docker run --rm \
-v npm_letsencrypt:/letsencrypt \
-v $(pwd):/backup \
alpine tar xzf /backup/npm_letsencrypt_backup.tar.gz -C /letsencrypt
# Levantar NPM
docker compose up -d
```
## Arquitecturas Soportadas
NPM soporta múltiples arquitecturas (manifest multi-arch):
- `amd64` - Intel/AMD 64-bit
- `arm64` - ARM 64-bit (Raspberry Pi 4, Apple Silicon)
- `armv7` - ARM 32-bit (Raspberry Pi 3)
No necesitas hacer nada especial, Docker pull descarga la imagen correcta automáticamente.
### Raspberry Pi Consideraciones
Para MariaDB en ARM, usar imagen alternativa:
```yaml
db:
image: yobasystems/alpine-mariadb:latest # en lugar de jc21/mariadb-aria
```
---
**Volver a**: [Página Principal](Home) | [Certificados SSL](SSL)

244
Home.md Normal file

@@ -0,0 +1,244 @@
# NGINX Proxy Manager - Documentación
Bienvenido a la documentación del despliegue de **NGINX Proxy Manager** usando Docker Compose.
## ¿Qué es NGINX Proxy Manager?
NGINX Proxy Manager (NPM) es una interfaz de gestión intuitiva para configurar y administrar proxy inversos NGINX sin necesidad de conocimientos profundos de NGINX. Ideal para:
- 🏠 **Self-hosting casero** - Exponer servicios locales a Internet de forma segura
- 🔒 **Certificados SSL automáticos** - Let's Encrypt integrado con renovación automática
- 🌐 **Múltiples dominios** - Gestionar decenas o cientos de proxy hosts desde una UI
- 📱 **Interfaz moderna** - Administración web responsive y fácil de usar
- 🔐 **Control de acceso** - Listas de acceso y autenticación básica HTTP
## Características Principales
### Gestión de Proxy Hosts
- **Proxy Hosts**: Redirigir dominios a servicios backend (HTTP/HTTPS)
- **Redirection Hosts**: Redirecciones 301/302 permanentes o temporales
- **404 Hosts**: Páginas personalizadas para dominios no configurados
- **Streams**: Proxy TCP/UDP para servicios no-HTTP (SSH, bases de datos, etc.)
### SSL/TLS
-**Let's Encrypt gratuito** con renovación automática
-**Certificados personalizados** (upload de cert + key)
-**Wildcard certificates** vía DNS challenge
-**HTTP/2 y HTTP/3** (QUIC) support
-**Force SSL** (redirección automática HTTP → HTTPS)
-**HSTS** (HTTP Strict Transport Security)
### Seguridad
- 🔐 **Access Lists** - Restricción por IP, username/password
- 🛡️ **Headers personalizados** - X-Frame-Options, CSP, CORS
- 🚫 **Bloqueo de exploits comunes** - Configuración NGINX hardening
- 🔑 **Gestión de usuarios** - Multi-usuario con roles y permisos
## Componentes del Stack
Este repositorio despliega NPM con la siguiente configuración:
### Servicio Principal
- **Imagen**: `jc21/nginx-proxy-manager:latest`
- **Contenedor**: `nginx-proxy-manager`
- **Reinicio**: `unless-stopped`
### Puertos Expuestos
- **80**: HTTP público (redirige automáticamente a HTTPS)
- **81**: Interfaz web de administración
- **443**: HTTPS público
### Volúmenes
- `npm_data``/data` - Base de datos SQLite, configuraciones, logs
- `npm_letsencrypt``/etc/letsencrypt` - Certificados SSL de Let's Encrypt
### Red
- `npm_network` - Red dedicada para el stack
## Requisitos Previos
Antes de desplegar NPM, asegúrate de tener:
- ✅ Docker Engine y Docker Compose instalados
- ✅ Puertos 80, 443 y 81 disponibles (o configurar puertos alternativos)
- ✅ Dominio(s) apuntando al servidor (para certificados SSL)
- ✅ Acceso a Internet (para validación de Let's Encrypt)
- ✅ Firewall configurado para permitir tráfico en puertos 80/443
## Despliegue Rápido
### 1. Clonar el Repositorio
```bash
git clone https://git.ictiberia.com/groales/npm
cd npm
```
### 2. Levantar el Stack
```bash
docker compose up -d
```
### 3. Verificar el Estado
```bash
docker ps --filter name=nginx-proxy-manager
docker logs nginx-proxy-manager
```
### 4. Acceder a la Interfaz Web
Abre tu navegador en: **http://IP-del-servidor:81**
⏱️ **Primera vez**: El inicio puede tardar 1-2 minutos. Espera a ver en los logs:
```
[setup ] Starting backend
```
### 5. Login Inicial
**Credenciales por defecto**:
```
Email: admin@example.com
Password: changeme
```
🔒 **Obligatorio**: Al primer login, se te pedirá:
1. Cambiar el email
2. Cambiar el nombre de usuario
3. Establecer una nueva contraseña
## Primer Proxy Host (Guía Rápida)
### Ejemplo: Exponer Portainer con SSL
Supongamos que tienes Portainer corriendo en `192.168.1.100:9443` y quieres acceder via `https://portainer.tudominio.com`.
1. **Ir a "Hosts" → "Proxy Hosts" → "Add Proxy Host"**
2. **Pestaña "Details"**:
- **Domain Names**: `portainer.tudominio.com`
- **Scheme**: `https` (Portainer usa HTTPS)
- **Forward Hostname / IP**: `192.168.1.100`
- **Forward Port**: `9443`
- **Cache Assets**: ✅ (opcional)
- **Block Common Exploits**: ✅
- **Websockets Support**: ✅ (necesario para Portainer)
3. **Pestaña "SSL"**:
-**Request a new SSL Certificate with Let's Encrypt**
-**Force SSL** (redirigir HTTP → HTTPS)
-**HTTP/2 Support**
-**HSTS Enabled** (opcional, recomendado)
- Email: `tu@email.com` (para notificaciones de Let's Encrypt)
-**I Agree to the Let's Encrypt Terms of Service**
4. **Save**
✅ En 10-30 segundos, el certificado SSL se generará y el proxy estará activo.
Accede a: `https://portainer.tudominio.com` 🎉
## Casos de Uso Comunes
### 1. Proxy a Contenedores Docker en la Misma Red
Si tienes servicios corriendo en Docker en el mismo host:
```yaml
# En el docker-compose.yaml de tu servicio
networks:
- npm_network
networks:
npm_network:
external: true
```
Luego en NPM:
- **Forward Hostname**: Nombre del contenedor (ej: `portainer`)
- **Forward Port**: Puerto interno del contenedor (no el publicado)
### 2. Redirección Permanente
**Ejemplo**: Redirigir `www.tudominio.com``tudominio.com`
1. **"Hosts" → "Redirection Hosts" → "Add Redirection Host"**
2. **Domain Names**: `www.tudominio.com`
3. **Scheme**: `https`
4. **Forward Domain Name**: `tudominio.com`
5. **Preserve Path**: ✅
6. **HTTP Code**: `301` (permanente)
7. **SSL**: Solicitar certificado para `www.tudominio.com`
### 3. Stream TCP (Ejemplo: SSH)
**Objetivo**: Acceder a SSH del servidor via puerto 2222 externo.
1. **"Streams" → "Add Stream"**
2. **Incoming Port**: `2222`
3. **Forwarding Host**: `127.0.0.1` (localhost)
4. **Forwarding Port**: `22` (SSH)
5. **TCP Forwarding**: ✅
6. **Save**
Añadir puerto al `docker-compose.yaml`:
```yaml
ports:
- "80:80"
- "81:81"
- "443:443"
- "2222:2222" # Stream SSH
```
Reiniciar: `docker compose up -d`
Conectar: `ssh usuario@IP-servidor -p 2222`
### 4. Access List (Restringir por IP)
1. **"Access Lists" → "Add Access List"**
2. **Name**: `Solo oficina`
3. **Pass Auth**: ✅ (si quieres autenticación adicional)
4. **Authorization****Add****Username**: `admin`, **Password**: `***`
5. **Access****Allow**`192.168.1.0/24` (red local)
6. **Access****Deny**`0.0.0.0/0` (todo lo demás)
7. **Save**
Aplicar a Proxy Host:
- Editar Proxy Host → **Access List**: Seleccionar "Solo oficina"
## Próximos Pasos
- 📖 [Configuración Avanzada](Configuracion) - MySQL, secrets, custom NGINX configs
- 🔒 [Certificados SSL/TLS](SSL) - Wildcard, DNS challenge, certificados propios
- 💾 [Backup y Restauración](Backup) - Cómo respaldar y restaurar NPM
- ⚙️ [Configuración Avanzada de NGINX](Avanzado) - Custom configs, geoIP, rate limiting
## Troubleshooting Rápido
| Problema | Solución |
|----------|----------|
| Puerto 80/443 ocupado | Ver proceso: `sudo netstat -tulpn \| grep :80`, cambiar puertos en compose |
| No se genera certificado SSL | Verificar DNS apunta al servidor, puertos 80/443 abiertos en firewall |
| Olvido de contraseña | Ver [Backup](Backup#reset-password) para resetear |
| Error "Address family not supported" | Añadir `DISABLE_IPV6: 'true'` en environment |
| 502 Bad Gateway | Verificar que el backend esté corriendo y el puerto correcto |
## Recursos Oficiales
- 📘 [Documentación Oficial](https://nginxproxymanager.com/)
- 🐛 [GitHub Issues](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
- 💬 [Reddit r/nginxproxymanager](https://reddit.com/r/nginxproxymanager)
- 🐳 [Docker Hub](https://hub.docker.com/r/jc21/nginx-proxy-manager)
- 📺 [Video Tutoriales](https://www.youtube.com/results?search_query=nginx+proxy+manager)
---
**Versión**: Latest (rolling release)
**Última actualización**: Noviembre 2025

344
SSL.md Normal file

@@ -0,0 +1,344 @@
# Certificados SSL/TLS
## Let's Encrypt (Recomendado)
NPM integra Let's Encrypt para certificados SSL gratuitos y automáticos.
### Requisitos
- ✅ Dominio apuntando al servidor (registro A/AAAA en DNS)
- ✅ Puertos 80 y 443 accesibles desde Internet
- ✅ Firewall configurado para permitir tráfico entrante
### Solicitar Certificado (HTTP Challenge)
1. **Crear/Editar Proxy Host**
2. **Pestaña SSL**:
-**Request a new SSL Certificate with Let's Encrypt**
- Email: `tu@email.com` (para notificaciones de expiración)
-**Force SSL** (redirigir HTTP → HTTPS automáticamente)
-**HTTP/2 Support**
-**HSTS Enabled** (opcional, recomendado para seguridad)
-**I Agree to the Let's Encrypt Terms of Service**
3. **Save**
✅ El certificado se generará en 10-30 segundos.
### Renovación Automática
NPM verifica certificados diariamente y renueva automáticamente los que están por expirar (< 30 días).
No requiere configuración adicional.
### Certificados Wildcard (DNS Challenge)
Para certificados wildcard (`*.tudominio.com`) se requiere DNS challenge.
#### Proveedores DNS Soportados
NPM soporta +100 proveedores via Certbot plugins. Los más comunes:
- Cloudflare
- Amazon Route53
- Google Cloud DNS
- DigitalOcean
- OVH
- Namecheap
- GoDaddy
- etc.
#### Configurar DNS Challenge
**Ejemplo: Cloudflare**
1. **Obtener API Token de Cloudflare**:
- Login en Cloudflare Dashboard
- Profile → API Tokens → Create Token
- Template: "Edit zone DNS"
- Zone Resources: Include → Specific zone → `tudominio.com`
- Continue → Create Token
- Copiar token
2. **En NPM: SSL Certificates → Add SSL Certificate**:
- **Domain Names**: `*.tudominio.com`, `tudominio.com` (ambos)
-**Use a DNS Challenge**
- **DNS Provider**: `Cloudflare`
- **Credentials File Content**:
```
dns_cloudflare_api_token = TU_TOKEN_AQUI
```
- Email: `tu@email.com`
- ✅ **I Agree to the Let's Encrypt Terms of Service**
- **Save**
3. **Usar el certificado**:
- Al crear Proxy Hosts, en pestaña SSL:
- Seleccionar certificado wildcard existente
- No marcar "Request a new SSL Certificate"
#### Otros Proveedores DNS
**Amazon Route53**:
```
dns_route53_access_key_id = YOUR_ACCESS_KEY
dns_route53_secret_access_key = YOUR_SECRET_KEY
```
**Google Cloud DNS**:
```
dns_google_credentials = /path/to/credentials.json
```
**DigitalOcean**:
```
dns_digitalocean_token = YOUR_TOKEN
```
**OVH**:
```
dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = YOUR_APP_KEY
dns_ovh_application_secret = YOUR_APP_SECRET
dns_ovh_consumer_key = YOUR_CONSUMER_KEY
```
Consulta [Certbot DNS plugins](https://eff-certbot.readthedocs.io/en/stable/using.html#dns-plugins) para más proveedores.
## Certificados Propios
### Subir Certificado y Clave Privada
1. **SSL Certificates → Add SSL Certificate**
2. **Custom**:
- **Name**: Nombre descriptivo (ej: "MiEmpresa Wildcard")
- **Certificate Key**: Pegar contenido del archivo `.key`
- **Certificate**: Pegar contenido del archivo `.crt` o `.pem`
- **Intermediate Certificate**: (opcional) Cadena de certificados intermedios
- **Save**
3. **Usar en Proxy Host**:
- Pestaña SSL → Seleccionar certificado custom
- ✅ **Force SSL**
- ✅ **HTTP/2 Support**
### Formato de Certificados
#### Certificado (Certificate)
```
-----BEGIN CERTIFICATE-----
MIIFXzCCBEegAwIBAgISBGP...
... (contenido base64) ...
-----END CERTIFICATE-----
```
#### Clave Privada (Certificate Key)
```
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQ...
... (contenido base64) ...
-----END PRIVATE KEY-----
```
#### Certificado Intermedio (Intermediate Certificate)
Si tu CA proporciona cadena de certificados:
```
-----BEGIN CERTIFICATE-----
(Certificado Intermedio 1)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Certificado Intermedio 2)
-----END CERTIFICATE-----
```
### Convertir Formatos
**PFX/P12 a PEM**:
```bash
# Extraer clave privada
openssl pkcs12 -in certificate.pfx -nocerts -out key.pem -nodes
# Extraer certificado
openssl pkcs12 -in certificate.pfx -clcerts -nokeys -out cert.pem
```
**DER a PEM**:
```bash
openssl x509 -inform der -in certificate.cer -out certificate.pem
```
## HTTP/2 y HTTP/3
### HTTP/2
Habilitado por defecto al activar SSL en Proxy Host.
✅ **HTTP/2 Support** en pestaña SSL.
### HTTP/3 (QUIC)
NPM soporta HTTP/3 pero requiere configuración adicional:
```bash
docker exec -it nginx-proxy-manager /bin/bash
cat > /data/nginx/custom/server_proxy.conf << 'EOF'
# HTTP/3
listen 443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400';
EOF
exit
docker exec nginx-proxy-manager nginx -s reload
```
Abrir puerto UDP 443:
```yaml
ports:
- "80:80"
- "81:81"
- "443:443"
- "443:443/udp" # HTTP/3
```
## HSTS (HTTP Strict Transport Security)
HSTS fuerza a los navegadores a usar HTTPS siempre.
### Habilitar en Proxy Host
Pestaña SSL:
- ✅ **HSTS Enabled**
- **HSTS Subdomains** (opcional, incluye subdominios)
Esto añade el header:
```
Strict-Transport-Security: max-age=31536000; includeSubDomains
```
### HSTS Preload
Para máxima seguridad, añadir tu dominio al [HSTS Preload List](https://hstspreload.org/).
Configuración custom:
```nginx
# En Proxy Host → Advanced → Custom Nginx Configuration
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
```
Luego enviar dominio a hstspreload.org.
## Configuración Avanzada de SSL
### Cipher Suites Personalizados
Para mayor compatibilidad o seguridad:
```nginx
# En /data/nginx/custom/server_proxy.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
```
### OCSP Stapling
Mejora rendimiento SSL:
```nginx
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/tudominio.com/chain.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
```
### Session Cache
Reducir overhead de handshakes SSL:
```nginx
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
```
## Troubleshooting
### Error: DNS Challenge Failed
**Síntomas**: Certificado wildcard no se genera.
**Causas**:
- API token/credenciales incorrectas
- Permisos insuficientes del token
- Propagación DNS lenta
**Soluciones**:
```bash
# Ver logs detallados
docker logs nginx-proxy-manager | grep certbot
# Verificar permisos de token (Cloudflare)
# Token debe tener: Zone:DNS:Edit
# Esperar propagación DNS (puede tardar minutos)
```
### Error: Rate Limit Exceeded
Let's Encrypt tiene límites:
- **5 certificados por dominio/semana**
- **50 certificados por cuenta/semana**
**Solución**:
- Esperar 7 días para reset
- Usar certificados wildcard (cubre múltiples subdominios con 1 cert)
- Durante desarrollo, usar [staging environment](https://letsencrypt.org/docs/staging-environment/)
### Certificado No Se Renueva
**Verificar**:
```bash
# Ver logs de renovación
docker logs nginx-proxy-manager | grep renew
# Listar certificados
docker exec nginx-proxy-manager certbot certificates
```
**Forzar renovación manual**:
```bash
docker exec nginx-proxy-manager certbot renew --force-renewal
docker exec nginx-proxy-manager nginx -s reload
```
### Error: Port 80 Not Available
Let's Encrypt HTTP challenge requiere puerto 80.
**Si puerto 80 no está disponible**:
1. Usa DNS challenge (wildcard)
2. O libera puerto 80 temporalmente
### Verificar Certificado SSL
**Desde línea de comandos**:
```bash
# Ver detalles del certificado
echo | openssl s_client -servername tudominio.com -connect tudominio.com:443 2>/dev/null | openssl x509 -noout -dates
# Test desde exterior
curl -vI https://tudominio.com 2>&1 | grep -i ssl
# SSL Labs test (rating A-F)
# https://www.ssllabs.com/ssltest/analyze.html?d=tudominio.com
```
---
**Volver a**: [Página Principal](Home) | [Configuración Avanzada](Configuracion)