Adding documentation
This commit is contained in:
368
README.md
Normal file
368
README.md
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
# Portainer Stacks Repository
|
||||||
|
|
||||||
|
Este repositorio contiene la configuración de Portainer y múltiples stacks de servicios Docker gestionados mediante Docker Compose.
|
||||||
|
|
||||||
|
## 📋 Tabla de Contenidos
|
||||||
|
|
||||||
|
- [Descripción](#descripción)
|
||||||
|
- [Arquitectura](#arquitectura)
|
||||||
|
- [Prerequisitos](#prerequisitos)
|
||||||
|
- [Instalación y Despliegue](#instalación-y-despliegue)
|
||||||
|
- [Stacks Disponibles](#stacks-disponibles)
|
||||||
|
- [Configuración](#configuración)
|
||||||
|
- [Uso](#uso)
|
||||||
|
|
||||||
|
## 📖 Descripción
|
||||||
|
|
||||||
|
Este proyecto proporciona una infraestructura completa de servicios containerizados utilizando:
|
||||||
|
- **Portainer** como gestor visual de contenedores Docker
|
||||||
|
- **Traefik** como reverse proxy con certificados SSL automáticos
|
||||||
|
- **Authentik** para autenticación SSO
|
||||||
|
- Múltiples servicios adicionales (Gitea, n8n, AdGuard, etc.)
|
||||||
|
|
||||||
|
## 🏗️ Arquitectura
|
||||||
|
|
||||||
|
La arquitectura sigue este orden de despliegue:
|
||||||
|
|
||||||
|
1. **Portainer** (gestor de contenedores) - acceso directo por puerto 9443
|
||||||
|
2. **Traefik** (reverse proxy) - desplegado desde Portainer
|
||||||
|
3. **Authentik** (SSO) - desplegado desde Portainer
|
||||||
|
4. **Resto de stacks** - desplegables desde Portainer
|
||||||
|
|
||||||
|
Todos los servicios se comunican a través de la red Docker `proxy` y están protegidos por Traefik con SSL.
|
||||||
|
|
||||||
|
> **⚠️ Importante**: Los registros DNS deben estar configurados ANTES de desplegar Traefik y Authentik para que los certificados SSL se generen correctamente.
|
||||||
|
|
||||||
|
## ✅ Prerequisitos
|
||||||
|
|
||||||
|
- Docker Engine (20.10+)
|
||||||
|
- Docker Compose (v2.0+)
|
||||||
|
- Dominio(s) configurado(s) apuntando a tu servidor
|
||||||
|
- Puertos 80 y 443 abiertos (o 9443 para modo directo)
|
||||||
|
|
||||||
|
## 🚀 Instalación y Despliegue
|
||||||
|
|
||||||
|
### Paso 1: Clonar el Repositorio
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <repository-url>
|
||||||
|
cd Portainer_repo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Paso 2: Crear la Red de Docker
|
||||||
|
|
||||||
|
Todos los servicios comparten la red `proxy`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker network create proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
### Paso 3: Preparar Secretos de Portainer
|
||||||
|
|
||||||
|
Crea el archivo de secreto para la clave de cifrado de Portainer:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Crear directorio para secretos
|
||||||
|
sudo mkdir -p /opt/portainer/secrets
|
||||||
|
|
||||||
|
# Generar una clave aleatoria de 32 caracteres
|
||||||
|
openssl rand -base64 32 | sudo tee /opt/portainer/secrets/portainer
|
||||||
|
|
||||||
|
# Asegurar permisos correctos
|
||||||
|
sudo chmod 600 /opt/portainer/secrets/portainer
|
||||||
|
```
|
||||||
|
|
||||||
|
### Paso 4: Desplegar Portainer (PRIMERO)
|
||||||
|
|
||||||
|
Despliega Portainer con acceso directo por puerto 9443:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.9443.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifica que Portainer esté corriendo:
|
||||||
|
```bash
|
||||||
|
docker ps | grep portainer
|
||||||
|
```
|
||||||
|
|
||||||
|
Accede a: `https://tu-servidor:9443`
|
||||||
|
|
||||||
|
### Paso 5: Configuración Inicial de Portainer
|
||||||
|
|
||||||
|
1. Accede a Portainer mediante `https://tu-servidor:9443`
|
||||||
|
2. Crea el usuario administrador (primera vez - tienes 5 minutos)
|
||||||
|
3. Selecciona el entorno Docker local
|
||||||
|
4. Completa la configuración inicial
|
||||||
|
|
||||||
|
### Paso 6: Configurar Registros DNS
|
||||||
|
|
||||||
|
**Antes de desplegar Traefik y Authentik**, configura los registros DNS:
|
||||||
|
|
||||||
|
- Registro A para Traefik Dashboard (ej: `traefik.tudominio.com`)
|
||||||
|
- Registro A para Portainer UI (ej: `portainer.tudominio.com`)
|
||||||
|
- Registro A para Portainer API (ej: `portainer-api.tudominio.com`)
|
||||||
|
- Registro A para Authentik (ej: `auth.tudominio.com`)
|
||||||
|
- Cualquier otro dominio que vayas a usar
|
||||||
|
|
||||||
|
> **⏰ Espera** a que los registros DNS se propaguen antes de continuar (puede tardar de minutos a horas).
|
||||||
|
|
||||||
|
Verifica la propagación:
|
||||||
|
```bash
|
||||||
|
nslookup traefik.tudominio.com
|
||||||
|
nslookup portainer.tudominio.com
|
||||||
|
nslookup auth.tudominio.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Paso 7: Desplegar Traefik desde Portainer
|
||||||
|
|
||||||
|
1. En Portainer, ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `traefik`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `Traefik/docker-compose.yml`
|
||||||
|
5. Añade el archivo de variables de entorno: `Traefik/stack.env` (o configúralas manualmente)
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
Verifica que Traefik esté funcionando:
|
||||||
|
```bash
|
||||||
|
docker logs traefik
|
||||||
|
```
|
||||||
|
|
||||||
|
### Paso 8: Desplegar Authentik desde Portainer
|
||||||
|
|
||||||
|
1. En Portainer, ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `authentik`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `authentik/docker-compose.yml`
|
||||||
|
5. Añade las variables de entorno necesarias
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
#### Configuración de Authentik
|
||||||
|
|
||||||
|
Una vez desplegado Authentik, necesitarás configurar:
|
||||||
|
- **Applications** (aplicaciones a proteger)
|
||||||
|
- **Providers** de tipo Forward Auth
|
||||||
|
- **Authorization Flow** de tipo Implicit
|
||||||
|
- **Outposts** para ejecutar los providers
|
||||||
|
- **Middleware** en Traefik
|
||||||
|
|
||||||
|
Para instrucciones detalladas, consulta el [README de Authentik](authentik/README.md).
|
||||||
|
|
||||||
|
### Paso 9: Configurar Variables de Entorno para Portainer UI
|
||||||
|
|
||||||
|
Una vez Traefik y Authentik están funcionando, actualiza el archivo `.env` en la raíz del proyecto:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Variables principales a configurar:
|
||||||
|
- `PORTAINER_DOMAIN`: Tu dominio para Portainer UI (ej: `portainer.tudominio.com`)
|
||||||
|
- `PORTAINER_API_DOMAIN`: Tu dominio para la API de Portainer (ej: `portainer-api.tudominio.com`)
|
||||||
|
- `PORTAINER_API_IP_WHITELIST`: IPs permitidas para acceso directo a la API
|
||||||
|
- `TRAEFIK_AUTH_MIDDLEWARE`: Middleware de autenticación (ej: `authentik@docker`)
|
||||||
|
|
||||||
|
### Paso 10: Actualizar Stack de Portainer (Opcional)
|
||||||
|
|
||||||
|
Si deseas acceder a Portainer mediante dominio con SSL (en lugar del puerto 9443):
|
||||||
|
|
||||||
|
1. En Portainer, ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `portainer`
|
||||||
|
3. Selecciona **Upload** y sube el archivo `docker-compose.yml` de la raíz
|
||||||
|
4. O usa **Repository** apuntando a la raíz del repositorio
|
||||||
|
5. Añade las variables de entorno del archivo `.env`
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
> **Nota**: Esto reemplazará el despliegue inicial por puerto 9443 con acceso mediante dominio.
|
||||||
|
|
||||||
|
### Paso 11: Desplegar Otros Stacks desde Portainer
|
||||||
|
|
||||||
|
Una vez la infraestructura base está funcionando, puedes desplegar el resto de stacks:
|
||||||
|
|
||||||
|
#### Método 1: Desde la UI de Portainer (Recomendado)
|
||||||
|
|
||||||
|
1. Ve a **Stacks** → **Add stack**
|
||||||
|
2. Selecciona **Repository**
|
||||||
|
3. Configura el repositorio Git:
|
||||||
|
- URL: `<tu-repositorio>`
|
||||||
|
- Reference: `main` (o tu rama)
|
||||||
|
- Compose path: `<stack-name>/docker-compose.yml`
|
||||||
|
4. Añade variables de entorno si es necesario
|
||||||
|
5. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
#### Método 2: Desde línea de comandos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ejemplo: Desplegar Authentik
|
||||||
|
cd authentik
|
||||||
|
docker compose up -d
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Ejemplo: Desplegar Gitea
|
||||||
|
cd gitea
|
||||||
|
docker compose up -d
|
||||||
|
cd ..
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 Stacks Disponibles
|
||||||
|
|
||||||
|
| Stack | Descripción | Carpeta | Documentación |
|
||||||
|
|-------|-------------|---------|---------------|
|
||||||
|
| **Traefik** | Reverse proxy con SSL automático | `Traefik/` | [README](Traefik/README.md) |
|
||||||
|
| **Portainer** | Gestor visual de Docker | Raíz (docker-compose.yml) | - |
|
||||||
|
| **Authentik** | Sistema de autenticación SSO (Forward Auth) | `authentik/` | [README](authentik/README.md) |
|
||||||
|
| **Gitea** | Servidor Git autoalojado con Actions | `gitea/` | [README](gitea/README.md) |
|
||||||
|
| **n8n** | Plataforma de automatización de workflows | `n8n/` | [README](n8n/README.md) |
|
||||||
|
| **AdGuard** | Bloqueador de anuncios DNS con DoT | `adguard/` | [README](adguard/README.md) |
|
||||||
|
| **Trilium** | Aplicación de notas jerárquicas | `trilium/` | [README](trilium/README.md) |
|
||||||
|
| **Wireguard** | VPN rápida y segura | `wireguard/` | [README](wireguard/README.md) |
|
||||||
|
| **Ruleta** | Aplicación Next.js personalizada | `ruleta/` | [README](ruleta/README.md) |
|
||||||
|
|
||||||
|
> **📖 Nota**: Cada stack tiene su propio README con instrucciones detalladas de configuración, uso y troubleshooting.
|
||||||
|
|
||||||
|
## ⚙️ Configuración
|
||||||
|
|
||||||
|
### Archivo .env Principal
|
||||||
|
|
||||||
|
El archivo `.env` en la raíz contiene las configuraciones globales:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Imagen de Portainer
|
||||||
|
PORTAINER_IMAGE=portainer/portainer-ce:latest
|
||||||
|
|
||||||
|
# Rutas de almacenamiento
|
||||||
|
PORTAINER_SECRET_PATH=/opt/portainer/secrets/portainer
|
||||||
|
PORTAINER_DATA_PATH=/opt/portainer/data
|
||||||
|
|
||||||
|
# Configuración de red y proxy
|
||||||
|
TRAEFIK_DOCKER_NETWORK=proxy
|
||||||
|
TRAEFIK_ENTRYPOINT_SECURE=websecure
|
||||||
|
TRAEFIK_CERTRESOLVER=letsencrypt
|
||||||
|
|
||||||
|
# Dominios
|
||||||
|
PORTAINER_DOMAIN=portainer.example.com
|
||||||
|
PORTAINER_API_DOMAIN=portainer-api.example.com
|
||||||
|
|
||||||
|
# Seguridad
|
||||||
|
PORTAINER_API_IP_WHITELIST=10.8.0.0/24,172.18.0.1/32
|
||||||
|
TRAEFIK_AUTH_MIDDLEWARE=authentik@docker
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuraciones por Stack
|
||||||
|
|
||||||
|
Cada stack puede tener su propio archivo `stack.env` o `.env` en su carpeta correspondiente.
|
||||||
|
|
||||||
|
## 🎯 Uso
|
||||||
|
|
||||||
|
### Ver Logs de Portainer
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker logs -f portainer
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ver Estado de Todos los Contenedores
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker ps -a
|
||||||
|
```
|
||||||
|
|
||||||
|
### Actualizar Portainer
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reiniciar un Stack
|
||||||
|
|
||||||
|
Desde Portainer UI o:
|
||||||
|
```bash
|
||||||
|
cd <stack-folder>
|
||||||
|
docker compose restart
|
||||||
|
```
|
||||||
|
|
||||||
|
### Eliminar un Stack
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd <stack-folder>
|
||||||
|
docker compose down
|
||||||
|
# Para eliminar también volúmenes:
|
||||||
|
docker compose down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 Seguridad
|
||||||
|
|
||||||
|
### Acceso a Portainer UI
|
||||||
|
|
||||||
|
- **Protegido por SSO**: La UI principal está protegida mediante Authentik (configurable con `TRAEFIK_AUTH_MIDDLEWARE`)
|
||||||
|
- **Dominio**: Accesible solo mediante el dominio configurado con SSL
|
||||||
|
|
||||||
|
### Acceso a API de Portainer
|
||||||
|
|
||||||
|
- **Whitelist IP**: La API está restringida a IPs específicas (VPN, localhost)
|
||||||
|
- **Dominio separado**: Usa un dominio diferente sin SSO para apps móviles
|
||||||
|
- **SSL**: Todo el tráfico está cifrado
|
||||||
|
|
||||||
|
### Base de Datos Cifrada
|
||||||
|
|
||||||
|
Portainer utiliza una clave de cifrado para proteger su base de datos, montada en:
|
||||||
|
- `/run/secrets/portainer`
|
||||||
|
- `/run/portainer/portainer`
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### Portainer no arranca
|
||||||
|
|
||||||
|
1. Verifica que la red `proxy` existe: `docker network ls | grep proxy`
|
||||||
|
2. Revisa los logs: `docker logs portainer`
|
||||||
|
3. Verifica que el archivo de secreto existe y tiene permisos correctos
|
||||||
|
4. Verifica que el puerto 9443 no esté ocupado: `sudo netstat -tulpn | grep 9443`
|
||||||
|
|
||||||
|
### No puedo acceder mediante dominio
|
||||||
|
|
||||||
|
1. Verifica que el dominio apunta a tu servidor: `nslookup tudominio.com`
|
||||||
|
2. Verifica que los registros DNS están propagados
|
||||||
|
3. Verifica que Traefik esté corriendo: `docker ps | grep traefik`
|
||||||
|
4. Verifica la configuración de Traefik: `docker logs traefik`
|
||||||
|
5. Revisa las labels de Traefik en el docker-compose.yml
|
||||||
|
6. Verifica que los puertos 80 y 443 estén abiertos: `sudo netstat -tulpn | grep -E ':(80|443)'`
|
||||||
|
7. Como respaldo, siempre puedes acceder por `https://tu-servidor:9443`
|
||||||
|
|
||||||
|
### Error de permisos con volúmenes (SELinux)
|
||||||
|
|
||||||
|
Si usas SELinux, los volúmenes ya tienen la opción `:Z` configurada. Si persisten problemas:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo chcon -Rt svirt_sandbox_file_t /opt/portainer/data
|
||||||
|
```
|
||||||
|
|
||||||
|
### Authentik no protege los servicios
|
||||||
|
|
||||||
|
1. Verifica que el outpost esté corriendo y en estado **Healthy**
|
||||||
|
2. Revisa que las aplicaciones y providers estén correctamente configurados
|
||||||
|
3. Verifica que el authorization flow sea de tipo **Implicit**
|
||||||
|
4. Comprueba que el middleware de Traefik esté correctamente referenciado en las labels
|
||||||
|
5. Revisa los logs de Authentik: `docker logs authentik-server`
|
||||||
|
6. Verifica la conectividad entre Traefik y Authentik en la red `proxy`
|
||||||
|
|
||||||
|
## 📝 Notas Adicionales
|
||||||
|
|
||||||
|
- **Orden de despliegue**: Siempre desplegar Portainer (9443) → Traefik → Authentik → Resto de stacks
|
||||||
|
- **Registros DNS**: Configurar ANTES de desplegar Traefik para que Let's Encrypt funcione correctamente
|
||||||
|
- **Puerto 9443**: Mantén el acceso por puerto 9443 como respaldo en caso de problemas con Traefik
|
||||||
|
- **Backups**: Considera hacer backup regular de `/opt/portainer/data` y el archivo de secretos
|
||||||
|
- **Actualizaciones**: Actualiza las imágenes regularmente desde Portainer UI
|
||||||
|
- **Monitoreo**: Usa Portainer para monitorear recursos y logs de todos los contenedores
|
||||||
|
|
||||||
|
## 📄 Licencia
|
||||||
|
|
||||||
|
Consulta el archivo LICENSE en este repositorio.
|
||||||
|
|
||||||
|
## 🤝 Contribuciones
|
||||||
|
|
||||||
|
Las contribuciones son bienvenidas. Por favor, abre un issue o pull request para sugerencias o mejoras.
|
||||||
312
Traefik/README.md
Normal file
312
Traefik/README.md
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
# Traefik - Reverse Proxy
|
||||||
|
|
||||||
|
Traefik es un reverse proxy moderno que gestiona automáticamente certificados SSL con Let's Encrypt y enruta el tráfico a tus servicios.
|
||||||
|
|
||||||
|
## 📋 Descripción
|
||||||
|
|
||||||
|
Este stack despliega Traefik configurado para:
|
||||||
|
- Redirección automática HTTP → HTTPS
|
||||||
|
- Certificados SSL automáticos con Let's Encrypt
|
||||||
|
- Integración con Docker para descubrimiento automático de servicios
|
||||||
|
- Dashboard web para monitoreo
|
||||||
|
- Soporte para configuración dinámica mediante archivos
|
||||||
|
|
||||||
|
## 🚀 Despliegue
|
||||||
|
|
||||||
|
### Prerequisitos
|
||||||
|
|
||||||
|
1. **Red Docker**: Crear la red `proxy`
|
||||||
|
```bash
|
||||||
|
docker network create proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Registros DNS**: Configurar los registros A para todos tus dominios apuntando a tu servidor
|
||||||
|
|
||||||
|
3. **Directorios**: Crear los directorios necesarios
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /opt/traefik/dynamic
|
||||||
|
sudo mkdir -p /opt/traefik/letsencrypt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Desde Portainer
|
||||||
|
|
||||||
|
1. Ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `traefik`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `Traefik/docker-compose.yml`
|
||||||
|
5. Carga el archivo de variables de entorno: `Traefik/stack.env`
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
### Variables de Entorno
|
||||||
|
|
||||||
|
Edita el archivo `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Imagen de Traefik
|
||||||
|
TRAEFIK_IMAGE=traefik:v3.2
|
||||||
|
|
||||||
|
# Red Docker
|
||||||
|
TRAEFIK_DOCKER_NETWORK=proxy
|
||||||
|
|
||||||
|
# Puertos
|
||||||
|
TRAEFIK_HTTP_PORT=80
|
||||||
|
TRAEFIK_HTTPS_PORT=443
|
||||||
|
|
||||||
|
# Let's Encrypt
|
||||||
|
TRAEFIK_ACME_EMAIL=tu-email@ejemplo.com
|
||||||
|
TRAEFIK_ACME_STORAGE=/letsencrypt/acme.json
|
||||||
|
|
||||||
|
# Nivel de log (DEBUG, INFO, WARN, ERROR)
|
||||||
|
TRAEFIK_LOG_LEVEL=INFO
|
||||||
|
|
||||||
|
# Directorios
|
||||||
|
TRAEFIK_DYNAMIC_DIR=/opt/traefik/dynamic
|
||||||
|
TRAEFIK_LETSENCRYPT_DIR=/opt/traefik/letsencrypt
|
||||||
|
```
|
||||||
|
|
||||||
|
> **⚠️ Importante**: Cambia `TRAEFIK_ACME_EMAIL` con tu email real.
|
||||||
|
|
||||||
|
## ⚙️ Configuración
|
||||||
|
|
||||||
|
### Características Principales
|
||||||
|
|
||||||
|
- **Redirección automática**: Todo el tráfico HTTP (puerto 80) se redirige automáticamente a HTTPS (puerto 443)
|
||||||
|
- **Let's Encrypt**: Certificados SSL automáticos mediante HTTP Challenge
|
||||||
|
- **Docker Provider**: Detecta automáticamente servicios Docker con labels de Traefik
|
||||||
|
- **File Provider**: Permite configuración dinámica mediante archivos en `/opt/traefik/dynamic`
|
||||||
|
|
||||||
|
### Configuración Dinámica
|
||||||
|
|
||||||
|
Puedes añadir configuraciones adicionales en `/opt/traefik/dynamic/`. Ejemplo:
|
||||||
|
|
||||||
|
**Archivo: `/opt/traefik/dynamic/middlewares.yml`**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
# Middleware de seguridad
|
||||||
|
security-headers:
|
||||||
|
headers:
|
||||||
|
stsSeconds: 31536000
|
||||||
|
stsIncludeSubdomains: true
|
||||||
|
stsPreload: true
|
||||||
|
contentTypeNosniff: true
|
||||||
|
frameDeny: true
|
||||||
|
|
||||||
|
# Middleware de compresión
|
||||||
|
compression:
|
||||||
|
compress: {}
|
||||||
|
|
||||||
|
# Rate limiting
|
||||||
|
rate-limit:
|
||||||
|
rateLimit:
|
||||||
|
average: 100
|
||||||
|
burst: 50
|
||||||
|
```
|
||||||
|
|
||||||
|
### Acceso al Dashboard
|
||||||
|
|
||||||
|
El dashboard está deshabilitado por defecto (`api.insecure=false`). Para habilitarlo de forma segura:
|
||||||
|
|
||||||
|
**Opción 1: Mediante Traefik con Authentik**
|
||||||
|
|
||||||
|
Añade las siguientes labels al servicio de Traefik:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
traefik.http.routers.dashboard.rule: "Host(`traefik.tudominio.com`)"
|
||||||
|
traefik.http.routers.dashboard.entrypoints: "websecure"
|
||||||
|
traefik.http.routers.dashboard.tls.certresolver: "letsencrypt"
|
||||||
|
traefik.http.routers.dashboard.service: "api@internal"
|
||||||
|
traefik.http.routers.dashboard.middlewares: "authentik@docker"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Opción 2: Acceso local (inseguro - solo desarrollo)**
|
||||||
|
|
||||||
|
Cambia en el `docker-compose.yml`:
|
||||||
|
```yaml
|
||||||
|
- "--api.insecure=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
Luego expón el puerto:
|
||||||
|
```yaml
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
```
|
||||||
|
|
||||||
|
Accede a: `http://tu-servidor:8080/dashboard/`
|
||||||
|
|
||||||
|
## 🔧 Uso con Servicios
|
||||||
|
|
||||||
|
### Ejemplo: Proteger un servicio con Traefik
|
||||||
|
|
||||||
|
En el `docker-compose.yml` de tu servicio:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
mi-servicio:
|
||||||
|
image: mi-imagen:latest
|
||||||
|
networks:
|
||||||
|
- proxy
|
||||||
|
labels:
|
||||||
|
# Habilitar Traefik
|
||||||
|
traefik.enable: "true"
|
||||||
|
traefik.docker.network: "proxy"
|
||||||
|
|
||||||
|
# Router
|
||||||
|
traefik.http.routers.mi-servicio.rule: "Host(`miservicio.tudominio.com`)"
|
||||||
|
traefik.http.routers.mi-servicio.entrypoints: "websecure"
|
||||||
|
traefik.http.routers.mi-servicio.tls.certresolver: "letsencrypt"
|
||||||
|
|
||||||
|
# Service (puerto interno del contenedor)
|
||||||
|
traefik.http.services.mi-servicio.loadbalancer.server.port: "80"
|
||||||
|
|
||||||
|
# Middleware (opcional)
|
||||||
|
traefik.http.routers.mi-servicio.middlewares: "authentik@docker"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
proxy:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ejemplo: Servicio con múltiples rutas
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
# UI protegida con SSO
|
||||||
|
traefik.http.routers.app-ui.rule: "Host(`app.tudominio.com`)"
|
||||||
|
traefik.http.routers.app-ui.entrypoints: "websecure"
|
||||||
|
traefik.http.routers.app-ui.tls.certresolver: "letsencrypt"
|
||||||
|
traefik.http.routers.app-ui.middlewares: "authentik@docker"
|
||||||
|
traefik.http.routers.app-ui.priority: "10"
|
||||||
|
|
||||||
|
# API pública sin protección
|
||||||
|
traefik.http.routers.app-api.rule: "Host(`app.tudominio.com`) && PathPrefix(`/api`)"
|
||||||
|
traefik.http.routers.app-api.entrypoints: "websecure"
|
||||||
|
traefik.http.routers.app-api.tls.certresolver: "letsencrypt"
|
||||||
|
traefik.http.routers.app-api.priority: "20"
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Nota**: Mayor `priority` = mayor prioridad. Las rutas más específicas deben tener mayor prioridad.
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### Los certificados SSL no se generan
|
||||||
|
|
||||||
|
1. Verifica que los registros DNS están configurados correctamente:
|
||||||
|
```bash
|
||||||
|
nslookup tudominio.com
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica que los puertos 80 y 443 están abiertos:
|
||||||
|
```bash
|
||||||
|
sudo netstat -tulpn | grep -E ':(80|443)'
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Revisa los logs de Traefik:
|
||||||
|
```bash
|
||||||
|
docker logs traefik
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Verifica el archivo de almacenamiento ACME:
|
||||||
|
```bash
|
||||||
|
ls -lh /opt/traefik/letsencrypt/acme.json
|
||||||
|
# Debe tener permisos 600
|
||||||
|
sudo chmod 600 /opt/traefik/letsencrypt/acme.json
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Comprueba los límites de Let's Encrypt:
|
||||||
|
- Let's Encrypt tiene límite de 5 certificados duplicados por semana
|
||||||
|
- Usa staging para pruebas: `--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory`
|
||||||
|
|
||||||
|
### Un servicio no es accesible
|
||||||
|
|
||||||
|
1. Verifica que el servicio está en la red `proxy`:
|
||||||
|
```bash
|
||||||
|
docker network inspect proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Revisa las labels de Traefik en el servicio:
|
||||||
|
```bash
|
||||||
|
docker inspect nombre-servicio | grep -A 20 Labels
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica los logs de Traefik:
|
||||||
|
```bash
|
||||||
|
docker logs traefik | grep nombre-servicio
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Comprueba que `traefik.enable: "true"` está configurado
|
||||||
|
|
||||||
|
### Error "Gateway Timeout" o "Bad Gateway"
|
||||||
|
|
||||||
|
1. Verifica que el puerto del servicio es correcto:
|
||||||
|
```yaml
|
||||||
|
traefik.http.services.mi-servicio.loadbalancer.server.port: "PUERTO_CORRECTO"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica que el servicio está corriendo:
|
||||||
|
```bash
|
||||||
|
docker ps | grep mi-servicio
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Comprueba la conectividad desde Traefik al servicio:
|
||||||
|
```bash
|
||||||
|
docker exec traefik ping nombre-servicio
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dashboard no accesible
|
||||||
|
|
||||||
|
1. Si habilitaste `api.insecure=true`, accede a: `http://IP:8080/dashboard/`
|
||||||
|
2. Si usas dominio, verifica las labels y que el DNS está configurado
|
||||||
|
3. Revisa los logs: `docker logs traefik`
|
||||||
|
|
||||||
|
## 📚 Recursos Adicionales
|
||||||
|
|
||||||
|
- [Documentación oficial de Traefik](https://doc.traefik.io/traefik/)
|
||||||
|
- [Traefik con Docker](https://doc.traefik.io/traefik/providers/docker/)
|
||||||
|
- [Let's Encrypt con Traefik](https://doc.traefik.io/traefik/https/acme/)
|
||||||
|
- [Middlewares de Traefik](https://doc.traefik.io/traefik/middlewares/overview/)
|
||||||
|
|
||||||
|
## 🔒 Seguridad
|
||||||
|
|
||||||
|
- **Dashboard**: Protege siempre el dashboard con autenticación (Authentik, BasicAuth, etc.)
|
||||||
|
- **Logs**: Considera cambiar el nivel de log a `WARN` o `ERROR` en producción
|
||||||
|
- **Rate Limiting**: Implementa rate limiting en servicios públicos
|
||||||
|
- **Headers de seguridad**: Usa middlewares para añadir headers de seguridad
|
||||||
|
|
||||||
|
## 💾 Backups
|
||||||
|
|
||||||
|
Realiza backups regulares de:
|
||||||
|
- `/opt/traefik/letsencrypt/acme.json` (certificados SSL)
|
||||||
|
- `/opt/traefik/dynamic/` (configuración dinámica)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup
|
||||||
|
sudo tar -czf traefik-backup-$(date +%Y%m%d).tar.gz /opt/traefik/
|
||||||
|
|
||||||
|
# Restaurar
|
||||||
|
sudo tar -xzf traefik-backup-YYYYMMDD.tar.gz -C /
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 Actualizaciones
|
||||||
|
|
||||||
|
Para actualizar Traefik:
|
||||||
|
|
||||||
|
1. En Portainer, ve al stack de Traefik
|
||||||
|
2. Edita el archivo `stack.env` y cambia la versión:
|
||||||
|
```env
|
||||||
|
TRAEFIK_IMAGE=traefik:v3.3
|
||||||
|
```
|
||||||
|
3. Haz clic en **Update the stack**
|
||||||
|
4. O desde línea de comandos:
|
||||||
|
```bash
|
||||||
|
cd Traefik
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
> **⚠️ Nota**: Revisa el [changelog de Traefik](https://github.com/traefik/traefik/releases) antes de actualizar versiones mayores.
|
||||||
367
adguard/README.md
Normal file
367
adguard/README.md
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
# AdGuard Home - Bloqueador de Anuncios DNS
|
||||||
|
|
||||||
|
AdGuard Home es un servidor DNS que bloquea anuncios y rastreadores a nivel de red.
|
||||||
|
|
||||||
|
## 📋 Descripción
|
||||||
|
|
||||||
|
Este stack despliega AdGuard Home con:
|
||||||
|
- Bloqueo de anuncios y rastreadores
|
||||||
|
- DNS-over-TLS (DoT) para privacidad
|
||||||
|
- Panel web protegido con Authentik
|
||||||
|
- Integración con Traefik para HTTPS
|
||||||
|
- Configuración persistente
|
||||||
|
|
||||||
|
## 🚀 Despliegue
|
||||||
|
|
||||||
|
### Prerequisitos
|
||||||
|
|
||||||
|
1. **Red Docker**: Asegúrate de que la red `proxy` existe
|
||||||
|
2. **Registro DNS**: Configura el registro A para tu dominio AdGuard
|
||||||
|
3. **IP Fija**: AdGuard necesita una IP fija en la red Docker
|
||||||
|
4. **Certificados DoT**: Necesitarás certificados SSL para DoT
|
||||||
|
|
||||||
|
### Configurar IP Fija en la Red Proxy
|
||||||
|
|
||||||
|
Primero, verifica el rango de IPs de la red `proxy`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker network inspect proxy | grep Subnet
|
||||||
|
```
|
||||||
|
|
||||||
|
Luego, elige una IP fija dentro del rango (ej: `172.18.0.10`).
|
||||||
|
|
||||||
|
### Generar Certificados para DoT
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Crear directorio para certificados
|
||||||
|
sudo mkdir -p /opt/adguard/certs
|
||||||
|
|
||||||
|
# Copiar certificados de Let's Encrypt (después de que Traefik los genere)
|
||||||
|
sudo cp /opt/traefik/letsencrypt/certificates/adguard.tudominio.com.crt /opt/adguard/certs/adguard.crt
|
||||||
|
sudo cp /opt/traefik/letsencrypt/certificates/adguard.tudominio.com.key /opt/adguard/certs/adguard.key
|
||||||
|
|
||||||
|
# O genera certificados autofirmados para pruebas
|
||||||
|
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||||
|
-keyout /opt/adguard/certs/adguard.key \
|
||||||
|
-out /opt/adguard/certs/adguard.crt \
|
||||||
|
-subj "/CN=adguard.tudominio.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Desde Portainer
|
||||||
|
|
||||||
|
1. Ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `adguard`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `adguard/docker-compose.yml`
|
||||||
|
5. Carga el archivo de variables de entorno: `adguard/stack.env`
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
### Variables de Entorno
|
||||||
|
|
||||||
|
Edita el archivo `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Imagen
|
||||||
|
ADGUARD_IMAGE=adguard/adguardhome:latest
|
||||||
|
|
||||||
|
# Dominio
|
||||||
|
ADGUARD_DOMAIN=adguard.tudominio.com
|
||||||
|
|
||||||
|
# IP fija en la red proxy
|
||||||
|
ADGUARD_IPV4=172.18.0.10
|
||||||
|
|
||||||
|
# Puerto DoT (DNS-over-TLS)
|
||||||
|
ADGUARD_DOT_PORT=853
|
||||||
|
|
||||||
|
# Puerto HTTP del panel (interno)
|
||||||
|
ADGUARD_HTTP_PORT=80
|
||||||
|
|
||||||
|
# Rutas
|
||||||
|
ADGUARD_WORK_PATH=/opt/adguard/work
|
||||||
|
ADGUARD_CONF_PATH=/opt/adguard/conf
|
||||||
|
ADGUARD_CERT_CRT_PATH=/opt/adguard/certs/adguard.crt
|
||||||
|
ADGUARD_CERT_KEY_PATH=/opt/adguard/certs/adguard.key
|
||||||
|
|
||||||
|
# Traefik
|
||||||
|
TRAEFIK_DOCKER_NETWORK=proxy
|
||||||
|
TRAEFIK_ENTRYPOINT_SECURE=websecure
|
||||||
|
TRAEFIK_CERTRESOLVER=letsencrypt
|
||||||
|
TRAEFIK_AUTH_MIDDLEWARE=authentik@docker
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Configuración Post-Instalación
|
||||||
|
|
||||||
|
### 1. Configuración Inicial
|
||||||
|
|
||||||
|
La primera vez que accedas a `https://adguard.tudominio.com`, se iniciará el asistente:
|
||||||
|
|
||||||
|
1. **Puerto de escucha**: Deja 3000 (se cambiará automáticamente a 80)
|
||||||
|
2. **Usuario y contraseña**: Crea las credenciales de administrador
|
||||||
|
3. **Interfaces de red**: Escucha en todas las interfaces
|
||||||
|
4. **DNS upstream**: Configura servidores DNS (ej: `1.1.1.1`, `8.8.8.8`)
|
||||||
|
|
||||||
|
> **Nota**: Si el panel escucha en puerto 3000, actualiza `ADGUARD_HTTP_PORT=3000` en el `stack.env` temporalmente.
|
||||||
|
|
||||||
|
### 2. Configurar DNS-over-TLS (DoT)
|
||||||
|
|
||||||
|
1. En el panel de AdGuard, ve a **Settings** → **Encryption settings**
|
||||||
|
2. Habilita **DNS-over-TLS**
|
||||||
|
3. Configura:
|
||||||
|
- **Server name**: `adguard.tudominio.com`
|
||||||
|
- **Certificate**: `/certs/adguard.crt`
|
||||||
|
- **Private key**: `/certs/adguard.key`
|
||||||
|
4. **Puerto**: 853
|
||||||
|
5. Haz clic en **Save**
|
||||||
|
|
||||||
|
### 3. Configurar Listas de Filtros
|
||||||
|
|
||||||
|
AdGuard viene con listas por defecto, pero puedes añadir más:
|
||||||
|
|
||||||
|
1. Ve a **Filters** → **DNS blocklists**
|
||||||
|
2. Añade listas populares:
|
||||||
|
- **Steven Black's Hosts**: Bloquea malware y anuncios
|
||||||
|
- **OISD**: Lista curada de dominios maliciosos
|
||||||
|
- **Hagezi**: Listas agresivas de bloqueo
|
||||||
|
3. Haz clic en **Add blocklist** y pega la URL
|
||||||
|
|
||||||
|
Ejemplos:
|
||||||
|
```
|
||||||
|
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
|
||||||
|
https://big.oisd.nl/
|
||||||
|
https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/domains/pro.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Configurar DNS Upstream
|
||||||
|
|
||||||
|
Para mejor privacidad, usa DNS cifrados:
|
||||||
|
|
||||||
|
1. Ve a **Settings** → **DNS settings**
|
||||||
|
2. En **Upstream DNS servers**, añade:
|
||||||
|
```
|
||||||
|
https://dns.cloudflare.com/dns-query
|
||||||
|
https://dns.google/dns-query
|
||||||
|
tls://1.1.1.1
|
||||||
|
tls://8.8.8.8
|
||||||
|
```
|
||||||
|
3. En **Bootstrap DNS servers** (para resolver los DNS cifrados):
|
||||||
|
```
|
||||||
|
1.1.1.1
|
||||||
|
8.8.8.8
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📱 Configurar Clientes
|
||||||
|
|
||||||
|
### Android - DNS Privado (DoT)
|
||||||
|
|
||||||
|
1. Ve a **Ajustes** → **Conexiones** → **Más ajustes de conexión**
|
||||||
|
2. Selecciona **DNS privado**
|
||||||
|
3. Elige **Nombre del host del proveedor de DNS privado**
|
||||||
|
4. Introduce: `adguard.tudominio.com`
|
||||||
|
5. Guarda
|
||||||
|
|
||||||
|
> Todo el tráfico DNS de tu móvil pasará por AdGuard, incluso fuera de casa.
|
||||||
|
|
||||||
|
### iOS - DNS-over-HTTPS
|
||||||
|
|
||||||
|
1. Descarga un perfil de configuración DoH
|
||||||
|
2. O usa apps como **AdGuard** o **DNSCloak**
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
#### Opción 1: Cambiar DNS del Sistema
|
||||||
|
|
||||||
|
1. Panel de Control → Redes → Propiedades del adaptador
|
||||||
|
2. IPv4 → Propiedades
|
||||||
|
3. DNS preferido: `IP-de-tu-servidor`
|
||||||
|
4. DNS alternativo: `8.8.8.8`
|
||||||
|
|
||||||
|
#### Opción 2: DNS-over-HTTPS (Windows 11)
|
||||||
|
|
||||||
|
1. Ajustes → Red e Internet → Ethernet/Wi-Fi
|
||||||
|
2. Editar DNS
|
||||||
|
3. Añade servidor DNS-over-HTTPS: `https://adguard.tudominio.com/dns-query`
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
Edita `/etc/resolv.conf`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nameserver IP-de-tu-servidor
|
||||||
|
nameserver 8.8.8.8
|
||||||
|
```
|
||||||
|
|
||||||
|
O con systemd-resolved:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nano /etc/systemd/resolved.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Resolve]
|
||||||
|
DNS=IP-de-tu-servidor
|
||||||
|
FallbackDNS=8.8.8.8
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl restart systemd-resolved
|
||||||
|
```
|
||||||
|
|
||||||
|
### Router
|
||||||
|
|
||||||
|
Configura AdGuard como DNS primario en tu router:
|
||||||
|
1. Accede al panel de tu router
|
||||||
|
2. Ve a configuración DHCP/DNS
|
||||||
|
3. DNS primario: `IP-de-tu-servidor`
|
||||||
|
4. DNS secundario: `8.8.8.8`
|
||||||
|
|
||||||
|
> **Ventaja**: Todos los dispositivos de tu red usarán AdGuard automáticamente.
|
||||||
|
|
||||||
|
## 🔧 Configuración Avanzada
|
||||||
|
|
||||||
|
### Listas Blancas (Whitelist)
|
||||||
|
|
||||||
|
Para permitir dominios bloqueados por error:
|
||||||
|
|
||||||
|
1. Ve a **Filters** → **Custom filtering rules**
|
||||||
|
2. Añade reglas:
|
||||||
|
```
|
||||||
|
@@||ejemplo-permitido.com^
|
||||||
|
@@||*.ejemplo.com^
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bloquear Dominios Específicos
|
||||||
|
|
||||||
|
```
|
||||||
|
||dominio-bloqueado.com^
|
||||||
|
||ads.ejemplo.com^
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reglas de Reescritura DNS
|
||||||
|
|
||||||
|
Para resolver dominios internos:
|
||||||
|
|
||||||
|
1. Ve a **Filters** → **DNS rewrites**
|
||||||
|
2. Añade entradas:
|
||||||
|
- **Domain**: `home.local`
|
||||||
|
- **Answer**: `192.168.1.10`
|
||||||
|
|
||||||
|
### Clientes Personalizados
|
||||||
|
|
||||||
|
Para aplicar configuraciones diferentes por cliente:
|
||||||
|
|
||||||
|
1. Ve a **Settings** → **Client settings**
|
||||||
|
2. Añade cliente por IP o ID
|
||||||
|
3. Configura filtros específicos, upstream DNS, etc.
|
||||||
|
|
||||||
|
### Estadísticas y Logs
|
||||||
|
|
||||||
|
- **Dashboard**: Ve estadísticas de consultas, clientes, dominios bloqueados
|
||||||
|
- **Query log**: Revisa todas las consultas DNS en tiempo real
|
||||||
|
- **Filtros por cliente**: Ve qué dispositivos hacen más consultas
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### No puedo acceder al panel web
|
||||||
|
|
||||||
|
1. Verifica que AdGuard está corriendo:
|
||||||
|
```bash
|
||||||
|
docker ps | grep adguard
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica los logs:
|
||||||
|
```bash
|
||||||
|
docker logs adguardhome
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Si el panel está en puerto 3000, cambia `ADGUARD_HTTP_PORT=3000` temporalmente
|
||||||
|
|
||||||
|
### DNS no resuelve dominios
|
||||||
|
|
||||||
|
1. Verifica que AdGuard está escuchando:
|
||||||
|
```bash
|
||||||
|
docker exec adguardhome netstat -tulpn
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Prueba DNS desde el servidor:
|
||||||
|
```bash
|
||||||
|
nslookup google.com 172.18.0.10
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica que los upstream DNS están configurados
|
||||||
|
|
||||||
|
### DoT no funciona en Android
|
||||||
|
|
||||||
|
1. Verifica que el puerto 853 está abierto:
|
||||||
|
```bash
|
||||||
|
sudo netstat -tulpn | grep 853
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica los certificados en AdGuard:
|
||||||
|
- Settings → Encryption → Verifica que están cargados correctamente
|
||||||
|
|
||||||
|
3. Prueba DoT desde el servidor:
|
||||||
|
```bash
|
||||||
|
kdig -d @adguard.tudominio.com +tls google.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Algunos sitios no cargan
|
||||||
|
|
||||||
|
1. Ve a **Query log** en AdGuard
|
||||||
|
2. Busca el dominio bloqueado
|
||||||
|
3. Añádelo a la whitelist si es necesario
|
||||||
|
|
||||||
|
### IP fija causa conflictos
|
||||||
|
|
||||||
|
Si la IP configurada está en uso:
|
||||||
|
|
||||||
|
1. Elige otra IP del rango de la red `proxy`
|
||||||
|
2. Actualiza `ADGUARD_IPV4` en `stack.env`
|
||||||
|
3. Actualiza el stack
|
||||||
|
|
||||||
|
## 📚 Recursos Adicionales
|
||||||
|
|
||||||
|
- [Documentación oficial de AdGuard Home](https://github.com/AdguardTeam/AdGuardHome/wiki)
|
||||||
|
- [Listas de filtros](https://filterlists.com/)
|
||||||
|
- [Comparativa con Pi-hole](https://github.com/AdguardTeam/AdGuardHome#comparison)
|
||||||
|
|
||||||
|
## 🔒 Seguridad
|
||||||
|
|
||||||
|
- **Panel web**: Siempre protegido con Authentik (SSO)
|
||||||
|
- **DoT**: Cifra las consultas DNS entre cliente y servidor
|
||||||
|
- **Upstream DNS**: Usa DNS cifrados (DoH/DoT) para privacidad total
|
||||||
|
- **Logs**: Revisa regularmente los logs para detectar anomalías
|
||||||
|
- **Actualizaciones**: Mantén AdGuard actualizado
|
||||||
|
|
||||||
|
## 💾 Backups
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup de configuración
|
||||||
|
sudo tar -czf adguard-backup-$(date +%Y%m%d).tar.gz /opt/adguard/
|
||||||
|
|
||||||
|
# Restaurar
|
||||||
|
sudo tar -xzf adguard-backup-YYYYMMDD.tar.gz -C /
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 Actualizaciones
|
||||||
|
|
||||||
|
1. Haz backup de la configuración
|
||||||
|
2. Actualiza en `stack.env`:
|
||||||
|
```env
|
||||||
|
ADGUARD_IMAGE=adguard/adguardhome:latest
|
||||||
|
```
|
||||||
|
3. Actualiza el stack en Portainer
|
||||||
|
4. Verifica los logs y el panel web
|
||||||
|
|
||||||
|
## 📊 Estadísticas
|
||||||
|
|
||||||
|
AdGuard ofrece estadísticas detalladas:
|
||||||
|
- **Consultas bloqueadas**: Porcentaje y cantidad
|
||||||
|
- **Top clientes**: Dispositivos que más consultas hacen
|
||||||
|
- **Top dominios**: Sitios más visitados
|
||||||
|
- **Top dominios bloqueados**: Anuncios y rastreadores más frecuentes
|
||||||
|
- **Upstream DNS**: Rendimiento de los servidores DNS configurados
|
||||||
|
|
||||||
|
Accede a estas estadísticas en el Dashboard de AdGuard.
|
||||||
345
authentik/README.md
Normal file
345
authentik/README.md
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
# Authentik - Sistema de Autenticación SSO
|
||||||
|
|
||||||
|
Authentik es un sistema de autenticación y autorización de código abierto que proporciona Single Sign-On (SSO) para tus aplicaciones.
|
||||||
|
|
||||||
|
## 📋 Descripción
|
||||||
|
|
||||||
|
Este stack despliega Authentik configurado para funcionar con Traefik mediante **Forward Authentication**, protegiendo tus servicios con autenticación centralizada.
|
||||||
|
|
||||||
|
## 🚀 Despliegue
|
||||||
|
|
||||||
|
### Desde Portainer
|
||||||
|
|
||||||
|
1. Ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `authentik`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `authentik/docker-compose.yml`
|
||||||
|
5. Carga el archivo de variables de entorno: `authentik/stack.env`
|
||||||
|
6. O añade manualmente las variables de entorno necesarias
|
||||||
|
7. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
### Variables de Entorno Importantes
|
||||||
|
|
||||||
|
Edita el archivo `stack.env` con tus valores:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Secretos (genera valores aleatorios seguros)
|
||||||
|
AUTHENTIK_SECRET_KEY=tu-clave-secreta-aleatoria
|
||||||
|
AUTHENTIK_POSTGRESQL_PASSWORD=tu-password-db-aleatorio
|
||||||
|
|
||||||
|
# Dominio de Authentik
|
||||||
|
AUTHENTIK_DOMAIN=auth.tudominio.com
|
||||||
|
|
||||||
|
# Email y SMTP (opcional pero recomendado)
|
||||||
|
AUTHENTIK_EMAIL__HOST=smtp.tudominio.com
|
||||||
|
AUTHENTIK_EMAIL__PORT=587
|
||||||
|
AUTHENTIK_EMAIL__USERNAME=noreply@tudominio.com
|
||||||
|
AUTHENTIK_EMAIL__PASSWORD=tu-password-email
|
||||||
|
AUTHENTIK_EMAIL__FROM=noreply@tudominio.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Configuración Post-Instalación
|
||||||
|
|
||||||
|
Una vez desplegado Authentik, accede a su interfaz web en `https://auth.tudominio.com` y completa la configuración inicial.
|
||||||
|
|
||||||
|
### 1. Acceso Inicial
|
||||||
|
|
||||||
|
- Usuario por defecto: `akadmin`
|
||||||
|
- Contraseña: La que configures en el primer acceso
|
||||||
|
- Cambia la contraseña inmediatamente
|
||||||
|
|
||||||
|
### 2. Crear Applications (Aplicaciones)
|
||||||
|
|
||||||
|
Para cada servicio que quieras proteger (ej: Portainer, Traefik Dashboard, Gitea, etc.):
|
||||||
|
|
||||||
|
1. Ve a **Applications** → **Create**
|
||||||
|
2. Completa el formulario:
|
||||||
|
- **Name**: `Portainer` (nombre descriptivo)
|
||||||
|
- **Slug**: `portainer` (identificador único en minúsculas)
|
||||||
|
- **Provider**: (lo crearás en el siguiente paso - déjalo vacío por ahora)
|
||||||
|
- **Policy engine mode**: `any` (permite acceso si alguna política coincide)
|
||||||
|
- **UI settings**: Configura el icono y apariencia (opcional)
|
||||||
|
3. Haz clic en **Create**
|
||||||
|
|
||||||
|
### 3. Crear Providers de tipo Forward Auth
|
||||||
|
|
||||||
|
Los providers conectan tus aplicaciones con Authentik. Para Forward Auth con Traefik:
|
||||||
|
|
||||||
|
1. Ve a **Applications** → Tu aplicación → **Provider** → **Create**
|
||||||
|
2. Selecciona tipo: **Proxy Provider**
|
||||||
|
3. Completa el formulario:
|
||||||
|
- **Name**: `Portainer Provider`
|
||||||
|
- **Authorization flow**: Selecciona `default-provider-authorization-implicit-consent` (créalo si no existe - ver paso 4)
|
||||||
|
- **Type**: **Forward auth (single application)**
|
||||||
|
- **External host**: `https://portainer.tudominio.com` (URL completa de tu servicio)
|
||||||
|
- **Internal host**: `http://portainer:9000` (opcional - URL interna si Authentik debe hacer reverse proxy)
|
||||||
|
- **Internal host SSL validation**: Desactivado (si usas HTTP interno)
|
||||||
|
4. **Advanced settings**:
|
||||||
|
- **Token validity**: `hours=24` (duración de la sesión)
|
||||||
|
- **Cookie domain**: `.tudominio.com` (permite SSO entre subdominios)
|
||||||
|
5. Haz clic en **Create**
|
||||||
|
6. Vuelve a la aplicación y selecciona el provider que acabas de crear
|
||||||
|
|
||||||
|
### 4. Crear Authorization Flow (Implicit)
|
||||||
|
|
||||||
|
El authorization flow de tipo **implicit** permite autorización sin pantalla de consentimiento explícita:
|
||||||
|
|
||||||
|
#### Opción A: Usar el flow por defecto
|
||||||
|
|
||||||
|
Authentik suele incluir un flow llamado `default-provider-authorization-implicit-consent`. Si existe, úsalo directamente en tus providers.
|
||||||
|
|
||||||
|
#### Opción B: Crear un flow personalizado
|
||||||
|
|
||||||
|
Si necesitas crear uno nuevo:
|
||||||
|
|
||||||
|
1. Ve a **Flows & Stages** → **Flows** → **Create**
|
||||||
|
2. Completa el formulario:
|
||||||
|
- **Name**: `Authorization Flow Implicit`
|
||||||
|
- **Title**: `Redirecting to application`
|
||||||
|
- **Slug**: `default-provider-authorization-implicit-consent`
|
||||||
|
- **Designation**: **Authorization**
|
||||||
|
- **Authentication**: `Require authentication` (el usuario debe estar autenticado)
|
||||||
|
- **Behavior settings**:
|
||||||
|
- **Layout**: `content_left` o el que prefieras
|
||||||
|
3. Haz clic en **Create**
|
||||||
|
|
||||||
|
#### Añadir Stages al Flow
|
||||||
|
|
||||||
|
1. Abre el flow que acabas de crear
|
||||||
|
2. Ve a la pestaña **Stage Bindings**
|
||||||
|
3. Añade el stage de consentimiento (opcional):
|
||||||
|
- Haz clic en **Bind existing stage**
|
||||||
|
- Selecciona `default-provider-authorization-consent` (o crea uno nuevo)
|
||||||
|
- **Order**: 10
|
||||||
|
- **Evaluate on plan**: Activado
|
||||||
|
- **Re-evaluate policies**: Activado
|
||||||
|
|
||||||
|
> **Nota**: Para implicit consent, puedes crear un flow sin stages de consentimiento, lo que permite autorización automática.
|
||||||
|
|
||||||
|
#### Crear Stage de Consent (si no existe)
|
||||||
|
|
||||||
|
Si necesitas crear el stage de consentimiento:
|
||||||
|
|
||||||
|
1. Ve a **Flows & Stages** → **Stages** → **Create**
|
||||||
|
2. Tipo: **Consent Stage**
|
||||||
|
3. Completa:
|
||||||
|
- **Name**: `default-provider-authorization-consent`
|
||||||
|
- **Mode**: `always_require` o `hidden` (para implicit)
|
||||||
|
- **Consent expire in**: `weeks=4` (duración del consentimiento)
|
||||||
|
4. Haz clic en **Create**
|
||||||
|
|
||||||
|
### 5. Configurar Outpost
|
||||||
|
|
||||||
|
Los **outposts** son los componentes que ejecutan los providers y procesan las peticiones de autenticación:
|
||||||
|
|
||||||
|
1. Ve a **Outposts** → **Outposts** → **Create**
|
||||||
|
2. Completa el formulario:
|
||||||
|
- **Name**: `authentik-embedded-outpost` (o el nombre que prefieras)
|
||||||
|
- **Type**: **Proxy**
|
||||||
|
- **Integration**: Déjalo vacío (el outpost embedded usa la integración por defecto)
|
||||||
|
3. **Applications**: Selecciona todas las aplicaciones que creaste (Portainer, Traefik, etc.)
|
||||||
|
4. **Configuration**:
|
||||||
|
```yaml
|
||||||
|
authentik_host: https://auth.tudominio.com
|
||||||
|
authentik_host_insecure: false
|
||||||
|
log_level: info
|
||||||
|
object_naming_template: ak-outpost-%(name)s
|
||||||
|
docker_network: proxy
|
||||||
|
docker_labels:
|
||||||
|
traefik.enable: "true"
|
||||||
|
```
|
||||||
|
5. Haz clic en **Create**
|
||||||
|
|
||||||
|
#### Verificar Estado del Outpost
|
||||||
|
|
||||||
|
1. Ve a **Outposts** → **Outposts**
|
||||||
|
2. Verifica que tu outpost aparece en estado **Healthy** (saludable)
|
||||||
|
3. Si aparece como **Unhealthy**:
|
||||||
|
- Verifica los logs: `docker logs authentik-worker`
|
||||||
|
- Asegúrate de que el contenedor puede comunicarse con el servidor de Authentik
|
||||||
|
- Verifica la red Docker `proxy`
|
||||||
|
|
||||||
|
### 6. Configurar Middleware en Traefik
|
||||||
|
|
||||||
|
Para que Traefik use Authentik como forward auth, necesitas configurar el middleware.
|
||||||
|
|
||||||
|
#### Opción A: Middleware en el stack de Authentik
|
||||||
|
|
||||||
|
Añade las siguientes labels al servicio `authentik-server` en el `docker-compose.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
# Middleware de Forward Auth
|
||||||
|
traefik.http.middlewares.authentik.forwardauth.address: "http://authentik-server:9000/outpost.goauthentik.io/auth/traefik"
|
||||||
|
traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: "true"
|
||||||
|
traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: "X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Opción B: Middleware en archivo de configuración de Traefik
|
||||||
|
|
||||||
|
En el archivo de configuración dinámica de Traefik (`dynamic.yml`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
authentik:
|
||||||
|
forwardAuth:
|
||||||
|
address: "http://authentik-server:9000/outpost.goauthentik.io/auth/traefik"
|
||||||
|
trustForwardHeader: true
|
||||||
|
authResponseHeaders:
|
||||||
|
- "X-authentik-username"
|
||||||
|
- "X-authentik-groups"
|
||||||
|
- "X-authentik-email"
|
||||||
|
- "X-authentik-name"
|
||||||
|
- "X-authentik-uid"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Proteger Servicios con Authentik
|
||||||
|
|
||||||
|
Una vez configurado el middleware, añade la label a los servicios que quieras proteger:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
traefik.http.routers.portainer.middlewares: "authentik@docker"
|
||||||
|
```
|
||||||
|
|
||||||
|
O si definiste el middleware en archivo:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
traefik.http.routers.portainer.middlewares: "authentik@file"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 Gestión de Usuarios y Grupos
|
||||||
|
|
||||||
|
### Crear Usuarios
|
||||||
|
|
||||||
|
1. Ve a **Directory** → **Users** → **Create**
|
||||||
|
2. Completa los datos del usuario
|
||||||
|
3. Asigna grupos si es necesario
|
||||||
|
4. Haz clic en **Create**
|
||||||
|
|
||||||
|
### Crear Grupos
|
||||||
|
|
||||||
|
1. Ve a **Directory** → **Groups** → **Create**
|
||||||
|
2. Nombre del grupo (ej: `admins`, `users`)
|
||||||
|
3. Añade usuarios al grupo
|
||||||
|
4. Haz clic en **Create**
|
||||||
|
|
||||||
|
### Crear Políticas de Acceso
|
||||||
|
|
||||||
|
Para controlar quién puede acceder a cada aplicación:
|
||||||
|
|
||||||
|
1. Ve a **Applications** → Tu aplicación → **Policy / Group / User Bindings**
|
||||||
|
2. Haz clic en **Bind existing policy/group/user**
|
||||||
|
3. Selecciona un grupo (ej: `admins`)
|
||||||
|
4. **Order**: 0 (menor número = mayor prioridad)
|
||||||
|
5. Haz clic en **Create**
|
||||||
|
|
||||||
|
## 🔧 Configuración Avanzada
|
||||||
|
|
||||||
|
### Configurar Múltiples Dominios (SSO entre subdominios)
|
||||||
|
|
||||||
|
En la configuración del provider:
|
||||||
|
- **Cookie domain**: `.tudominio.com` (con el punto inicial)
|
||||||
|
- Esto permite que la sesión se comparta entre todos los subdominios
|
||||||
|
|
||||||
|
### Configurar Email (SMTP)
|
||||||
|
|
||||||
|
Para notificaciones y recuperación de contraseñas:
|
||||||
|
|
||||||
|
1. Ve a **System** → **Settings** → **Email**
|
||||||
|
2. Configura los parámetros SMTP (o usa las variables de entorno en `stack.env`)
|
||||||
|
|
||||||
|
### Configurar Autenticación de Dos Factores (2FA)
|
||||||
|
|
||||||
|
1. Ve a **Flows & Stages** → **Stages**
|
||||||
|
2. Crea stages de tipo **Authenticator Validation Stage** (TOTP, WebAuthn, etc.)
|
||||||
|
3. Añade estos stages a tu authentication flow
|
||||||
|
|
||||||
|
### Integración con Proveedores Externos (OAuth, SAML)
|
||||||
|
|
||||||
|
1. Ve a **System** → **Providers** → **Create**
|
||||||
|
2. Selecciona el tipo (OAuth2, SAML, etc.)
|
||||||
|
3. Configura según el proveedor externo (Google, GitHub, etc.)
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### El outpost aparece como Unhealthy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ver logs del worker
|
||||||
|
docker logs authentik-worker
|
||||||
|
|
||||||
|
# Ver logs del servidor
|
||||||
|
docker logs authentik-server
|
||||||
|
|
||||||
|
# Verificar conectividad de red
|
||||||
|
docker exec authentik-server ping authentik-postgresql
|
||||||
|
docker exec authentik-server ping authentik-redis
|
||||||
|
```
|
||||||
|
|
||||||
|
### Los servicios no están protegidos
|
||||||
|
|
||||||
|
1. Verifica que el middleware de Traefik esté correctamente configurado
|
||||||
|
2. Comprueba que las labels en el servicio están correctas
|
||||||
|
3. Verifica los logs de Traefik: `docker logs traefik`
|
||||||
|
4. Asegúrate de que el provider está asociado a la aplicación
|
||||||
|
5. Verifica que el outpost esté en estado **Healthy**
|
||||||
|
|
||||||
|
### Error "Invalid redirect_uri"
|
||||||
|
|
||||||
|
1. Verifica que el **External host** en el provider coincide exactamente con la URL del servicio
|
||||||
|
2. Asegúrate de incluir el protocolo (`https://`)
|
||||||
|
3. No incluyas barras finales
|
||||||
|
|
||||||
|
### Sesiones no persisten / Se desconecta constantemente
|
||||||
|
|
||||||
|
1. Verifica que el **Cookie domain** esté configurado correctamente (`.tudominio.com`)
|
||||||
|
2. Comprueba que Redis esté funcionando: `docker logs authentik-redis`
|
||||||
|
3. Aumenta el **Token validity** en el provider
|
||||||
|
|
||||||
|
### No puedo acceder al panel de Authentik
|
||||||
|
|
||||||
|
1. Accede directamente por IP: `http://IP-servidor:9000`
|
||||||
|
2. Verifica los logs: `docker logs authentik-server`
|
||||||
|
3. Comprueba que el dominio DNS está configurado correctamente
|
||||||
|
4. Verifica que Traefik está redirigiendo correctamente
|
||||||
|
|
||||||
|
## 📚 Recursos Adicionales
|
||||||
|
|
||||||
|
- [Documentación oficial de Authentik](https://goauthentik.io/docs/)
|
||||||
|
- [Authentik con Traefik](https://goauthentik.io/docs/providers/proxy/forward_auth)
|
||||||
|
- [Configuración de Flows](https://goauthentik.io/docs/flow/)
|
||||||
|
- [Configuración de Outposts](https://goauthentik.io/docs/outposts/)
|
||||||
|
|
||||||
|
## 🔒 Seguridad
|
||||||
|
|
||||||
|
- **Cambia inmediatamente** el password por defecto de `akadmin`
|
||||||
|
- Genera valores **aleatorios** para `AUTHENTIK_SECRET_KEY` y `AUTHENTIK_POSTGRESQL_PASSWORD`
|
||||||
|
- Habilita **2FA** para usuarios administradores
|
||||||
|
- Realiza **backups regulares** de la base de datos PostgreSQL
|
||||||
|
- Mantén Authentik **actualizado** a la última versión
|
||||||
|
|
||||||
|
## 💾 Backups
|
||||||
|
|
||||||
|
Para hacer backup de la configuración de Authentik:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup de la base de datos PostgreSQL
|
||||||
|
docker exec authentik-postgresql pg_dump -U authentik authentik > authentik_backup.sql
|
||||||
|
|
||||||
|
# Backup de Redis (sesiones)
|
||||||
|
docker exec authentik-redis redis-cli --rdb /data/dump.rdb
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 Actualizaciones
|
||||||
|
|
||||||
|
1. En Portainer, ve a tu stack de Authentik
|
||||||
|
2. Haz clic en **Editor**
|
||||||
|
3. Actualiza las versiones de las imágenes si es necesario
|
||||||
|
4. Haz clic en **Update the stack**
|
||||||
|
5. O ejecuta: `docker compose pull && docker compose up -d`
|
||||||
379
gitea/README.md
Normal file
379
gitea/README.md
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
# Gitea - Servidor Git Autoalojado
|
||||||
|
|
||||||
|
Gitea es un servidor Git ligero y autoalojado, similar a GitHub o GitLab.
|
||||||
|
|
||||||
|
## 📋 Descripción
|
||||||
|
|
||||||
|
Este stack despliega Gitea con:
|
||||||
|
- Base de datos PostgreSQL
|
||||||
|
- Servidor SSH para operaciones Git
|
||||||
|
- Gitea Actions (CI/CD similar a GitHub Actions)
|
||||||
|
- Act Runner para ejecutar pipelines
|
||||||
|
- Integración con Traefik y Authentik
|
||||||
|
|
||||||
|
## 🚀 Despliegue
|
||||||
|
|
||||||
|
### Prerequisitos
|
||||||
|
|
||||||
|
1. **Red Docker**: Asegúrate de que la red `proxy` existe
|
||||||
|
2. **Registro DNS**: Configura el registro A para tu dominio Gitea
|
||||||
|
3. **Puerto SSH**: El puerto SSH debe estar disponible (por defecto 222)
|
||||||
|
|
||||||
|
### Desde Portainer
|
||||||
|
|
||||||
|
1. Ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `gitea`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `gitea/docker-compose.yml`
|
||||||
|
5. Carga el archivo de variables de entorno: `gitea/stack.env`
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
### Variables de Entorno Importantes
|
||||||
|
|
||||||
|
Edita el archivo `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Imágenes
|
||||||
|
GITEA_IMAGE=gitea/gitea:latest
|
||||||
|
GITEA_POSTGRES_IMAGE=postgres:16
|
||||||
|
GITEA_RUNNER_IMAGE=gitea/act_runner:latest
|
||||||
|
|
||||||
|
# Base de datos
|
||||||
|
GITEA_DB_PASSWORD=tu-password-seguro-aleatorio
|
||||||
|
|
||||||
|
# Dominios
|
||||||
|
GITEA_DOMAIN=git.tudominio.com
|
||||||
|
GITEA_ROOT_URL=https://git.tudominio.com
|
||||||
|
|
||||||
|
# SSH
|
||||||
|
GITEA_SSH_DOMAIN=git.tudominio.com
|
||||||
|
GITEA_SSH_PORT=222
|
||||||
|
|
||||||
|
# Gitea Actions Runner
|
||||||
|
GITEA_RUNNER_REGISTRATION_TOKEN=tu-token-de-registro
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Configuración Post-Instalación
|
||||||
|
|
||||||
|
### 1. Primer Acceso
|
||||||
|
|
||||||
|
1. Accede a `https://git.tudominio.com`
|
||||||
|
2. Completa la configuración inicial:
|
||||||
|
- Base de datos: Ya está configurada (PostgreSQL)
|
||||||
|
- Configuración del servidor: Usa los valores predefinidos
|
||||||
|
- **Importante**: Crea la cuenta de administrador en este paso
|
||||||
|
3. Haz clic en **Install Gitea**
|
||||||
|
|
||||||
|
### 2. Configurar Gitea Actions
|
||||||
|
|
||||||
|
Para habilitar CI/CD con Gitea Actions:
|
||||||
|
|
||||||
|
#### Paso 1: Generar Token de Registro
|
||||||
|
|
||||||
|
1. Accede a Gitea como administrador
|
||||||
|
2. Ve a **Site Administration** → **Actions** → **Runners**
|
||||||
|
3. Haz clic en **Create new Runner**
|
||||||
|
4. Copia el **Registration Token**
|
||||||
|
|
||||||
|
#### Paso 2: Actualizar el Stack
|
||||||
|
|
||||||
|
1. Edita el archivo `stack.env`
|
||||||
|
2. Añade el token:
|
||||||
|
```env
|
||||||
|
GITEA_RUNNER_REGISTRATION_TOKEN=tu-token-copiado
|
||||||
|
```
|
||||||
|
3. Actualiza el stack en Portainer
|
||||||
|
|
||||||
|
#### Paso 3: Verificar el Runner
|
||||||
|
|
||||||
|
1. En Gitea, ve a **Site Administration** → **Actions** → **Runners**
|
||||||
|
2. Deberías ver el runner registrado y activo
|
||||||
|
3. Nombre del runner: `act-runner-docker` (o el configurado en `GITEA_RUNNER_NAME`)
|
||||||
|
|
||||||
|
### 3. Configurar SSH
|
||||||
|
|
||||||
|
Para usar Git con SSH:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clonar repositorio con SSH
|
||||||
|
git clone ssh://git@git.tudominio.com:222/usuario/repositorio.git
|
||||||
|
|
||||||
|
# O configurar SSH en ~/.ssh/config
|
||||||
|
Host git.tudominio.com
|
||||||
|
HostName git.tudominio.com
|
||||||
|
Port 222
|
||||||
|
User git
|
||||||
|
IdentityFile ~/.ssh/id_ed25519
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Integración con Authentik (SSO)
|
||||||
|
|
||||||
|
Este stack tiene una configuración especial para Authentik:
|
||||||
|
|
||||||
|
#### Rutas Protegidas
|
||||||
|
|
||||||
|
- `/user/login` - Página de login (protegida con SSO)
|
||||||
|
- `/explore` - Explorar repositorios públicos (protegida)
|
||||||
|
- `/TheHomelessSherlock` - Perfil de usuario específico (protegido)
|
||||||
|
|
||||||
|
#### Rutas Públicas
|
||||||
|
|
||||||
|
- Repositorios públicos accesibles sin autenticación
|
||||||
|
- API Git (clone, pull, push) funciona sin SSO
|
||||||
|
|
||||||
|
#### Configurar OAuth con Authentik
|
||||||
|
|
||||||
|
1. En Authentik, crea una aplicación para Gitea:
|
||||||
|
- Tipo: **OAuth2/OpenID Provider**
|
||||||
|
- Client type: **Confidential**
|
||||||
|
- Redirect URIs: `https://git.tudominio.com/user/oauth2/authentik/callback`
|
||||||
|
|
||||||
|
2. En Gitea, ve a **Site Administration** → **Authentication Sources** → **Add Authentication Source**
|
||||||
|
3. Tipo: **OAuth2**
|
||||||
|
4. Configura:
|
||||||
|
- Provider: **OpenID Connect**
|
||||||
|
- Client ID: (de Authentik)
|
||||||
|
- Client Secret: (de Authentik)
|
||||||
|
- OpenID Connect Auto Discovery URL: `https://auth.tudominio.com/application/o/gitea/.well-known/openid-configuration`
|
||||||
|
|
||||||
|
5. Actualiza las variables en `stack.env`:
|
||||||
|
```env
|
||||||
|
GITEA_ENABLE_OPENID_SIGNIN=true
|
||||||
|
GITEA_ENABLE_OPENID_SIGNUP=true
|
||||||
|
GITEA_DISABLE_LOGIN_FORM=false # Mantén false para permitir login local también
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Configuración Avanzada
|
||||||
|
|
||||||
|
### Personalización de la UI
|
||||||
|
|
||||||
|
Las siguientes opciones están preconfiguradas:
|
||||||
|
|
||||||
|
- **Tema por defecto**: Oscuro (`gitea-dark`)
|
||||||
|
- **Registro deshabilitado**: Solo administradores pueden crear usuarios (o usar SSO)
|
||||||
|
- **Visibilidad por defecto**: Privada
|
||||||
|
- **Requiere login para ver**: Activado
|
||||||
|
|
||||||
|
Para cambiar estas opciones, edita `stack.env` y actualiza el stack.
|
||||||
|
|
||||||
|
### Limitar Acceso por Organización
|
||||||
|
|
||||||
|
```env
|
||||||
|
GITEA_DEFAULT_ALLOW_CREATE_ORGANIZATION=false
|
||||||
|
GITEA_DEFAULT_ORG_VISIBILITY=private
|
||||||
|
```
|
||||||
|
|
||||||
|
### Notificaciones por Email
|
||||||
|
|
||||||
|
Añade al archivo `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
GITEA__mailer__ENABLED=true
|
||||||
|
GITEA__mailer__FROM=gitea@tudominio.com
|
||||||
|
GITEA__mailer__PROTOCOL=smtp
|
||||||
|
GITEA__mailer__SMTP_ADDR=smtp.tudominio.com
|
||||||
|
GITEA__mailer__SMTP_PORT=587
|
||||||
|
GITEA__mailer__USER=gitea@tudominio.com
|
||||||
|
GITEA__mailer__PASSWD=tu-password-smtp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configurar Webhooks
|
||||||
|
|
||||||
|
Gitea soporta webhooks para integración con otros servicios:
|
||||||
|
|
||||||
|
1. Ve a tu repositorio → **Settings** → **Webhooks**
|
||||||
|
2. Añade un webhook con la URL de destino
|
||||||
|
3. Selecciona los eventos que quieres recibir
|
||||||
|
|
||||||
|
### Ejemplo de Workflow con Gitea Actions
|
||||||
|
|
||||||
|
Crea `.gitea/workflows/build.yml` en tu repositorio:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Build and Test
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### No puedo hacer push/pull por SSH
|
||||||
|
|
||||||
|
1. Verifica que el puerto SSH está abierto:
|
||||||
|
```bash
|
||||||
|
telnet git.tudominio.com 222
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica tu clave SSH:
|
||||||
|
```bash
|
||||||
|
ssh -T git@git.tudominio.com -p 222
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Añade tu clave SSH en Gitea:
|
||||||
|
- Ve a **Settings** → **SSH / GPG Keys** → **Add Key**
|
||||||
|
|
||||||
|
### El runner de Actions no se registra
|
||||||
|
|
||||||
|
1. Verifica los logs:
|
||||||
|
```bash
|
||||||
|
docker logs gitea-act-runner
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica que el token es correcto en `stack.env`
|
||||||
|
|
||||||
|
3. Regenera el token en Gitea si es necesario
|
||||||
|
|
||||||
|
4. Asegúrate de que el runner puede comunicarse con Gitea:
|
||||||
|
```bash
|
||||||
|
docker exec gitea-act-runner ping gitea
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error de permisos con volúmenes
|
||||||
|
|
||||||
|
Si usas SELinux, los volúmenes ya tienen `:Z`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Si persisten problemas
|
||||||
|
sudo chcon -Rt svirt_sandbox_file_t /opt/gitea/data
|
||||||
|
sudo chcon -Rt svirt_sandbox_file_t /opt/gitea/postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
### OAuth con Authentik no funciona
|
||||||
|
|
||||||
|
1. Verifica que la Redirect URI en Authentik es exacta
|
||||||
|
2. Comprueba que el Discovery URL es accesible desde el contenedor:
|
||||||
|
```bash
|
||||||
|
docker exec gitea curl https://auth.tudominio.com/application/o/gitea/.well-known/openid-configuration
|
||||||
|
```
|
||||||
|
3. Revisa los logs de Gitea: `docker logs gitea`
|
||||||
|
|
||||||
|
### La base de datos no inicia
|
||||||
|
|
||||||
|
1. Verifica los logs de PostgreSQL:
|
||||||
|
```bash
|
||||||
|
docker logs gitea-postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica los permisos del directorio de datos:
|
||||||
|
```bash
|
||||||
|
ls -lh /opt/gitea/postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Si necesitas reiniciar desde cero:
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
sudo rm -rf /opt/gitea/postgres/*
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Recursos Adicionales
|
||||||
|
|
||||||
|
- [Documentación oficial de Gitea](https://docs.gitea.io/)
|
||||||
|
- [Gitea Actions](https://docs.gitea.io/en-us/usage/actions/overview/)
|
||||||
|
- [Act Runner](https://gitea.com/gitea/act_runner)
|
||||||
|
- [Migrar desde GitHub/GitLab](https://docs.gitea.io/en-us/usage/migrations/)
|
||||||
|
|
||||||
|
## 🔒 Seguridad
|
||||||
|
|
||||||
|
- **SSH**: Usa claves SSH en lugar de passwords para Git
|
||||||
|
- **2FA**: Habilita autenticación de dos factores en tu cuenta
|
||||||
|
- **Tokens**: Usa tokens de acceso con permisos limitados para CI/CD
|
||||||
|
- **Webhooks**: Verifica siempre las firmas de webhooks
|
||||||
|
- **Backups**: Realiza backups regulares de la base de datos y repositorios
|
||||||
|
|
||||||
|
## 💾 Backups
|
||||||
|
|
||||||
|
### Backup de la Base de Datos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup completo
|
||||||
|
docker exec gitea-postgres pg_dump -U gitea gitea > gitea_backup_$(date +%Y%m%d).sql
|
||||||
|
|
||||||
|
# Restaurar
|
||||||
|
cat gitea_backup_YYYYMMDD.sql | docker exec -i gitea-postgres psql -U gitea gitea
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup de Repositorios y Datos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup completo de datos
|
||||||
|
sudo tar -czf gitea-data-backup-$(date +%Y%m%d).tar.gz /opt/gitea/data
|
||||||
|
|
||||||
|
# Restaurar
|
||||||
|
sudo tar -xzf gitea-data-backup-YYYYMMDD.tar.gz -C /
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Automático
|
||||||
|
|
||||||
|
Considera usar el comando nativo de Gitea:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -u git gitea gitea dump -c /data/gitea/conf/app.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
Esto crea un archivo `gitea-dump-*.zip` con todo lo necesario para restaurar.
|
||||||
|
|
||||||
|
## 🔄 Actualizaciones
|
||||||
|
|
||||||
|
1. **Backup primero**: Siempre haz backup antes de actualizar
|
||||||
|
2. Actualiza la versión en `stack.env`:
|
||||||
|
```env
|
||||||
|
GITEA_IMAGE=gitea/gitea:1.21.0
|
||||||
|
```
|
||||||
|
3. Actualiza el stack en Portainer
|
||||||
|
4. Verifica los logs: `docker logs gitea`
|
||||||
|
5. Prueba que todo funciona correctamente
|
||||||
|
|
||||||
|
## 📊 Monitoreo
|
||||||
|
|
||||||
|
### Ver Estadísticas
|
||||||
|
|
||||||
|
- Accede a **Site Administration** → **Dashboard**
|
||||||
|
- Revisa usuarios, repositorios, organizaciones, etc.
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Logs de Gitea
|
||||||
|
docker logs -f gitea
|
||||||
|
|
||||||
|
# Logs de PostgreSQL
|
||||||
|
docker logs -f gitea-postgres
|
||||||
|
|
||||||
|
# Logs del Runner
|
||||||
|
docker logs -f gitea-act-runner
|
||||||
|
```
|
||||||
|
|
||||||
|
### Métricas
|
||||||
|
|
||||||
|
Gitea soporta exportación de métricas para Prometheus:
|
||||||
|
|
||||||
|
1. Habilita métricas en `stack.env`:
|
||||||
|
```env
|
||||||
|
GITEA__metrics__ENABLED=true
|
||||||
|
GITEA__metrics__TOKEN=tu-token-secreto
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Las métricas estarán disponibles en: `https://git.tudominio.com/metrics?token=tu-token-secreto`
|
||||||
370
n8n/README.md
Normal file
370
n8n/README.md
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
# n8n - Plataforma de Automatización
|
||||||
|
|
||||||
|
n8n es una plataforma de automatización de código abierto que permite conectar diferentes servicios y crear flujos de trabajo (workflows).
|
||||||
|
|
||||||
|
## 📋 Descripción
|
||||||
|
|
||||||
|
Este stack despliega n8n con:
|
||||||
|
- Base de datos PostgreSQL para persistencia
|
||||||
|
- Integración con Traefik para acceso HTTPS
|
||||||
|
- Webhooks públicos sin autenticación
|
||||||
|
- UI protegida con Authentik (SSO)
|
||||||
|
- Cifrado de credenciales
|
||||||
|
|
||||||
|
## 🚀 Despliegue
|
||||||
|
|
||||||
|
### Prerequisitos
|
||||||
|
|
||||||
|
1. **Red Docker**: Asegúrate de que la red `proxy` existe
|
||||||
|
2. **Registro DNS**: Configura el registro A para tu dominio n8n
|
||||||
|
3. **Clave de cifrado**: Genera una clave segura para cifrar credenciales
|
||||||
|
|
||||||
|
### Desde Portainer
|
||||||
|
|
||||||
|
1. Ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `n8n`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `n8n/docker-compose.yml`
|
||||||
|
5. Carga el archivo de variables de entorno: `n8n/stack.env`
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
### Variables de Entorno Importantes
|
||||||
|
|
||||||
|
Edita el archivo `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Base de datos PostgreSQL
|
||||||
|
POSTGRES_PASSWORD=tu-password-seguro-aleatorio
|
||||||
|
N8N_DB_PASSWORD=tu-password-seguro-aleatorio
|
||||||
|
|
||||||
|
# Dominio y URLs
|
||||||
|
N8N_DOMAIN=n8n.tudominio.com
|
||||||
|
N8N_HOST=n8n.tudominio.com
|
||||||
|
N8N_WEBHOOK_URL=https://n8n.tudominio.com/
|
||||||
|
|
||||||
|
# Cifrado de credenciales (IMPORTANTE: genera una clave única y guárdala)
|
||||||
|
N8N_ENCRYPTION_KEY=tu-clave-de-cifrado-aleatoria-muy-larga
|
||||||
|
|
||||||
|
# Zona horaria
|
||||||
|
N8N_TIMEZONE=Europe/Madrid
|
||||||
|
```
|
||||||
|
|
||||||
|
> **⚠️ CRÍTICO**: La `N8N_ENCRYPTION_KEY` es **fundamental**. Si la pierdes, perderás acceso a todas las credenciales guardadas. Haz backup de esta clave.
|
||||||
|
|
||||||
|
### Generar Clave de Cifrado
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openssl rand -hex 32
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Configuración Post-Instalación
|
||||||
|
|
||||||
|
### 1. Primer Acceso
|
||||||
|
|
||||||
|
1. Accede a `https://n8n.tudominio.com`
|
||||||
|
2. Si Authentik está configurado, serás redirigido al login de SSO
|
||||||
|
3. Completa la configuración inicial de n8n:
|
||||||
|
- Email del propietario
|
||||||
|
- Nombre de la instancia (opcional)
|
||||||
|
- Preferencias de uso
|
||||||
|
|
||||||
|
### 2. Crear tu Primer Workflow
|
||||||
|
|
||||||
|
1. Haz clic en **Create new workflow**
|
||||||
|
2. Añade un nodo trigger (ej: **Webhook**, **Schedule**, **Manual**)
|
||||||
|
3. Añade nodos de acción (ej: **HTTP Request**, **Gmail**, **Slack**)
|
||||||
|
4. Conecta los nodos
|
||||||
|
5. Haz clic en **Execute workflow** para probar
|
||||||
|
6. Activa el workflow
|
||||||
|
|
||||||
|
### 3. Configurar Credenciales
|
||||||
|
|
||||||
|
Para servicios externos (Gmail, Slack, etc.):
|
||||||
|
|
||||||
|
1. Haz clic en un nodo que requiera credenciales
|
||||||
|
2. Haz clic en **Create New Credential**
|
||||||
|
3. Completa los datos de autenticación
|
||||||
|
4. Las credenciales se cifran automáticamente con `N8N_ENCRYPTION_KEY`
|
||||||
|
|
||||||
|
## 🔧 Uso de Webhooks
|
||||||
|
|
||||||
|
### Webhooks Públicos
|
||||||
|
|
||||||
|
Los webhooks NO están protegidos por Authentik, permitiendo que servicios externos los activen:
|
||||||
|
|
||||||
|
- URL de producción: `https://n8n.tudominio.com/webhook/tu-id-webhook`
|
||||||
|
- URL de test: `https://n8n.tudominio.com/webhook-test/tu-id-webhook`
|
||||||
|
|
||||||
|
### Ejemplo de Webhook
|
||||||
|
|
||||||
|
1. Crea un workflow con un nodo **Webhook**
|
||||||
|
2. Configura:
|
||||||
|
- **HTTP Method**: `POST` (o el que necesites)
|
||||||
|
- **Path**: `mi-webhook` (se generará automáticamente)
|
||||||
|
3. Activa el workflow
|
||||||
|
4. Copia la URL del webhook
|
||||||
|
5. Pruébalo:
|
||||||
|
```bash
|
||||||
|
curl -X POST https://n8n.tudominio.com/webhook/mi-webhook \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"mensaje": "Hola desde webhook"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Webhook con Autenticación
|
||||||
|
|
||||||
|
Para proteger webhooks, añade autenticación en el propio workflow:
|
||||||
|
|
||||||
|
1. Añade un nodo **IF** después del webhook
|
||||||
|
2. Verifica un token o firma en los headers:
|
||||||
|
```javascript
|
||||||
|
{{ $node["Webhook"].json.headers.authorization }} === "Bearer mi-token-secreto"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Configuración Avanzada
|
||||||
|
|
||||||
|
### Variables de Entorno
|
||||||
|
|
||||||
|
n8n soporta muchas variables de entorno. Algunas útiles:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Ejecución
|
||||||
|
N8N_DEFAULT_BINARY_DATA_MODE=filesystem
|
||||||
|
EXECUTIONS_DATA_SAVE_ON_ERROR=all
|
||||||
|
EXECUTIONS_DATA_SAVE_ON_SUCCESS=all
|
||||||
|
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true
|
||||||
|
|
||||||
|
# Timeout
|
||||||
|
EXECUTIONS_TIMEOUT=300
|
||||||
|
EXECUTIONS_TIMEOUT_MAX=3600
|
||||||
|
|
||||||
|
# Comunidad
|
||||||
|
N8N_TEMPLATES_ENABLED=true
|
||||||
|
N8N_TEMPLATES_HOST=https://api.n8n.io/api/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
N8N_LOG_LEVEL=info
|
||||||
|
N8N_LOG_OUTPUT=console
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integración con Servicios Externos
|
||||||
|
|
||||||
|
#### Gmail
|
||||||
|
1. Crea credenciales OAuth2 en Google Cloud Console
|
||||||
|
2. En n8n, añade credencial de tipo **Gmail OAuth2**
|
||||||
|
3. Completa Client ID y Client Secret
|
||||||
|
4. Autoriza la aplicación
|
||||||
|
|
||||||
|
#### Slack
|
||||||
|
1. Crea una Slack App en api.slack.com
|
||||||
|
2. Añade permisos necesarios (chat:write, etc.)
|
||||||
|
3. En n8n, añade credencial de tipo **Slack OAuth2**
|
||||||
|
4. Autoriza la aplicación
|
||||||
|
|
||||||
|
#### Webhooks de GitHub
|
||||||
|
1. En tu repositorio de GitHub, ve a **Settings** → **Webhooks**
|
||||||
|
2. Añade webhook URL: `https://n8n.tudominio.com/webhook/github`
|
||||||
|
3. Selecciona eventos (push, pull request, etc.)
|
||||||
|
4. En n8n, procesa los eventos con nodos **IF** y **Switch**
|
||||||
|
|
||||||
|
### Programar Ejecuciones
|
||||||
|
|
||||||
|
Usa el nodo **Schedule Trigger**:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Cada hora
|
||||||
|
0 * * * *
|
||||||
|
|
||||||
|
# Cada día a las 9:00
|
||||||
|
0 9 * * *
|
||||||
|
|
||||||
|
# Cada lunes a las 8:30
|
||||||
|
30 8 * * 1
|
||||||
|
|
||||||
|
# Cada 5 minutos
|
||||||
|
*/5 * * * *
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### No puedo acceder a n8n
|
||||||
|
|
||||||
|
1. Verifica que el DNS apunta correctamente:
|
||||||
|
```bash
|
||||||
|
nslookup n8n.tudominio.com
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica los logs:
|
||||||
|
```bash
|
||||||
|
docker logs n8n
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica Traefik:
|
||||||
|
```bash
|
||||||
|
docker logs traefik | grep n8n
|
||||||
|
```
|
||||||
|
|
||||||
|
### Los webhooks no funcionan
|
||||||
|
|
||||||
|
1. Verifica que la URL del webhook es correcta
|
||||||
|
2. Asegúrate de que el workflow está **activado**
|
||||||
|
3. Revisa los logs de ejecución en n8n
|
||||||
|
4. Verifica que la configuración de Traefik permite webhooks sin autenticación
|
||||||
|
5. Prueba con curl:
|
||||||
|
```bash
|
||||||
|
curl -v https://n8n.tudominio.com/webhook/test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error al guardar credenciales
|
||||||
|
|
||||||
|
1. Verifica que `N8N_ENCRYPTION_KEY` está configurada
|
||||||
|
2. No cambies nunca esta clave después del primer uso
|
||||||
|
3. Revisa los logs: `docker logs n8n`
|
||||||
|
|
||||||
|
### La base de datos no conecta
|
||||||
|
|
||||||
|
1. Verifica que PostgreSQL está corriendo:
|
||||||
|
```bash
|
||||||
|
docker ps | grep n8n-pg
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica los logs de PostgreSQL:
|
||||||
|
```bash
|
||||||
|
docker logs n8n-pg
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica las credenciales en `stack.env`
|
||||||
|
|
||||||
|
### Workflows se ejecutan lentamente
|
||||||
|
|
||||||
|
1. Aumenta los recursos del contenedor
|
||||||
|
2. Verifica el timeout en variables de entorno
|
||||||
|
3. Optimiza el workflow (divide en workflows más pequeños)
|
||||||
|
4. Revisa los logs de ejecución
|
||||||
|
|
||||||
|
### Error "Execution timed out"
|
||||||
|
|
||||||
|
Aumenta el timeout en `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
EXECUTIONS_TIMEOUT=600
|
||||||
|
EXECUTIONS_TIMEOUT_MAX=7200
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Recursos Adicionales
|
||||||
|
|
||||||
|
- [Documentación oficial de n8n](https://docs.n8n.io/)
|
||||||
|
- [Workflows de ejemplo](https://n8n.io/workflows/)
|
||||||
|
- [Integrations](https://n8n.io/integrations/)
|
||||||
|
- [Forum de la comunidad](https://community.n8n.io/)
|
||||||
|
|
||||||
|
## 🎯 Casos de Uso
|
||||||
|
|
||||||
|
### Automatización de GitHub
|
||||||
|
- Notificar en Slack cuando hay un nuevo PR
|
||||||
|
- Ejecutar tests automáticos
|
||||||
|
- Crear issues desde emails
|
||||||
|
|
||||||
|
### Backup Automático
|
||||||
|
- Backup de bases de datos a Google Drive
|
||||||
|
- Notificaciones de éxito/error
|
||||||
|
- Programar backups diarios
|
||||||
|
|
||||||
|
### Monitoreo
|
||||||
|
- Verificar disponibilidad de sitios web
|
||||||
|
- Alertas por email/Slack si un servicio está caído
|
||||||
|
- Recopilar métricas y enviar a InfluxDB
|
||||||
|
|
||||||
|
### Integración con CRM
|
||||||
|
- Sincronizar contactos entre sistemas
|
||||||
|
- Automatizar seguimiento de leads
|
||||||
|
- Generar reportes automáticos
|
||||||
|
|
||||||
|
### Procesamiento de Datos
|
||||||
|
- Extraer datos de APIs
|
||||||
|
- Transformar y limpiar datos
|
||||||
|
- Cargar en bases de datos
|
||||||
|
|
||||||
|
## 🔒 Seguridad
|
||||||
|
|
||||||
|
- **Credenciales**: Todas las credenciales se cifran con `N8N_ENCRYPTION_KEY`
|
||||||
|
- **Webhooks**: Implementa autenticación personalizada en webhooks sensibles
|
||||||
|
- **UI**: Protegida con Authentik (SSO)
|
||||||
|
- **Backups**: Haz backup de la clave de cifrado y la base de datos
|
||||||
|
- **Variables**: No expongas secrets en los workflows; usa credenciales
|
||||||
|
|
||||||
|
## 💾 Backups
|
||||||
|
|
||||||
|
### Backup de la Base de Datos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup
|
||||||
|
docker exec n8n-pg pg_dump -U n8n n8n > n8n_backup_$(date +%Y%m%d).sql
|
||||||
|
|
||||||
|
# Restaurar
|
||||||
|
cat n8n_backup_YYYYMMDD.sql | docker exec -i n8n-pg psql -U n8n n8n
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup de la Clave de Cifrado
|
||||||
|
|
||||||
|
Guarda `N8N_ENCRYPTION_KEY` en un lugar seguro:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Extraer del stack.env
|
||||||
|
grep N8N_ENCRYPTION_KEY stack.env > encryption_key_backup.txt
|
||||||
|
|
||||||
|
# Guardar en un gestor de contraseñas o vault
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup de Workflows
|
||||||
|
|
||||||
|
n8n guarda workflows en la base de datos, por lo que el backup de PostgreSQL incluye los workflows.
|
||||||
|
|
||||||
|
También puedes exportar workflows manualmente:
|
||||||
|
1. En n8n, abre un workflow
|
||||||
|
2. Haz clic en los 3 puntos → **Download**
|
||||||
|
3. Guarda el archivo JSON
|
||||||
|
|
||||||
|
## 🔄 Actualizaciones
|
||||||
|
|
||||||
|
1. Haz **backup** de la base de datos y la clave de cifrado
|
||||||
|
2. Actualiza en `stack.env`:
|
||||||
|
```env
|
||||||
|
N8N_IMAGE=n8nio/n8n:latest
|
||||||
|
```
|
||||||
|
3. Actualiza el stack en Portainer
|
||||||
|
4. Verifica los logs: `docker logs n8n`
|
||||||
|
5. Prueba algunos workflows críticos
|
||||||
|
|
||||||
|
> **Nota**: n8n se actualiza frecuentemente. Revisa las [release notes](https://github.com/n8n-io/n8n/releases) antes de actualizar.
|
||||||
|
|
||||||
|
## 📊 Monitoreo
|
||||||
|
|
||||||
|
### Ver Ejecuciones
|
||||||
|
|
||||||
|
En n8n:
|
||||||
|
1. Ve a **Executions**
|
||||||
|
2. Filtra por estado (éxito, error, corriendo)
|
||||||
|
3. Revisa logs detallados de cada ejecución
|
||||||
|
|
||||||
|
### Logs del Contenedor
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Logs en tiempo real
|
||||||
|
docker logs -f n8n
|
||||||
|
|
||||||
|
# Últimas 100 líneas
|
||||||
|
docker logs --tail 100 n8n
|
||||||
|
|
||||||
|
# Logs con timestamps
|
||||||
|
docker logs -t n8n
|
||||||
|
```
|
||||||
|
|
||||||
|
### Métricas
|
||||||
|
|
||||||
|
n8n no tiene métricas Prometheus por defecto, pero puedes:
|
||||||
|
1. Crear un workflow que publique métricas
|
||||||
|
2. Usar el nodo HTTP Request para enviar a un collector
|
||||||
|
3. Monitorear logs con herramientas como Loki/Grafana
|
||||||
438
ruleta/README.md
Normal file
438
ruleta/README.md
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
# Ruleta - Aplicación Next.js
|
||||||
|
|
||||||
|
Aplicación web personalizada construida con Next.js.
|
||||||
|
|
||||||
|
## 📋 Descripción
|
||||||
|
|
||||||
|
Este stack despliega una aplicación Next.js con:
|
||||||
|
- Dos rutas de acceso: subdominio y path
|
||||||
|
- Integración con Traefik para HTTPS
|
||||||
|
- Soporte para múltiples dominios
|
||||||
|
- Configuración opcional de Authentik (SSO)
|
||||||
|
|
||||||
|
## 🚀 Despliegue
|
||||||
|
|
||||||
|
### Prerequisitos
|
||||||
|
|
||||||
|
1. **Red Docker**: Asegúrate de que la red `proxy` existe
|
||||||
|
2. **Registros DNS**: Configura los registros A para tus dominios
|
||||||
|
3. **Imagen Docker**: La aplicación debe estar construida como imagen Docker
|
||||||
|
|
||||||
|
### Desde Portainer
|
||||||
|
|
||||||
|
1. Ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `ruleta`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `ruleta/docker-compose.yml`
|
||||||
|
5. Carga el archivo de variables de entorno: `ruleta/stack.env`
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
### Variables de Entorno
|
||||||
|
|
||||||
|
Edita el archivo `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Imagen de la aplicación (construida previamente)
|
||||||
|
RULETA_IMAGE=tu-usuario/ruleta:latest
|
||||||
|
|
||||||
|
# Entorno de Node.js
|
||||||
|
RULETA_NODE_ENV=production
|
||||||
|
RULETA_NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
# Puerto interno de Next.js
|
||||||
|
RULETA_APP_PORT=3000
|
||||||
|
|
||||||
|
# Dominios
|
||||||
|
# Opción 1: Subdominio dedicado
|
||||||
|
RULETA_SUBDOMAIN=ruleta.tudominio.com
|
||||||
|
|
||||||
|
# Opción 2: Path en dominio principal
|
||||||
|
RULETA_MAIN_DOMAIN=tudominio.com
|
||||||
|
|
||||||
|
# Traefik
|
||||||
|
TRAEFIK_DOCKER_NETWORK=proxy
|
||||||
|
TRAEFIK_ENTRYPOINT_SECURE=websecure
|
||||||
|
TRAEFIK_CERTRESOLVER=letsencrypt
|
||||||
|
|
||||||
|
# Si usas Supabase, descomenta y configura:
|
||||||
|
# NEXT_PUBLIC_SUPABASE_URL=https://tu-proyecto.supabase.co
|
||||||
|
# NEXT_PUBLIC_SUPABASE_ANON_KEY=tu-clave-publica
|
||||||
|
# SUPABASE_SERVICE_ROLE_KEY=tu-clave-privada
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Rutas de Acceso
|
||||||
|
|
||||||
|
Esta aplicación tiene dos formas de acceso configuradas:
|
||||||
|
|
||||||
|
### 1. Subdominio Dedicado
|
||||||
|
|
||||||
|
Accede mediante: `https://ruleta.tudominio.com`
|
||||||
|
|
||||||
|
- URL completa del subdominio
|
||||||
|
- Next.js recibe las peticiones en el path raíz `/`
|
||||||
|
- No requiere configuración especial en Next.js
|
||||||
|
|
||||||
|
### 2. Path en Dominio Principal
|
||||||
|
|
||||||
|
Accede mediante: `https://tudominio.com/ruleta`
|
||||||
|
|
||||||
|
- Path dentro del dominio principal
|
||||||
|
- Traefik elimina el prefijo `/ruleta` antes de enviar a Next.js
|
||||||
|
- Next.js recibe las peticiones como si estuvieran en `/`
|
||||||
|
|
||||||
|
> **Nota**: Puedes usar ambas rutas simultáneamente o deshabilitar una editando el `docker-compose.yml`.
|
||||||
|
|
||||||
|
## 🔧 Configuración de Next.js
|
||||||
|
|
||||||
|
### Configurar basePath (si usas path)
|
||||||
|
|
||||||
|
Si quieres que Next.js sea consciente del path `/ruleta`, edita `next.config.js`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
basePath: '/ruleta',
|
||||||
|
assetPrefix: '/ruleta',
|
||||||
|
// ... otras opciones
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = nextConfig
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Nota**: Con la configuración actual (middleware de stripprefix en Traefik), esto NO es necesario. Traefik se encarga de eliminar el prefijo.
|
||||||
|
|
||||||
|
### Variables de Entorno en Next.js
|
||||||
|
|
||||||
|
Para exponer variables al cliente (navegador):
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// next.config.js
|
||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
CUSTOM_VAR: process.env.CUSTOM_VAR,
|
||||||
|
},
|
||||||
|
// o usa NEXT_PUBLIC_ prefix
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
En `stack.env`:
|
||||||
|
```env
|
||||||
|
NEXT_PUBLIC_API_URL=https://api.tudominio.com
|
||||||
|
CUSTOM_VAR=valor-personalizado
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 Proteger con Authentik (Opcional)
|
||||||
|
|
||||||
|
Por defecto, la aplicación NO está protegida con SSO. Para protegerla:
|
||||||
|
|
||||||
|
### Opción 1: Proteger Todo
|
||||||
|
|
||||||
|
Edita el `docker-compose.yml` y descomenta:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
# Para subdominio
|
||||||
|
traefik.http.routers.ruleta-sub.middlewares: "authentik@docker"
|
||||||
|
|
||||||
|
# Para path (requiere cadena de middlewares)
|
||||||
|
traefik.http.routers.ruleta-path.middlewares: "authentik@docker,ruleta-strip@docker"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Opción 2: Proteger Solo Ciertas Rutas
|
||||||
|
|
||||||
|
Crea routers adicionales en Traefik:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Router para rutas públicas
|
||||||
|
traefik.http.routers.ruleta-public.rule: "Host(`ruleta.tudominio.com`) && PathPrefix(`/api`, `/public`)"
|
||||||
|
traefik.http.routers.ruleta-public.priority: "20"
|
||||||
|
|
||||||
|
# Router para rutas protegidas
|
||||||
|
traefik.http.routers.ruleta-private.rule: "Host(`ruleta.tudominio.com`) && PathPrefix(`/admin`)"
|
||||||
|
traefik.http.routers.ruleta-private.middlewares: "authentik@docker"
|
||||||
|
traefik.http.routers.ruleta-private.priority: "30"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏗️ Construir la Imagen Docker
|
||||||
|
|
||||||
|
### Dockerfile de Ejemplo
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# Build stage
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:20-alpine AS runner
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
# Copiar archivos necesarios
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
COPY --from=builder /app/.next/standalone ./
|
||||||
|
COPY --from=builder /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["node", "server.js"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### next.config.js para Standalone
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
output: 'standalone',
|
||||||
|
// ... otras opciones
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = nextConfig
|
||||||
|
```
|
||||||
|
|
||||||
|
### Construir y Publicar
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Construir
|
||||||
|
docker build -t tu-usuario/ruleta:latest .
|
||||||
|
|
||||||
|
# Probar localmente
|
||||||
|
docker run -p 3000:3000 tu-usuario/ruleta:latest
|
||||||
|
|
||||||
|
# Publicar en Docker Hub
|
||||||
|
docker push tu-usuario/ruleta:latest
|
||||||
|
|
||||||
|
# O publicar en GitHub Container Registry
|
||||||
|
docker tag tu-usuario/ruleta:latest ghcr.io/tu-usuario/ruleta:latest
|
||||||
|
docker push ghcr.io/tu-usuario/ruleta:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Configuración Avanzada
|
||||||
|
|
||||||
|
### Integración con Supabase
|
||||||
|
|
||||||
|
Si tu aplicación usa Supabase:
|
||||||
|
|
||||||
|
1. Crea un proyecto en [supabase.com](https://supabase.com)
|
||||||
|
2. Obtén las credenciales:
|
||||||
|
- **URL del proyecto**: Settings → API → Project URL
|
||||||
|
- **Anon key**: Settings → API → anon public
|
||||||
|
- **Service role key**: Settings → API → service_role (secreto)
|
||||||
|
|
||||||
|
3. Añade a `stack.env`:
|
||||||
|
```env
|
||||||
|
NEXT_PUBLIC_SUPABASE_URL=https://tu-proyecto.supabase.co
|
||||||
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbG...
|
||||||
|
SUPABASE_SERVICE_ROLE_KEY=eyJhbG...
|
||||||
|
```
|
||||||
|
|
||||||
|
4. En tu código Next.js:
|
||||||
|
```javascript
|
||||||
|
import { createClient } from '@supabase/supabase-js'
|
||||||
|
|
||||||
|
const supabase = createClient(
|
||||||
|
process.env.NEXT_PUBLIC_SUPABASE_URL,
|
||||||
|
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables de Entorno Sensibles
|
||||||
|
|
||||||
|
Para secrets (API keys, tokens):
|
||||||
|
|
||||||
|
1. No las incluyas en `stack.env` si el repositorio es público
|
||||||
|
2. Configúralas manualmente en Portainer:
|
||||||
|
- Edita el stack
|
||||||
|
- Ve a la pestaña **Environment variables**
|
||||||
|
- Añade variables adicionales
|
||||||
|
|
||||||
|
3. O usa Docker secrets:
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
secrets:
|
||||||
|
- api_key
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
api_key:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Volúmenes para Datos Persistentes
|
||||||
|
|
||||||
|
Si necesitas persistir datos (uploads, cache):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
volumes:
|
||||||
|
- ${RULETA_DATA_PATH}:/app/data:Z
|
||||||
|
- ${RULETA_UPLOADS_PATH}:/app/public/uploads:Z
|
||||||
|
```
|
||||||
|
|
||||||
|
Añade a `stack.env`:
|
||||||
|
```env
|
||||||
|
RULETA_DATA_PATH=/opt/ruleta/data
|
||||||
|
RULETA_UPLOADS_PATH=/opt/ruleta/uploads
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### La aplicación no inicia
|
||||||
|
|
||||||
|
1. Verifica los logs:
|
||||||
|
```bash
|
||||||
|
docker logs ruleta-app
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica que la imagen existe:
|
||||||
|
```bash
|
||||||
|
docker images | grep ruleta
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica variables de entorno:
|
||||||
|
```bash
|
||||||
|
docker inspect ruleta-app | grep -A 20 Env
|
||||||
|
```
|
||||||
|
|
||||||
|
### No puedo acceder por dominio
|
||||||
|
|
||||||
|
1. Verifica DNS:
|
||||||
|
```bash
|
||||||
|
nslookup ruleta.tudominio.com
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica Traefik:
|
||||||
|
```bash
|
||||||
|
docker logs traefik | grep ruleta
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica labels de Traefik:
|
||||||
|
```bash
|
||||||
|
docker inspect ruleta-app | grep -A 30 Labels
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error 502 Bad Gateway
|
||||||
|
|
||||||
|
1. Verifica que el puerto interno es correcto:
|
||||||
|
- Next.js por defecto usa puerto 3000
|
||||||
|
- Verifica `RULETA_APP_PORT=3000`
|
||||||
|
|
||||||
|
2. Verifica que la aplicación está escuchando:
|
||||||
|
```bash
|
||||||
|
docker exec ruleta-app netstat -tulpn
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica conectividad desde Traefik:
|
||||||
|
```bash
|
||||||
|
docker exec traefik ping ruleta-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### Las rutas no funcionan con basePath
|
||||||
|
|
||||||
|
Si configuraste `basePath` en Next.js:
|
||||||
|
|
||||||
|
1. **Opción A**: Elimina el middleware `stripprefix` de Traefik
|
||||||
|
2. **Opción B**: Elimina `basePath` de Next.js (Traefik se encarga)
|
||||||
|
|
||||||
|
### Recursos estáticos (CSS/JS) no cargan
|
||||||
|
|
||||||
|
Verifica:
|
||||||
|
1. El `assetPrefix` en `next.config.js` (debe coincidir con basePath)
|
||||||
|
2. Los logs del navegador (F12 → Console)
|
||||||
|
3. Las rutas en el inspector de red (F12 → Network)
|
||||||
|
|
||||||
|
### Variables de entorno no disponibles
|
||||||
|
|
||||||
|
Recuerda:
|
||||||
|
- Solo variables con prefijo `NEXT_PUBLIC_` están disponibles en el navegador
|
||||||
|
- Variables sin prefijo solo están disponibles en el servidor (API routes, getServerSideProps)
|
||||||
|
|
||||||
|
## 📚 Recursos Adicionales
|
||||||
|
|
||||||
|
- [Documentación de Next.js](https://nextjs.org/docs)
|
||||||
|
- [Deploying Next.js](https://nextjs.org/docs/deployment)
|
||||||
|
- [Next.js con Docker](https://github.com/vercel/next.js/tree/canary/examples/with-docker)
|
||||||
|
- [Traefik con Next.js](https://doc.traefik.io/traefik/routing/routers/)
|
||||||
|
|
||||||
|
## 🔄 Actualizaciones
|
||||||
|
|
||||||
|
### Actualizar la Aplicación
|
||||||
|
|
||||||
|
1. Construye una nueva versión de la imagen:
|
||||||
|
```bash
|
||||||
|
docker build -t tu-usuario/ruleta:v2.0 .
|
||||||
|
docker push tu-usuario/ruleta:v2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Actualiza en `stack.env`:
|
||||||
|
```env
|
||||||
|
RULETA_IMAGE=tu-usuario/ruleta:v2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Actualiza el stack en Portainer
|
||||||
|
|
||||||
|
### Rolling Updates
|
||||||
|
|
||||||
|
Para actualizaciones sin downtime, usa múltiples réplicas (requiere Docker Swarm o Kubernetes).
|
||||||
|
|
||||||
|
### Rollback
|
||||||
|
|
||||||
|
Si algo sale mal:
|
||||||
|
|
||||||
|
1. Vuelve a la versión anterior en `stack.env`
|
||||||
|
2. Actualiza el stack en Portainer
|
||||||
|
|
||||||
|
## 📊 Monitoreo
|
||||||
|
|
||||||
|
### Logs de la Aplicación
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Logs en tiempo real
|
||||||
|
docker logs -f ruleta-app
|
||||||
|
|
||||||
|
# Últimas 100 líneas
|
||||||
|
docker logs --tail 100 ruleta-app
|
||||||
|
|
||||||
|
# Logs con timestamps
|
||||||
|
docker logs -t ruleta-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logs de Next.js
|
||||||
|
|
||||||
|
Next.js registra en stdout/stderr, accesibles con `docker logs`.
|
||||||
|
|
||||||
|
Para logs estructurados, considera usar:
|
||||||
|
- [Pino](https://github.com/pinojs/pino)
|
||||||
|
- [Winston](https://github.com/winstonjs/winston)
|
||||||
|
|
||||||
|
### Métricas
|
||||||
|
|
||||||
|
Para monitorear la aplicación:
|
||||||
|
1. Implementa un endpoint `/api/health`
|
||||||
|
2. Usa herramientas como Prometheus + Grafana
|
||||||
|
3. O servicios de APM como New Relic, Datadog
|
||||||
|
|
||||||
|
## 🎯 Casos de Uso
|
||||||
|
|
||||||
|
Este stack es ideal para:
|
||||||
|
- Aplicaciones Next.js personalizadas
|
||||||
|
- Landing pages
|
||||||
|
- Dashboards administrativos
|
||||||
|
- Aplicaciones full-stack con API routes
|
||||||
|
- JAMstack con SSR/SSG
|
||||||
|
|
||||||
|
## 💡 Tips
|
||||||
|
|
||||||
|
- Usa `output: 'standalone'` en Next.js para imágenes Docker más pequeñas
|
||||||
|
- Implementa caching con Redis para mejor rendimiento
|
||||||
|
- Usa ISR (Incremental Static Regeneration) para contenido dinámico
|
||||||
|
- Implementa rate limiting en API routes
|
||||||
|
- Usa CDN para assets estáticos (imágenes, CSS, JS)
|
||||||
382
trilium/README.md
Normal file
382
trilium/README.md
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
# Trilium Notes - Aplicación de Notas Jerárquicas
|
||||||
|
|
||||||
|
Trilium Notes es una aplicación de toma de notas jerárquicas con editor WYSIWYG, soporte para scripts, y cifrado de notas.
|
||||||
|
|
||||||
|
## 📋 Descripción
|
||||||
|
|
||||||
|
Este stack despliega Trilium con:
|
||||||
|
- Almacenamiento persistente de notas
|
||||||
|
- Acceso mediante HTTPS con Traefik
|
||||||
|
- Sincronización entre dispositivos
|
||||||
|
- Sin protección SSO (Trilium tiene su propio sistema de autenticación)
|
||||||
|
- Headers de seguridad configurados
|
||||||
|
|
||||||
|
## 🚀 Despliegue
|
||||||
|
|
||||||
|
### Prerequisitos
|
||||||
|
|
||||||
|
1. **Red Docker**: Asegúrate de que la red `proxy` existe
|
||||||
|
2. **Registro DNS**: Configura los registros A para tus dominios Trilium
|
||||||
|
|
||||||
|
### Desde Portainer
|
||||||
|
|
||||||
|
1. Ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `trilium`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `trilium/docker-compose.yml`
|
||||||
|
5. Carga el archivo de variables de entorno: `trilium/stack.env`
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
### Variables de Entorno
|
||||||
|
|
||||||
|
Edita el archivo `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Imagen
|
||||||
|
TRILIUM_IMAGE=zadam/trilium:latest
|
||||||
|
|
||||||
|
# Hostname (para identificación interna)
|
||||||
|
TRILIUM_HOSTNAME=trilium-server
|
||||||
|
|
||||||
|
# Puerto HTTP interno
|
||||||
|
TRILIUM_HTTP_PORT=8080
|
||||||
|
|
||||||
|
# Dominios (puedes tener múltiples dominios apuntando a la misma instancia)
|
||||||
|
TRILIUM_DOMAIN_1=notes.tudominio.com
|
||||||
|
TRILIUM_DOMAIN_2=trilium.tudominio.com
|
||||||
|
|
||||||
|
# Ruta de datos
|
||||||
|
TRILIUM_DATA_PATH=/opt/trilium/data
|
||||||
|
|
||||||
|
# Zona horaria
|
||||||
|
TZ=Europe/Madrid
|
||||||
|
|
||||||
|
# Traefik
|
||||||
|
TRAEFIK_DOCKER_NETWORK=proxy
|
||||||
|
TRAEFIK_ENTRYPOINT_SECURE=websecure
|
||||||
|
TRAEFIK_CERTRESOLVER=letsencrypt
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Configuración Post-Instalación
|
||||||
|
|
||||||
|
### 1. Primer Acceso
|
||||||
|
|
||||||
|
1. Accede a `https://notes.tudominio.com`
|
||||||
|
2. En el primer acceso, Trilium te pedirá crear una contraseña
|
||||||
|
3. **Guarda bien esta contraseña**: Es la contraseña maestra que protege todas tus notas
|
||||||
|
|
||||||
|
### 2. Configuración Inicial
|
||||||
|
|
||||||
|
Trilium te guiará por un tutorial interactivo. Explora:
|
||||||
|
- **Crear notas**: Haz clic en el botón + o usa `Ctrl+P`
|
||||||
|
- **Jerarquía**: Organiza notas en árbol jerárquico
|
||||||
|
- **Atributos**: Añade etiquetas (#tag) y relaciones
|
||||||
|
- **Scripts**: Automatiza tareas con JavaScript
|
||||||
|
|
||||||
|
### 3. Cifrado de Notas
|
||||||
|
|
||||||
|
Para cifrar notas sensibles:
|
||||||
|
|
||||||
|
1. Haz clic derecho en una nota → **Note info**
|
||||||
|
2. Añade el atributo `#encrypted`
|
||||||
|
3. Trilium te pedirá una contraseña de cifrado
|
||||||
|
4. La nota se cifrará localmente
|
||||||
|
|
||||||
|
### 4. Sincronización entre Dispositivos
|
||||||
|
|
||||||
|
Trilium soporta sincronización servidor-cliente:
|
||||||
|
|
||||||
|
#### Configurar Servidor (ya está hecho)
|
||||||
|
|
||||||
|
Tu instancia de Trilium ya funciona como servidor.
|
||||||
|
|
||||||
|
#### Configurar Cliente Desktop
|
||||||
|
|
||||||
|
1. Descarga Trilium Desktop desde [GitHub](https://github.com/zadam/trilium/releases)
|
||||||
|
2. Instálalo en tu PC/Mac/Linux
|
||||||
|
3. En el primer inicio, selecciona **Sync from server**
|
||||||
|
4. Configura:
|
||||||
|
- **Server URL**: `https://notes.tudominio.com`
|
||||||
|
- **Username**: Crea un usuario de sincronización en el servidor
|
||||||
|
- **Password**: Password del usuario
|
||||||
|
|
||||||
|
#### Crear Usuario de Sincronización
|
||||||
|
|
||||||
|
1. En el servidor web, ve a **Options** → **Sync**
|
||||||
|
2. Haz clic en **Create sync user**
|
||||||
|
3. Usuario: `mi-desktop`
|
||||||
|
4. Password: (genera uno seguro)
|
||||||
|
5. Copia las credenciales para usarlas en el cliente
|
||||||
|
|
||||||
|
## 🔧 Características Principales
|
||||||
|
|
||||||
|
### Notas Jerárquicas
|
||||||
|
|
||||||
|
- Organiza notas en árbol (padres e hijos)
|
||||||
|
- Múltiples padres por nota (clones)
|
||||||
|
- Drag & drop para reorganizar
|
||||||
|
|
||||||
|
### Tipos de Notas
|
||||||
|
|
||||||
|
- **Text**: Notas de texto con editor WYSIWYG
|
||||||
|
- **Code**: Notas de código con syntax highlighting
|
||||||
|
- **Render**: Notas que ejecutan HTML/JavaScript
|
||||||
|
- **Book**: Agrupaciones de notas
|
||||||
|
- **Relation map**: Mapas de relaciones entre notas
|
||||||
|
- **Canvas**: Notas de dibujo libre
|
||||||
|
|
||||||
|
### Atributos y Relaciones
|
||||||
|
|
||||||
|
```
|
||||||
|
#etiqueta - Etiqueta simple
|
||||||
|
#etiqueta=valor - Etiqueta con valor
|
||||||
|
~relacion=@notaId - Relación a otra nota
|
||||||
|
#cssClass=mi-clase - Clase CSS personalizada
|
||||||
|
#hideChildrenOverview - Oculta hijos en overview
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scripts
|
||||||
|
|
||||||
|
Trilium permite automatización con JavaScript:
|
||||||
|
|
||||||
|
1. Crea una nota de tipo **Code** (JavaScript)
|
||||||
|
2. Añade el atributo `#run=frontendStartup` o `#run=backendStartup`
|
||||||
|
3. El script se ejecutará automáticamente
|
||||||
|
|
||||||
|
Ejemplo - Script de búsqueda personalizada:
|
||||||
|
```javascript
|
||||||
|
api.addButtonToToolbar({
|
||||||
|
title: 'Buscar TODO',
|
||||||
|
icon: 'check',
|
||||||
|
action: () => {
|
||||||
|
const notes = api.searchForNotes('#todo !#done');
|
||||||
|
api.showMessage(`Encontradas ${notes.length} tareas pendientes`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Plantillas
|
||||||
|
|
||||||
|
Crea plantillas para notas recurrentes:
|
||||||
|
|
||||||
|
1. Crea una nota con la estructura deseada
|
||||||
|
2. Añade `#template`
|
||||||
|
3. Usa la plantilla: Clic derecho en padre → **Create note from template**
|
||||||
|
|
||||||
|
### Web Clipper
|
||||||
|
|
||||||
|
Captura contenido web directamente a Trilium:
|
||||||
|
|
||||||
|
1. Ve a **Options** → **Web clipper**
|
||||||
|
2. Sigue las instrucciones para instalar la extensión del navegador
|
||||||
|
3. Captura páginas web con un clic
|
||||||
|
|
||||||
|
## 🔧 Configuración Avanzada
|
||||||
|
|
||||||
|
### Backup Automático
|
||||||
|
|
||||||
|
Trilium hace backups automáticos diarios en `/opt/trilium/data/backup/`.
|
||||||
|
|
||||||
|
Para configurar backups externos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Script de backup
|
||||||
|
#!/bin/bash
|
||||||
|
BACKUP_DIR=/backups/trilium
|
||||||
|
DATE=$(date +%Y%m%d_%H%M%S)
|
||||||
|
|
||||||
|
# Backup de toda la data
|
||||||
|
tar -czf $BACKUP_DIR/trilium-$DATE.tar.gz /opt/trilium/data/
|
||||||
|
|
||||||
|
# Mantener solo últimos 30 días
|
||||||
|
find $BACKUP_DIR -name "trilium-*.tar.gz" -mtime +30 -delete
|
||||||
|
```
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
Trilium tiene una API ETAPI para integración:
|
||||||
|
|
||||||
|
1. Ve a **Options** → **ETAPI**
|
||||||
|
2. Crea un token de API
|
||||||
|
3. Úsalo en tus scripts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Obtener nota
|
||||||
|
curl -H "Authorization: YOUR_ETAPI_TOKEN" \
|
||||||
|
https://notes.tudominio.com/etapi/notes/noteId
|
||||||
|
|
||||||
|
# Crear nota
|
||||||
|
curl -X POST https://notes.tudominio.com/etapi/notes \
|
||||||
|
-H "Authorization: YOUR_ETAPI_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"noteId":"new-note","title":"Mi Nota","content":"Contenido"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Temas y Estilos
|
||||||
|
|
||||||
|
Personaliza la apariencia:
|
||||||
|
|
||||||
|
1. Crea una nota de tipo **Code** (CSS)
|
||||||
|
2. Añade `#appTheme`
|
||||||
|
3. Escribe tu CSS personalizado:
|
||||||
|
|
||||||
|
```css
|
||||||
|
/* Tema oscuro personalizado */
|
||||||
|
body {
|
||||||
|
--main-background-color: #1e1e1e;
|
||||||
|
--main-text-color: #d4d4d4;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shortcuts Personalizados
|
||||||
|
|
||||||
|
1. Ve a **Options** → **Keyboard shortcuts**
|
||||||
|
2. Personaliza o añade nuevos shortcuts
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### No puedo acceder a Trilium
|
||||||
|
|
||||||
|
1. Verifica que está corriendo:
|
||||||
|
```bash
|
||||||
|
docker ps | grep trilium
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica los logs:
|
||||||
|
```bash
|
||||||
|
docker logs trilium
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica DNS:
|
||||||
|
```bash
|
||||||
|
nslookup notes.tudominio.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Olvidé la contraseña maestra
|
||||||
|
|
||||||
|
Si perdiste la contraseña maestra, NO HAY forma de recuperarla. Las notas están cifradas localmente.
|
||||||
|
|
||||||
|
**Prevención**:
|
||||||
|
- Guarda la contraseña en un gestor de contraseñas
|
||||||
|
- Haz backups regulares de `/opt/trilium/data/`
|
||||||
|
- Considera no usar cifrado para todas las notas
|
||||||
|
|
||||||
|
### Sincronización no funciona
|
||||||
|
|
||||||
|
1. Verifica las credenciales del usuario de sync
|
||||||
|
2. Revisa los logs del servidor:
|
||||||
|
```bash
|
||||||
|
docker logs trilium | grep sync
|
||||||
|
```
|
||||||
|
3. En el cliente, ve a **Options** → **Sync** → **Check for updates**
|
||||||
|
4. Fuerza sincronización: **Options** → **Sync** → **Force full sync**
|
||||||
|
|
||||||
|
### Notas no se guardan
|
||||||
|
|
||||||
|
1. Verifica espacio en disco:
|
||||||
|
```bash
|
||||||
|
df -h /opt/trilium/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica permisos:
|
||||||
|
```bash
|
||||||
|
ls -lh /opt/trilium/data/
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Revisa los logs para errores
|
||||||
|
|
||||||
|
### Performance lento
|
||||||
|
|
||||||
|
1. Verifica el tamaño de la base de datos:
|
||||||
|
```bash
|
||||||
|
du -sh /opt/trilium/data/document.db
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Considera optimizar la base de datos:
|
||||||
|
- Ve a **Options** → **Advanced** → **Anonymize database**
|
||||||
|
- Esto elimina historial antiguo
|
||||||
|
|
||||||
|
3. Aumenta recursos del contenedor si es necesario
|
||||||
|
|
||||||
|
## 📚 Recursos Adicionales
|
||||||
|
|
||||||
|
- [Documentación oficial de Trilium](https://github.com/zadam/trilium/wiki)
|
||||||
|
- [Galería de plantillas](https://github.com/zadam/trilium/wiki/Gallery)
|
||||||
|
- [Scripts de ejemplo](https://github.com/zadam/trilium/wiki/Scripts)
|
||||||
|
- [Forum de la comunidad](https://github.com/zadam/trilium/discussions)
|
||||||
|
|
||||||
|
## 🔒 Seguridad
|
||||||
|
|
||||||
|
- **Contraseña maestra**: Protege todas tus notas
|
||||||
|
- **Cifrado opcional**: Usa `#encrypted` para notas sensibles
|
||||||
|
- **HTTPS**: Todo el tráfico está cifrado con SSL
|
||||||
|
- **Backups**: Haz backups regulares de tus notas
|
||||||
|
- **Sin SSO**: Trilium gestiona su propia autenticación (más seguro para notas personales)
|
||||||
|
|
||||||
|
## 💾 Backups
|
||||||
|
|
||||||
|
### Backup Manual
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup completo
|
||||||
|
sudo tar -czf trilium-backup-$(date +%Y%m%d).tar.gz /opt/trilium/data/
|
||||||
|
|
||||||
|
# Solo base de datos
|
||||||
|
sudo cp /opt/trilium/data/document.db trilium-db-backup-$(date +%Y%m%d).db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restaurar
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Detener Trilium
|
||||||
|
docker stop trilium
|
||||||
|
|
||||||
|
# Restaurar backup
|
||||||
|
sudo tar -xzf trilium-backup-YYYYMMDD.tar.gz -C /
|
||||||
|
|
||||||
|
# Reiniciar
|
||||||
|
docker start trilium
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Automático (dentro de Trilium)
|
||||||
|
|
||||||
|
Trilium hace backups automáticos:
|
||||||
|
- **Ubicación**: `/opt/trilium/data/backup/`
|
||||||
|
- **Frecuencia**: Diaria
|
||||||
|
- **Retención**: Configurable en **Options** → **Other**
|
||||||
|
|
||||||
|
## 🔄 Actualizaciones
|
||||||
|
|
||||||
|
1. Haz **backup completo** antes de actualizar
|
||||||
|
2. Actualiza en `stack.env`:
|
||||||
|
```env
|
||||||
|
TRILIUM_IMAGE=zadam/trilium:0.63.7
|
||||||
|
```
|
||||||
|
3. Actualiza el stack en Portainer
|
||||||
|
4. Verifica los logs: `docker logs trilium`
|
||||||
|
5. Accede y verifica que todo funciona
|
||||||
|
|
||||||
|
> **Nota**: Revisa el [changelog](https://github.com/zadam/trilium/blob/master/CHANGELOG.md) antes de actualizar.
|
||||||
|
|
||||||
|
## 📊 Uso
|
||||||
|
|
||||||
|
### Casos de Uso
|
||||||
|
|
||||||
|
- **Notas personales**: Diario, ideas, recordatorios
|
||||||
|
- **Base de conocimiento**: Wiki personal, documentación
|
||||||
|
- **Gestión de proyectos**: Tareas, planificación
|
||||||
|
- **Investigación**: Organización de información
|
||||||
|
- **Snippets de código**: Biblioteca de código reutilizable
|
||||||
|
- **Journaling**: Diario personal cifrado
|
||||||
|
|
||||||
|
### Tips
|
||||||
|
|
||||||
|
- Usa `Ctrl+P` para búsqueda rápida
|
||||||
|
- Usa `Ctrl+S` para guardar (automático)
|
||||||
|
- Usa `Alt+Up/Down` para navegar por el árbol
|
||||||
|
- Usa `Ctrl+K` para crear links internos
|
||||||
|
- Usa `#` para etiquetas en el título
|
||||||
|
- Usa backlinks para ver referencias a una nota
|
||||||
435
wireguard/README.md
Normal file
435
wireguard/README.md
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
# WireGuard - VPN Rápida y Segura
|
||||||
|
|
||||||
|
WireGuard es una VPN moderna, rápida y segura. Este stack usa `wg-easy` para gestión simplificada de clientes.
|
||||||
|
|
||||||
|
## 📋 Descripción
|
||||||
|
|
||||||
|
Este stack despliega WireGuard con:
|
||||||
|
- Interfaz web para gestión de clientes (wg-easy)
|
||||||
|
- Generación automática de configuraciones de clientes
|
||||||
|
- Códigos QR para configuración móvil rápida
|
||||||
|
- Panel web protegido con Authentik
|
||||||
|
- Puerto UDP para el túnel VPN
|
||||||
|
|
||||||
|
## 🚀 Despliegue
|
||||||
|
|
||||||
|
### Prerequisitos
|
||||||
|
|
||||||
|
1. **Red Docker**: Asegúrate de que la red `proxy` existe
|
||||||
|
2. **Registro DNS**: Configura el registro A para tu dominio WireGuard
|
||||||
|
3. **Puerto UDP**: El puerto UDP debe estar abierto en el firewall (por defecto 51820)
|
||||||
|
4. **Kernel modules**: El servidor debe soportar WireGuard
|
||||||
|
|
||||||
|
### Verificar Soporte WireGuard
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verificar módulo WireGuard
|
||||||
|
lsmod | grep wireguard
|
||||||
|
|
||||||
|
# O intentar cargarlo
|
||||||
|
sudo modprobe wireguard
|
||||||
|
|
||||||
|
# Si falla, instala wireguard-tools
|
||||||
|
sudo dnf install wireguard-tools # Fedora/RHEL
|
||||||
|
sudo apt install wireguard # Debian/Ubuntu
|
||||||
|
```
|
||||||
|
|
||||||
|
### Desde Portainer
|
||||||
|
|
||||||
|
1. Ve a **Stacks** → **Add stack**
|
||||||
|
2. Nombre: `wireguard`
|
||||||
|
3. Selecciona **Repository** o **Git repository**
|
||||||
|
4. Configura:
|
||||||
|
- Repository URL: `<tu-repositorio>`
|
||||||
|
- Repository reference: `main`
|
||||||
|
- Compose path: `wireguard/docker-compose.yml`
|
||||||
|
5. Carga el archivo de variables de entorno: `wireguard/stack.env`
|
||||||
|
6. Haz clic en **Deploy the stack**
|
||||||
|
|
||||||
|
### Variables de Entorno
|
||||||
|
|
||||||
|
Edita el archivo `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Imagen
|
||||||
|
WG_EASY_IMAGE=ghcr.io/wg-easy/wg-easy:latest
|
||||||
|
|
||||||
|
# Dominio o IP pública del servidor
|
||||||
|
WG_HOST=vpn.tudominio.com
|
||||||
|
|
||||||
|
# Puerto UDP de WireGuard (debe estar abierto en el firewall)
|
||||||
|
WG_PORT=51820
|
||||||
|
WG_UDP_PORT=51820
|
||||||
|
|
||||||
|
# Puerto HTTP de la UI (interno)
|
||||||
|
WG_UI_PORT=51821
|
||||||
|
|
||||||
|
# Credenciales iniciales para la UI
|
||||||
|
INIT_ENABLED=true
|
||||||
|
INIT_USERNAME=admin
|
||||||
|
INIT_PASSWORD=tu-password-seguro
|
||||||
|
|
||||||
|
# Desactivar IPv6 (si el servidor no lo soporta)
|
||||||
|
DISABLE_IPV6=true
|
||||||
|
|
||||||
|
# Rutas
|
||||||
|
WG_DATA_PATH=/opt/wireguard/data
|
||||||
|
WG_MODULES_PATH=/lib/modules
|
||||||
|
|
||||||
|
# Dominio de la UI
|
||||||
|
WG_DOMAIN=vpn-admin.tudominio.com
|
||||||
|
|
||||||
|
# Traefik
|
||||||
|
TRAEFIK_DOCKER_NETWORK=proxy
|
||||||
|
TRAEFIK_ENTRYPOINT_SECURE=websecure
|
||||||
|
TRAEFIK_CERTRESOLVER=letsencrypt
|
||||||
|
TRAEFIK_AUTH_MIDDLEWARE=authentik@docker
|
||||||
|
```
|
||||||
|
|
||||||
|
> **⚠️ Importante**:
|
||||||
|
> - Cambia `INIT_PASSWORD` por una contraseña segura
|
||||||
|
> - Usa tu dominio o IP pública en `WG_HOST`
|
||||||
|
|
||||||
|
### Abrir Puerto UDP en el Firewall
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Firewalld (Fedora/RHEL)
|
||||||
|
sudo firewall-cmd --permanent --add-port=51820/udp
|
||||||
|
sudo firewall-cmd --reload
|
||||||
|
|
||||||
|
# UFW (Ubuntu/Debian)
|
||||||
|
sudo ufw allow 51820/udp
|
||||||
|
|
||||||
|
# iptables
|
||||||
|
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
|
||||||
|
sudo iptables-save > /etc/iptables/rules.v4
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Configuración Post-Instalación
|
||||||
|
|
||||||
|
### 1. Acceso al Panel Web
|
||||||
|
|
||||||
|
1. Accede a `https://vpn-admin.tudominio.com`
|
||||||
|
2. Si configuraste Authentik, serás redirigido al SSO
|
||||||
|
3. Inicia sesión con las credenciales configuradas en `INIT_USERNAME` y `INIT_PASSWORD`
|
||||||
|
|
||||||
|
### 2. Crear Cliente VPN
|
||||||
|
|
||||||
|
1. En el panel web, haz clic en **+ Add Client**
|
||||||
|
2. Nombre del cliente: `mi-laptop`, `mi-movil`, etc.
|
||||||
|
3. El cliente se crea automáticamente con:
|
||||||
|
- Par de claves pública/privada
|
||||||
|
- IP asignada dentro del túnel VPN
|
||||||
|
- Configuración completa
|
||||||
|
|
||||||
|
### 3. Configurar Cliente
|
||||||
|
|
||||||
|
#### Móvil (Android/iOS)
|
||||||
|
|
||||||
|
1. Instala la app **WireGuard** desde Play Store o App Store
|
||||||
|
2. En el panel web, haz clic en el icono **QR** del cliente
|
||||||
|
3. Escanea el código QR con la app
|
||||||
|
4. Activa el túnel VPN
|
||||||
|
|
||||||
|
#### Windows/Mac/Linux Desktop
|
||||||
|
|
||||||
|
##### Opción A: Escanear QR
|
||||||
|
|
||||||
|
1. Descarga WireGuard desde [wireguard.com](https://www.wireguard.com/install/)
|
||||||
|
2. Instala la aplicación
|
||||||
|
3. Haz clic en **Import tunnel(s) from QR code**
|
||||||
|
4. Escanea el QR del panel web con tu webcam
|
||||||
|
|
||||||
|
##### Opción B: Descargar archivo de configuración
|
||||||
|
|
||||||
|
1. En el panel web, haz clic en el icono **Download** del cliente
|
||||||
|
2. Guarda el archivo `.conf`
|
||||||
|
3. En WireGuard app, haz clic en **Import tunnel(s) from file**
|
||||||
|
4. Selecciona el archivo `.conf`
|
||||||
|
|
||||||
|
##### Opción C: Configuración manual
|
||||||
|
|
||||||
|
Copia la configuración del panel web:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Interface]
|
||||||
|
PrivateKey = tu_clave_privada
|
||||||
|
Address = 10.8.0.2/24
|
||||||
|
DNS = 1.1.1.1
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = clave_publica_servidor
|
||||||
|
PresharedKey = clave_compartida
|
||||||
|
Endpoint = vpn.tudominio.com:51820
|
||||||
|
AllowedIPs = 0.0.0.0/0, ::/0
|
||||||
|
PersistentKeepalive = 25
|
||||||
|
```
|
||||||
|
|
||||||
|
Guarda como `cliente.conf` y carga en WireGuard.
|
||||||
|
|
||||||
|
### 4. Verificar Conexión
|
||||||
|
|
||||||
|
Una vez activado el túnel:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verificar IP pública (debe ser la de tu servidor VPN)
|
||||||
|
curl ifconfig.me
|
||||||
|
|
||||||
|
# Ping al servidor VPN (IP interna)
|
||||||
|
ping 10.8.0.1
|
||||||
|
|
||||||
|
# Verificar DNS
|
||||||
|
nslookup google.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Configuración Avanzada
|
||||||
|
|
||||||
|
### Rutear Solo Tráfico Específico (Split Tunneling)
|
||||||
|
|
||||||
|
Por defecto, WireGuard enruta TODO el tráfico (`AllowedIPs = 0.0.0.0/0`).
|
||||||
|
|
||||||
|
Para rutear solo ciertos rangos:
|
||||||
|
|
||||||
|
1. Descarga el archivo `.conf` del cliente
|
||||||
|
2. Edita `AllowedIPs`:
|
||||||
|
```ini
|
||||||
|
AllowedIPs = 10.8.0.0/24, 192.168.1.0/24
|
||||||
|
```
|
||||||
|
3. Importa el archivo modificado en el cliente
|
||||||
|
|
||||||
|
Ejemplos:
|
||||||
|
- Solo red VPN: `10.8.0.0/24`
|
||||||
|
- Red VPN + red local del servidor: `10.8.0.0/24, 192.168.1.0/24`
|
||||||
|
- Todo excepto red local del cliente: `0.0.0.0/1, 128.0.0.0/1`
|
||||||
|
|
||||||
|
### Cambiar Rango de IPs de la VPN
|
||||||
|
|
||||||
|
Por defecto usa `10.8.0.0/24`. Para cambiar:
|
||||||
|
|
||||||
|
1. Detén el stack
|
||||||
|
2. Edita `/opt/wireguard/data/wireguard.conf`
|
||||||
|
3. Cambia:
|
||||||
|
```ini
|
||||||
|
[Interface]
|
||||||
|
Address = 10.9.0.1/24
|
||||||
|
```
|
||||||
|
4. Actualiza también en cada cliente
|
||||||
|
5. Reinicia el stack
|
||||||
|
|
||||||
|
### Usar DNS Personalizado
|
||||||
|
|
||||||
|
Para que los clientes usen tu AdGuard Home:
|
||||||
|
|
||||||
|
1. En el panel web, ve a **Settings**
|
||||||
|
2. Cambia **DNS** a la IP de tu servidor (ej: `192.168.1.10`)
|
||||||
|
3. O edita manualmente en cada archivo `.conf`:
|
||||||
|
```ini
|
||||||
|
DNS = IP-de-tu-AdGuard
|
||||||
|
```
|
||||||
|
|
||||||
|
### Limitar Ancho de Banda
|
||||||
|
|
||||||
|
No soportado directamente por wg-easy, pero puedes usar `tc` en el servidor:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Limitar a 10 Mbps
|
||||||
|
sudo tc qdisc add dev wg0 root tbf rate 10mbit burst 32kbit latency 400ms
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configurar Post-Up/Post-Down Scripts
|
||||||
|
|
||||||
|
Para ejecutar scripts al iniciar/detener el túnel:
|
||||||
|
|
||||||
|
Edita `/opt/wireguard/data/wireguard.conf`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Interface]
|
||||||
|
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
|
||||||
|
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### No puedo conectar al VPN
|
||||||
|
|
||||||
|
1. Verifica que el puerto UDP está abierto:
|
||||||
|
```bash
|
||||||
|
sudo netstat -tulpn | grep 51820
|
||||||
|
nc -zuv vpn.tudominio.com 51820
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica que WireGuard está corriendo:
|
||||||
|
```bash
|
||||||
|
docker logs wg-easy
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica que el módulo WireGuard está cargado:
|
||||||
|
```bash
|
||||||
|
lsmod | grep wireguard
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Verifica la configuración del cliente (especialmente `Endpoint`)
|
||||||
|
|
||||||
|
### Conecta pero no hay Internet
|
||||||
|
|
||||||
|
1. Verifica que el forwarding está habilitado en el servidor:
|
||||||
|
```bash
|
||||||
|
cat /proc/sys/net/ipv4/ip_forward # Debe ser 1
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica las reglas de iptables:
|
||||||
|
```bash
|
||||||
|
sudo iptables -L -v -n
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica la configuración de NAT en wg-easy
|
||||||
|
|
||||||
|
### Panel web no accesible
|
||||||
|
|
||||||
|
1. Verifica que está corriendo:
|
||||||
|
```bash
|
||||||
|
docker ps | grep wg-easy
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica los logs:
|
||||||
|
```bash
|
||||||
|
docker logs wg-easy
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verifica Traefik:
|
||||||
|
```bash
|
||||||
|
docker logs traefik | grep wg
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error "Cannot find device wg0"
|
||||||
|
|
||||||
|
El módulo WireGuard no está cargado:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Intentar cargar
|
||||||
|
sudo modprobe wireguard
|
||||||
|
|
||||||
|
# Si falla, instalar
|
||||||
|
sudo dnf install wireguard-tools # Fedora/RHEL
|
||||||
|
sudo apt install wireguard # Debian/Ubuntu
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clientes se desconectan frecuentemente
|
||||||
|
|
||||||
|
1. Aumenta `PersistentKeepalive` en la configuración del cliente:
|
||||||
|
```ini
|
||||||
|
PersistentKeepalive = 25
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verifica el MTU (puede ser muy alto para tu red):
|
||||||
|
```ini
|
||||||
|
MTU = 1280
|
||||||
|
```
|
||||||
|
|
||||||
|
### IPv6 causa problemas
|
||||||
|
|
||||||
|
Desactiva IPv6 en `stack.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DISABLE_IPV6=true
|
||||||
|
```
|
||||||
|
|
||||||
|
Y reinicia el stack.
|
||||||
|
|
||||||
|
## 📚 Recursos Adicionales
|
||||||
|
|
||||||
|
- [Documentación oficial de WireGuard](https://www.wireguard.com/)
|
||||||
|
- [wg-easy en GitHub](https://github.com/wg-easy/wg-easy)
|
||||||
|
- [Guía de WireGuard](https://www.wireguard.com/quickstart/)
|
||||||
|
|
||||||
|
## 🔒 Seguridad
|
||||||
|
|
||||||
|
- **Cifrado**: WireGuard usa criptografía moderna (ChaCha20, Curve25519)
|
||||||
|
- **Panel web**: Protegido con Authentik (SSO)
|
||||||
|
- **Claves**: Cada cliente tiene su par de claves único
|
||||||
|
- **PresharedKey**: Capa adicional de seguridad cuántica
|
||||||
|
- **Firewall**: Solo el puerto UDP de WireGuard debe estar abierto
|
||||||
|
|
||||||
|
### Best Practices
|
||||||
|
|
||||||
|
1. **Cambia la contraseña** del panel web
|
||||||
|
2. **Usa Authentik** para proteger el panel
|
||||||
|
3. **Limita IPs** si solo necesitas acceso desde ciertos rangos
|
||||||
|
4. **Revoca clientes** cuando ya no los uses
|
||||||
|
5. **Haz backups** de `/opt/wireguard/data/`
|
||||||
|
|
||||||
|
## 💾 Backups
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup de configuraciones
|
||||||
|
sudo tar -czf wireguard-backup-$(date +%Y%m%d).tar.gz /opt/wireguard/data/
|
||||||
|
|
||||||
|
# Restaurar
|
||||||
|
sudo tar -xzf wireguard-backup-YYYYMMDD.tar.gz -C /
|
||||||
|
docker restart wg-easy
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Importante**: Guarda los backups de forma segura. Contienen las claves privadas.
|
||||||
|
|
||||||
|
## 🔄 Actualizaciones
|
||||||
|
|
||||||
|
1. Haz backup de `/opt/wireguard/data/`
|
||||||
|
2. Actualiza en `stack.env`:
|
||||||
|
```env
|
||||||
|
WG_EASY_IMAGE=ghcr.io/wg-easy/wg-easy:latest
|
||||||
|
```
|
||||||
|
3. Actualiza el stack en Portainer
|
||||||
|
4. Verifica que los clientes siguen conectando
|
||||||
|
|
||||||
|
## 📊 Monitoreo
|
||||||
|
|
||||||
|
### Ver Clientes Conectados
|
||||||
|
|
||||||
|
En el panel web, verás:
|
||||||
|
- Clientes activos (verde)
|
||||||
|
- Última conexión
|
||||||
|
- Transferencia de datos
|
||||||
|
- IP asignada
|
||||||
|
|
||||||
|
### Ver Stats del Túnel
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Desde el servidor
|
||||||
|
docker exec wg-easy wg show
|
||||||
|
|
||||||
|
# Ver configuración
|
||||||
|
docker exec wg-easy cat /etc/wireguard/wg0.conf
|
||||||
|
|
||||||
|
# Ver logs
|
||||||
|
docker logs -f wg-easy
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 Casos de Uso
|
||||||
|
|
||||||
|
### Acceso Remoto Seguro
|
||||||
|
|
||||||
|
Accede a tu red doméstica desde cualquier lugar:
|
||||||
|
- Administra servidores
|
||||||
|
- Accede a servicios internos
|
||||||
|
- Usa impresoras de red
|
||||||
|
|
||||||
|
### Protección en Redes Públicas
|
||||||
|
|
||||||
|
Usa WireGuard en WiFi públicas para:
|
||||||
|
- Cifrar todo el tráfico
|
||||||
|
- Evitar ataques Man-in-the-Middle
|
||||||
|
- Proteger tus datos
|
||||||
|
|
||||||
|
### Bypass de Restricciones Geográficas
|
||||||
|
|
||||||
|
Usa la IP de tu servidor para:
|
||||||
|
- Acceder a contenido local
|
||||||
|
- Evitar censura
|
||||||
|
- Mantener tu IP original
|
||||||
|
|
||||||
|
### Combinar con AdGuard
|
||||||
|
|
||||||
|
Configura los clientes VPN para usar tu AdGuard Home:
|
||||||
|
- Bloqueo de anuncios en móvil
|
||||||
|
- Protección contra rastreadores
|
||||||
|
- DNS filtrado incluso fuera de casa
|
||||||
Reference in New Issue
Block a user