Compare commits
17 Commits
afb95f4375
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| fef085efef | |||
| ba4d444f7e | |||
| 7c0b7b62c1 | |||
| 1822c4f3fb | |||
| 91e4a2f8af | |||
| 416bfe0430 | |||
| 811b0ad61a | |||
| f6e2ddd714 | |||
| 24d46bfbf3 | |||
| 400d41687b | |||
| dec01f536c | |||
| 7575b004ab | |||
| 6e7067c91f | |||
| f3815ae8df | |||
| 4e9a74850c | |||
| 77666edf14 | |||
| cf589780f9 |
39
README.md
39
README.md
@@ -12,9 +12,10 @@ Traefik es un reverse proxy moderno y ligero que detecta servicios Docker autom
|
|||||||
|
|
||||||
- 🔒 HTTPS automático con Let's Encrypt (HTTP-01)
|
- 🔒 HTTPS automático con Let's Encrypt (HTTP-01)
|
||||||
- 🧠 Descubrimiento automático de servicios Docker
|
- 🧠 Descubrimiento automático de servicios Docker
|
||||||
- 🧷 Redirección HTTP→HTTPS
|
- 🧿 Redirección HTTP→HTTPS
|
||||||
- 🧰 Dashboard web (seguro por dominio)
|
- 🧰 Dashboard web (seguro por dominio)
|
||||||
- 🧩 Middlewares: auth básica, headers de seguridad, rate limit, etc.
|
- 🧩 Middlewares: auth básica, headers de seguridad, rate limit, etc.
|
||||||
|
- 📊 Logs de acceso y errores (stdout/stderr)
|
||||||
|
|
||||||
## Requisitos
|
## Requisitos
|
||||||
|
|
||||||
@@ -31,13 +32,7 @@ Internet → Traefik (80/443) → Servicios (en red proxy)
|
|||||||
|
|
||||||
## Despliegue
|
## Despliegue
|
||||||
|
|
||||||
### 1) Crear red `proxy`
|
### 1) Clonar y configurar
|
||||||
|
|
||||||
```bash
|
|
||||||
docker network create proxy
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2) Clonar y configurar
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.ictiberia.com/groales/traefik
|
git clone https://git.ictiberia.com/groales/traefik
|
||||||
@@ -49,7 +44,7 @@ touch ./letsencrypt/acme.json
|
|||||||
chmod 600 ./letsencrypt/acme.json
|
chmod 600 ./letsencrypt/acme.json
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3) Editar configuración
|
### 2) Editar configuración
|
||||||
|
|
||||||
**IMPORTANTE:** Antes de desplegar, edita los siguientes archivos con tus datos reales:
|
**IMPORTANTE:** Antes de desplegar, edita los siguientes archivos con tus datos reales:
|
||||||
|
|
||||||
@@ -61,16 +56,15 @@ certificatesResolvers:
|
|||||||
email: tu-email@tudominio.com # ← EDITA AQUÍ
|
email: tu-email@tudominio.com # ← EDITA AQUÍ
|
||||||
```
|
```
|
||||||
|
|
||||||
**docker-compose.yaml:**
|
**docker-compose.yml:**
|
||||||
```yaml
|
```yaml
|
||||||
labels:
|
labels:
|
||||||
- "traefik.http.routers.traefik.rule=Host(`traefik.tudominio.com`)" # ← EDITA AQUÍ
|
- "traefik.http.routers.traefik.rule=Host(`traefik.tudominio.com`)" # ← EDITA AQUÍ
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4) Desplegar
|
### 3) Desplegar
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker network create proxy # Si no existe
|
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -78,7 +72,7 @@ docker compose up -d
|
|||||||
|
|
||||||
Este stack expone el dashboard por dominio usando TLS y el servicio interno `api@internal`.
|
Este stack expone el dashboard por dominio usando TLS y el servicio interno `api@internal`.
|
||||||
|
|
||||||
**Autenticación básica habilitada:** El dashboard está protegido mediante el middleware `auth-basic@file` definido en `dynamic/middlewares.yml`.
|
**Autenticación básica habilitada:** El dashboard está protegido mediante el middleware `auth-basic@file` definido en `dynamic/config.yml`.
|
||||||
|
|
||||||
### Configurar contraseña
|
### Configurar contraseña
|
||||||
|
|
||||||
@@ -87,7 +81,7 @@ Este stack expone el dashboard por dominio usando TLS y el servicio interno `api
|
|||||||
docker run --rm httpd:alpine htpasswd -nbB admin tu_password_segura
|
docker run --rm httpd:alpine htpasswd -nbB admin tu_password_segura
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Edita `dynamic/middlewares.yml` línea 35 y reemplaza el hash de ejemplo:
|
2. Edita `dynamic/config.yml` (sección middlewares > auth-basic) y reemplaza el hash de ejemplo:
|
||||||
```yaml
|
```yaml
|
||||||
auth-basic:
|
auth-basic:
|
||||||
basicAuth:
|
basicAuth:
|
||||||
@@ -137,6 +131,23 @@ certificatesResolvers:
|
|||||||
caServer: https://acme-staging-v02.api.letsencrypt.org/directory
|
caServer: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Logs
|
||||||
|
|
||||||
|
Traefik envía logs a stdout/stderr (sin persistencia en disco):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ver logs en tiempo real
|
||||||
|
docker logs -f traefik
|
||||||
|
|
||||||
|
# Filtrar errores
|
||||||
|
docker logs traefik | Select-String -Pattern error
|
||||||
|
|
||||||
|
# Ver logs de acceso
|
||||||
|
docker logs traefik | Select-String -Pattern "GET|POST"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nivel de log**: INFO (configurable en `traefik.yml` → `log.level`)
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
- Certificado no se emite:
|
- Certificado no se emite:
|
||||||
|
|||||||
@@ -24,9 +24,10 @@ services:
|
|||||||
- "traefik.http.routers.traefik.tls=true"
|
- "traefik.http.routers.traefik.tls=true"
|
||||||
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
|
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
|
||||||
- "traefik.http.routers.traefik.service=api@internal"
|
- "traefik.http.routers.traefik.service=api@internal"
|
||||||
# Autenticación básica (usa middleware del archivo dynamic/middlewares.yml)
|
# Autenticación básica (usa middleware del archivo dynamic/config.yml)
|
||||||
- "traefik.http.routers.traefik.middlewares=auth-basic@file"
|
- "traefik.http.routers.traefik.middlewares=auth-basic@file"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
proxy:
|
proxy:
|
||||||
external: true
|
name: proxy
|
||||||
|
driver: bridge
|
||||||
@@ -4,7 +4,25 @@ Este directorio contiene configuración que Traefik recarga automáticamente sin
|
|||||||
|
|
||||||
## Archivos
|
## Archivos
|
||||||
|
|
||||||
- **middlewares.yml**: Middlewares reutilizables (headers seguridad, rate limit, auth, etc.)
|
- **config.yml**: Configuración dinámica completa (serversTransports, middlewares, routers, servicios)
|
||||||
|
|
||||||
|
**Importante:** Con `directory:` en el proveedor file, se debe usar un único archivo consolidado con la estructura `http:` como raíz.
|
||||||
|
|
||||||
|
## ServersTransports
|
||||||
|
|
||||||
|
El archivo incluye el transport `insecure` para servicios con certificados autofirmados (como Portainer):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
http:
|
||||||
|
serversTransports:
|
||||||
|
insecure:
|
||||||
|
insecureSkipVerify: true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Uso en labels**:
|
||||||
|
```yaml
|
||||||
|
- "traefik.http.services.mi-servicio.loadbalancer.serversTransport=insecure@file"
|
||||||
|
```
|
||||||
|
|
||||||
## Autenticación Básica
|
## Autenticación Básica
|
||||||
|
|
||||||
@@ -19,7 +37,7 @@ docker run --rm httpd:alpine htpasswd -nbB admin tu_password
|
|||||||
|
|
||||||
2. Copia el hash completo (después de `admin:`)
|
2. Copia el hash completo (después de `admin:`)
|
||||||
|
|
||||||
3. Edita `middlewares.yml` línea 35:
|
3. Edita `config.yml` (sección http > middlewares > auth-basic):
|
||||||
```yaml
|
```yaml
|
||||||
auth-basic:
|
auth-basic:
|
||||||
basicAuth:
|
basicAuth:
|
||||||
@@ -33,7 +51,7 @@ auth-basic:
|
|||||||
|
|
||||||
### Aplicar middleware a un servicio
|
### Aplicar middleware a un servicio
|
||||||
|
|
||||||
En el `docker-compose.yaml` de tu servicio:
|
En el `docker-compose.yml` de tu servicio:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
@@ -52,7 +70,7 @@ services:
|
|||||||
|
|
||||||
Puedes combinar varios:
|
Puedes combinar varios:
|
||||||
```yaml
|
```yaml
|
||||||
- "traefik.http.routers.app.middlewares=security-headers@file,rate-limit@file,ip-whitelist@file"
|
- "traefik.http.routers.app.middlewares=security-headers@file,rate-limit@file,ip-allowlist@file"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Recarga automática
|
## Recarga automática
|
||||||
@@ -61,4 +79,5 @@ Traefik detecta cambios en este directorio y recarga sin reiniciar. Espera ~10 s
|
|||||||
|
|
||||||
## Ejemplos adicionales
|
## Ejemplos adicionales
|
||||||
|
|
||||||
Consulta la wiki: https://git.ictiberia.com/groales/traefik/wiki/Middlewares-Seguridad
|
- **Routers y Servicios:** Ver ejemplos comentados en `config.yml` (secciones routers y services) para configurar rutas sin labels Docker
|
||||||
|
- **Middlewares avanzados:** Consulta la wiki: https://git.ictiberia.com/groales/traefik/wiki/Middlewares-Seguridad
|
||||||
|
|||||||
116
dynamic/config.yml
Normal file
116
dynamic/config.yml
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
# ============================================
|
||||||
|
# CONFIGURACIÓN DINÁMICA DE TRAEFIK
|
||||||
|
# ============================================
|
||||||
|
# Este archivo contiene middlewares, routers y servicios
|
||||||
|
# Traefik recarga automáticamente los cambios (~10s)
|
||||||
|
|
||||||
|
http:
|
||||||
|
# ============================================
|
||||||
|
# SERVERS TRANSPORTS
|
||||||
|
# ============================================
|
||||||
|
serversTransports:
|
||||||
|
# Transport para servicios con certificados autofirmados
|
||||||
|
insecure:
|
||||||
|
insecureSkipVerify: true
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# MIDDLEWARES
|
||||||
|
# ============================================
|
||||||
|
middlewares:
|
||||||
|
# Headers de seguridad
|
||||||
|
security-headers:
|
||||||
|
headers:
|
||||||
|
stsSeconds: 63072000
|
||||||
|
forceSTSHeader: true
|
||||||
|
stsIncludeSubdomains: true
|
||||||
|
stsPreload: true
|
||||||
|
frameDeny: true
|
||||||
|
contentTypeNosniff: true
|
||||||
|
browserXssFilter: true
|
||||||
|
referrerPolicy: "strict-origin-when-cross-origin"
|
||||||
|
customResponseHeaders:
|
||||||
|
X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex"
|
||||||
|
|
||||||
|
# Rate limiting
|
||||||
|
rate-limit:
|
||||||
|
rateLimit:
|
||||||
|
average: 100
|
||||||
|
burst: 200
|
||||||
|
period: 1m
|
||||||
|
|
||||||
|
# IP Allow List (ejemplo - ajusta tus IPs)
|
||||||
|
ip-allowlist:
|
||||||
|
ipAllowList:
|
||||||
|
sourceRange:
|
||||||
|
- "127.0.0.1/32"
|
||||||
|
- "10.0.0.0/8"
|
||||||
|
- "172.16.0.0/12"
|
||||||
|
- "192.168.0.0/16"
|
||||||
|
|
||||||
|
# Autenticación básica (genera hash con: docker run --rm httpd:alpine htpasswd -nbB admin tu_password)
|
||||||
|
auth-basic:
|
||||||
|
basicAuth:
|
||||||
|
users:
|
||||||
|
- "admin:$2y$05$example_hash_CHANGE_THIS" # CAMBIA ESTE HASH
|
||||||
|
|
||||||
|
# Redirect www a root
|
||||||
|
redirect-www:
|
||||||
|
redirectRegex:
|
||||||
|
regex: "^https?://www\\.(.+)"
|
||||||
|
replacement: "https://${1}"
|
||||||
|
permanent: true
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# ROUTERS (Ejemplos comentados)
|
||||||
|
# ============================================
|
||||||
|
# routers:
|
||||||
|
# # Ejemplo: Router para aplicación web con HTTPS y middlewares
|
||||||
|
# whoami:
|
||||||
|
# rule: "Host(`whoami.tudominio.com`)"
|
||||||
|
# entryPoints:
|
||||||
|
# - websecure
|
||||||
|
# middlewares:
|
||||||
|
# - security-headers
|
||||||
|
# - rate-limit
|
||||||
|
# service: whoami-service
|
||||||
|
# tls:
|
||||||
|
# certResolver: letsencrypt
|
||||||
|
#
|
||||||
|
# # Ejemplo: Router con autenticación básica y restricción IP
|
||||||
|
# admin-panel:
|
||||||
|
# rule: "Host(`admin.tudominio.com`)"
|
||||||
|
# entryPoints:
|
||||||
|
# - websecure
|
||||||
|
# middlewares:
|
||||||
|
# - auth-basic
|
||||||
|
# - ip-allowlist
|
||||||
|
# - security-headers
|
||||||
|
# service: admin-service
|
||||||
|
# tls:
|
||||||
|
# certResolver: letsencrypt
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SERVICES (Ejemplos comentados)
|
||||||
|
# ============================================
|
||||||
|
# services:
|
||||||
|
# # Ejemplo: Servicio apuntando a contenedor local
|
||||||
|
# whoami-service:
|
||||||
|
# loadBalancer:
|
||||||
|
# servers:
|
||||||
|
# - url: "http://whoami:80"
|
||||||
|
#
|
||||||
|
# # Ejemplo: Servicio apuntando a servidor externo
|
||||||
|
# admin-service:
|
||||||
|
# loadBalancer:
|
||||||
|
# servers:
|
||||||
|
# - url: "http://192.168.1.100:8080"
|
||||||
|
#
|
||||||
|
# # Ejemplo: Servicio con health check
|
||||||
|
# api-service:
|
||||||
|
# loadBalancer:
|
||||||
|
# servers:
|
||||||
|
# - url: "http://api:3000"
|
||||||
|
# healthCheck:
|
||||||
|
# path: "/health"
|
||||||
|
# interval: "10s"
|
||||||
|
# timeout: "3s"
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
http:
|
|
||||||
middlewares:
|
|
||||||
# Headers de seguridad
|
|
||||||
security-headers:
|
|
||||||
headers:
|
|
||||||
stsSeconds: 63072000
|
|
||||||
forceSTSHeader: true
|
|
||||||
stsIncludeSubdomains: true
|
|
||||||
stsPreload: true
|
|
||||||
frameDeny: true
|
|
||||||
contentTypeNosniff: true
|
|
||||||
browserXssFilter: true
|
|
||||||
referrerPolicy: "strict-origin-when-cross-origin"
|
|
||||||
customResponseHeaders:
|
|
||||||
X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex"
|
|
||||||
|
|
||||||
# Rate limiting
|
|
||||||
rate-limit:
|
|
||||||
rateLimit:
|
|
||||||
average: 100
|
|
||||||
burst: 200
|
|
||||||
period: 1m
|
|
||||||
|
|
||||||
# IP Whitelist (ejemplo - ajusta tus IPs)
|
|
||||||
ip-whitelist:
|
|
||||||
ipWhiteList:
|
|
||||||
sourceRange:
|
|
||||||
- "127.0.0.1/32"
|
|
||||||
- "10.0.0.0/8"
|
|
||||||
- "192.168.0.0/16"
|
|
||||||
|
|
||||||
# Autenticación básica (genera hash con: docker run --rm httpd:alpine htpasswd -nbB admin tu_password)
|
|
||||||
auth-basic:
|
|
||||||
basicAuth:
|
|
||||||
users:
|
|
||||||
- "admin:$2y$05$example_hash_CHANGE_THIS" # CAMBIA ESTE HASH
|
|
||||||
|
|
||||||
# Redirect www a root
|
|
||||||
redirect-www:
|
|
||||||
redirectRegex:
|
|
||||||
regex: "^https?://www\\.(.+)"
|
|
||||||
replacement: "https://${1}"
|
|
||||||
permanent: true
|
|
||||||
@@ -2,6 +2,13 @@
|
|||||||
api:
|
api:
|
||||||
dashboard: true
|
dashboard: true
|
||||||
insecure: false
|
insecure: false
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
log:
|
||||||
|
level: INFO # DEBUG, INFO, WARN, ERROR
|
||||||
|
|
||||||
|
accessLog: {}
|
||||||
|
|
||||||
# Puertos de escucha de Traefik y redirección automatica
|
# Puertos de escucha de Traefik y redirección automatica
|
||||||
entryPoints:
|
entryPoints:
|
||||||
web:
|
web:
|
||||||
|
|||||||
Reference in New Issue
Block a user