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)
|
||||
- 🧠 Descubrimiento automático de servicios Docker
|
||||
- 🧷 Redirección HTTP→HTTPS
|
||||
- 🧿 Redirección HTTP→HTTPS
|
||||
- 🧰 Dashboard web (seguro por dominio)
|
||||
- 🧩 Middlewares: auth básica, headers de seguridad, rate limit, etc.
|
||||
- 📊 Logs de acceso y errores (stdout/stderr)
|
||||
|
||||
## Requisitos
|
||||
|
||||
@@ -31,13 +32,7 @@ Internet → Traefik (80/443) → Servicios (en red proxy)
|
||||
|
||||
## Despliegue
|
||||
|
||||
### 1) Crear red `proxy`
|
||||
|
||||
```bash
|
||||
docker network create proxy
|
||||
```
|
||||
|
||||
### 2) Clonar y configurar
|
||||
### 1) Clonar y configurar
|
||||
|
||||
```bash
|
||||
git clone https://git.ictiberia.com/groales/traefik
|
||||
@@ -49,7 +44,7 @@ touch ./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:
|
||||
|
||||
@@ -61,16 +56,15 @@ certificatesResolvers:
|
||||
email: tu-email@tudominio.com # ← EDITA AQUÍ
|
||||
```
|
||||
|
||||
**docker-compose.yaml:**
|
||||
**docker-compose.yml:**
|
||||
```yaml
|
||||
labels:
|
||||
- "traefik.http.routers.traefik.rule=Host(`traefik.tudominio.com`)" # ← EDITA AQUÍ
|
||||
```
|
||||
|
||||
### 4) Desplegar
|
||||
### 3) Desplegar
|
||||
|
||||
```bash
|
||||
docker network create proxy # Si no existe
|
||||
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`.
|
||||
|
||||
**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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
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
|
||||
auth-basic:
|
||||
basicAuth:
|
||||
@@ -137,6 +131,23 @@ certificatesResolvers:
|
||||
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
|
||||
|
||||
- Certificado no se emite:
|
||||
|
||||
@@ -24,9 +24,10 @@ services:
|
||||
- "traefik.http.routers.traefik.tls=true"
|
||||
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
|
||||
- "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"
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
name: proxy
|
||||
driver: bridge
|
||||
@@ -4,7 +4,25 @@ Este directorio contiene configuración que Traefik recarga automáticamente sin
|
||||
|
||||
## 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
|
||||
|
||||
@@ -19,7 +37,7 @@ docker run --rm httpd:alpine htpasswd -nbB admin tu_password
|
||||
|
||||
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
|
||||
auth-basic:
|
||||
basicAuth:
|
||||
@@ -33,7 +51,7 @@ auth-basic:
|
||||
|
||||
### Aplicar middleware a un servicio
|
||||
|
||||
En el `docker-compose.yaml` de tu servicio:
|
||||
En el `docker-compose.yml` de tu servicio:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
@@ -52,7 +70,7 @@ services:
|
||||
|
||||
Puedes combinar varios:
|
||||
```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
|
||||
@@ -61,4 +79,5 @@ Traefik detecta cambios en este directorio y recarga sin reiniciar. Espera ~10 s
|
||||
|
||||
## 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:
|
||||
dashboard: true
|
||||
insecure: false
|
||||
|
||||
# Logs
|
||||
log:
|
||||
level: INFO # DEBUG, INFO, WARN, ERROR
|
||||
|
||||
accessLog: {}
|
||||
|
||||
# Puertos de escucha de Traefik y redirección automatica
|
||||
entryPoints:
|
||||
web:
|
||||
|
||||
Reference in New Issue
Block a user