---
title: "Traefik como Proxy Inverso en Docker: Guía Completa de Configuración"
description: "Configura Traefik como proxy inverso en Docker con certificados TLS automáticos de Let's Encrypt. Guía paso a paso que cubre v3.7, la seguridad del dashboard y el despliegue de apps."
date: 2024-07-30
categories: ["self-hosting"]
tags: ["traefik","docker","reverse-proxy"]
---

import YouTubeEmbed from "@components/widgets/YouTubeEmbed.astro";
import Button from "@components/widgets/Button.astro";
import Notice from "@components/widgets/Notice.astro";
import ListCheck from "@components/widgets/ListCheck.astro";
import Accordion from "@components/widgets/Accordion.astro";
import Tabs from "@components/widgets/Tabs.astro";
import Tab from "@components/widgets/Tab.astro";
import { Picture } from "astro:assets";
import img1 from "@assets/images/24/07/traefik-diagram.jpeg";

Si estás ejecutando Docker en un VPS y necesitas un proxy inverso que gestione los certificados TLS automáticamente, Traefik es la mejor opción. Yo he estado usando Cloudflare Tunnels para la mayoría de mis configuraciones, pero Traefik te da control total. Sin dependencia de túneles de terceros, certificados automáticos de Let's Encrypt e integración nativa con Docker. En esta guía configuraremos Traefik como proxy inverso en Docker desde cero: creación del VPS, instalación de Docker, configuración de Traefik v3.7, seguridad del dashboard y tu primera app detrás del proxy.

<Notice type="error" title="Advertencia de Seguridad">
La versión original de esta guía usaba Traefik v3.1, que llegó al fin de su vida útil el 28 de octubre de 2024 y tiene vulnerabilidades críticas conocidas (CVE-2024-45410, CVSS 7.5 HIGH según el NVD / 9.8 según el aviso de GitHub). Esta guía se ha actualizado a Traefik v3.7. Si estás ejecutando v3.1, actualiza inmediatamente.
</Notice>

<Notice type="info">
Si necesitas un certificado wildcard de Let's Encrypt con el reto DNS de Cloudflare, consulta: <a href="/es/traefik-certificado-wildcard/">Certificado Wildcard GRATIS de Let's Encrypt para Traefik con el Proveedor Cloudflare</a>
</Notice>

## ¿Qué es Traefik?

[Traefik](https://traefik.io/traefik/) es un proxy inverso y balanceador de carga moderno diseñado para entornos en contenedores. Dirige el tráfico hacia tus microservicios y aplicaciones descubriendo y configurando rutas automáticamente según tu infraestructura.

La integración de Traefik con Docker es lo que lo diferencia. Detecta nuevos contenedores y actualiza su configuración de enrutamiento automáticamente. No tienes que tocar un archivo de configuración cada vez que añades un servicio.

Características principales:

1. Descubrimiento y configuración automática de servicios
2. Soporte para múltiples protocolos (HTTP, HTTPS, TCP, UDP)
3. Panel de monitorización integrado
4. Integración con Let's Encrypt para la gestión automática de certificados SSL/TLS
5. Soporte para varios algoritmos de balanceo de carga
6. Middleware para añadir funcionalidades extra como autenticación o limitación de tasa

<Picture formats={["webp"]} fallbackFormat="webp" src={img1} alt="Diagrama de arquitectura de Traefik mostrando el flujo de EntryPoints, Routers y Middlewares" />

## La arquitectura de Traefik

La arquitectura de Traefik se basa en tres componentes principales: EntryPoints, Routers y Middlewares.

### EntryPoints

Los EntryPoints son los puntos de entrada de red a Traefik. Definen los puertos y protocolos en los que Traefik escucha el tráfico entrante.

Qué hacen los EntryPoints:

- Definen los puertos de escucha para tráfico HTTP, HTTPS o UDP
- Se pueden configurar para los protocolos TCP y UDP
- Soportan múltiples EntryPoints (p. ej., uno para HTTP y otro para HTTPS)
- Se pueden asociar a direcciones IP específicas

### Routers

Los Routers se encargan de conectar las peticiones entrantes con los servicios que pueden gestionarlas. Analizan las peticiones mediante reglas y las enrutan en consecuencia.

Qué hacen los Routers:

- Usan reglas para determinar qué peticiones deben gestionar
- Se pueden asociar a EntryPoints específicos
- Soportan ajustes de prioridad para gestionar reglas superpuestas
- Se pueden configurar para tráfico HTTP, TCP o UDP

### Middlewares

Los Middlewares modifican las peticiones antes de que se envíen a tu servicio (o las respuestas antes de que se devuelvan a los clientes). Se pueden adjuntar a los routers y ofrecen una forma de aplicar modificaciones a peticiones o respuestas.

Qué hacen los Middlewares:

- Pueden modificar peticiones y respuestas
- Son encadenables (se pueden aplicar varios middlewares en secuencia)
- Ofrecen funcionalidades como autenticación, limitación de tasa, manipulación de cabeceras, etc.
- Se pueden reutilizar en varios routers

Traefik tiene tres componentes básicos: EntryPoints (dónde escucha), Routers (cómo gestiona las peticiones) y Middlewares (modificaciones de peticiones/respuestas). Juntos forman un sistema de enrutamiento flexible para entornos en contenedores.

## Cómo configurar Traefik como proxy inverso para tus apps Docker

<YouTubeEmbed
  url="https://www.youtube.com/embed/vce3EEkvuZ4"
  label="Cómo usar Traefik como proxy inverso en Docker"
/>

<Notice type="info">
¿Quieres monitorizar los recursos del servidor como CPU, memoria y espacio en disco? Consulta: <a href="/es/monitorizar-servidor/">Cómo Monitorizar los Recursos del Servidor y de Docker</a>
</Notice>

Después de ver qué es Traefik, vamos a repasar todos los pasos necesarios: crear y configurar un VPS, instalar Docker, configurar el DNS, poner en marcha Traefik con el dashboard y desplegar algunas aplicaciones.

### 1. Crear un servidor VPS

Necesitas un VPS con los puertos 22, 80 y 443 abiertos. Yo uso [Hetzner](https://go.bitdoze.com/hetzner) o [Hostinger](https://go.bitdoze.com/hostinger-vps) para la mayoría de las configuraciones. Usa el firewall en la nube de tu proveedor si está disponible (p. ej., Hetzner Cloud Firewall). Es más fiable que UFW por sí solo por cómo interactúa Docker con iptables (más sobre esto en el Paso 4).

_Los precios de los VPS subieron en general en 2026 — si estás replanteándote alquilar un servidor, mira [qué cambió y cuándo gana un mini PC](/es/subidas-precios-vps/)._

<Notice type="info">
Para reforzar tu VPS más allá de las reglas básicas de firewall, considera <a href="/es/crowdsec-servidor-seguro/">asegurar tu VPS con CrowdSec</a>. Funciona bien junto a Traefik.
</Notice>

### 2. Añadir SWAP

La mayoría de los VPS no tienen swap por defecto. Añádelo con:

```sh
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
```

### 3. Instalar Docker

El siguiente paso es instalar Docker y Docker Compose v2. Los comandos de abajo detectan automáticamente el nombre clave de tu distribución (funciona tanto para Ubuntu como para Debian):

```sh
# Add Docker's official GPG key
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository (auto-detects Ubuntu/Debian codename)
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```

Verifica que la instalación funcionó:

```sh
docker --version
docker compose version
```

Deberías ver la salida de versión en ambos. Si `docker compose version` da error, el plugin de Compose no se instaló correctamente.

### 4. Configurar el firewall y actualizar el SO

Actualiza primero el SO:

```sh
sudo apt update && sudo apt upgrade -y
```

Si estás usando UFW, abre los puertos necesarios:

```sh
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
sudo ufw status
```

<Notice type="warning" title="Docker se salta UFW">
Docker manipula iptables directamente, lo que puede saltarse las reglas de UFW. Los contenedores con puertos publicados pueden ser accesibles aunque UFW bloquee ese puerto. Considera usar el firewall de tu proveedor de nube (p. ej., Hetzner Cloud Firewall) o la cadena DOCKER-USER de iptables. Consulta: <a href="/es/docker-evita-firewall/">Docker se salta las reglas del firewall UFW</a>
</Notice>

Reinicia después de las actualizaciones:

```sh
reboot
```

### 5. Crear la red Docker

Crea la red externa que Traefik y tus apps compartirán:

```sh
docker network create traefik-net
```

Verifica:

```sh
docker network ls | grep traefik-net
```

Deberías ver `traefik-net` en la lista con el driver bridge.

### 6. Crear el archivo Docker Compose del proxy inverso Traefik

Crea el directorio y navega hasta él:

```sh
mkdir -p /opt/stacks/traefik && cd /opt/stacks/traefik
```

<Notice type="info">
Esta guía usa el reto TLS-ALPN-01, que requiere que el puerto 443 sea accesible desde internet. Si necesitas certificados wildcard o no puedes abrir el puerto 443, usa el reto DNS en su lugar. Consulta: <a href="/es/traefik-certificado-wildcard/">Certificado Wildcard de Let's Encrypt para Traefik</a>
</Notice>

La configuración recomendada usa un proxy de socket Docker para limitar el acceso de Traefik a la API de Docker. Si prefieres la versión más simple con el socket directo, usa la segunda pestaña de abajo.

<Tabs>
<Tab name="Recomendado: Socket Proxy">

Crea un archivo `compose.yml`:

```yaml
services:
  socket-proxy:
    image: tecnativa/docker-socket-proxy:latest
    container_name: socket-proxy
    restart: unless-stopped
    networks:
      - traefik-net
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      CONTAINERS: 1
      SERVICES: 1
      TASKS: 1
      NETWORKS: 1
    security_opt:
      - no-new-privileges:true

  traefik:
    image: traefik:v3.7
    container_name: traefik
    restart: unless-stopped
    command:
      #- --log.level=DEBUG
      - --api.dashboard=true
      - --ping=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.endpoint=tcp://socket-proxy:2375
      - --providers.docker.network=traefik-net
      - --entrypoints.http.address=:80
      - --entrypoints.http.http.redirections.entrypoint.to=https
      - --entrypoints.http.http.redirections.entrypoint.scheme=https
      - --entrypoints.https.address=:443
      - --certificatesresolvers.letsencrypt.acme.tlschallenge=true
      #- --certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.letsencrypt.acme.email=you@example.com
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
    security_opt:
      - no-new-privileges:true
    networks:
      - traefik-net
    ports:
      - 80:80
      - 443:443
    healthcheck:
      test: ["CMD", "traefik", "healthcheck", "--ping"]
      interval: 30s
      timeout: 5s
      retries: 3
    env_file: .env
    volumes:
      - ./letsencrypt:/letsencrypt
    labels:
      - traefik.enable=true
      - traefik.http.routers.traefik-secure.rule=Host(`traefik.yourdomain.com`)
      - traefik.http.routers.traefik-secure.entrypoints=https
      - traefik.http.routers.traefik-secure.service=api@internal
      - traefik.http.routers.traefik-secure.tls.certresolver=letsencrypt
      - traefik.http.routers.traefik-secure.middlewares=traefik-auth
      - traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}
      - traefik.http.routers.traefik-secure.tls=true

networks:
  traefik-net:
    external: true
```

</Tab>
<Tab name="Simple: Socket Directo">

Si prefieres la configuración más simple sin proxy de socket, crea un archivo `compose.yml`:

```yaml
services:
  traefik:
    image: traefik:v3.7
    container_name: traefik
    restart: unless-stopped
    command:
      #- --log.level=DEBUG
      - --api.dashboard=true
      - --ping=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=traefik-net
      - --entrypoints.http.address=:80
      - --entrypoints.http.http.redirections.entrypoint.to=https
      - --entrypoints.http.http.redirections.entrypoint.scheme=https
      - --entrypoints.https.address=:443
      - --certificatesresolvers.letsencrypt.acme.tlschallenge=true
      #- --certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.letsencrypt.acme.email=you@example.com
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
    security_opt:
      - no-new-privileges:true
    networks:
      - traefik-net
    ports:
      - 80:80
      - 443:443
    healthcheck:
      test: ["CMD", "traefik", "healthcheck", "--ping"]
      interval: 30s
      timeout: 5s
      retries: 3
    env_file: .env
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
    labels:
      - traefik.enable=true
      - traefik.http.routers.traefik-secure.rule=Host(`traefik.yourdomain.com`)
      - traefik.http.routers.traefik-secure.entrypoints=https
      - traefik.http.routers.traefik-secure.service=api@internal
      - traefik.http.routers.traefik-secure.tls.certresolver=letsencrypt
      - traefik.http.routers.traefik-secure.middlewares=traefik-auth
      - traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}
      - traefik.http.routers.traefik-secure.tls=true

networks:
  traefik-net:
    external: true
```

Esto monta el socket de Docker de solo lectura directamente en el contenedor de Traefik. Funciona bien para configuraciones de un solo usuario, pero la versión con proxy de socket de arriba limita el radio de impacto si Traefik se ve comprometido.

</Tab>
</Tabs>

**Opciones de comandos explicadas:**

1. `--api.dashboard=true`: Activa el dashboard web de Traefik.
2. `--providers.docker=true`: Activa Docker como proveedor para el descubrimiento automático de servicios.
3. `--providers.docker.exposedbydefault=false`: Evita que Traefik exponga automáticamente todos los contenedores. Debes activar cada uno explícitamente.
4. `--providers.docker.endpoint=tcp://socket-proxy:2375`: Conecta con la API de Docker a través del proxy de socket en lugar del socket sin procesar. (Omitido en la versión de socket directo.)
5. `--providers.docker.network=traefik-net`: Indica a Traefik qué red Docker usar para enrutar el tráfico a los contenedores.
6. `--entrypoints.http.address=:80`: Entrypoint HTTP en el puerto 80.
7. `--entrypoints.http.http.redirections.entrypoint.to=https`: Redirige todo el tráfico HTTP a HTTPS.
8. `--entrypoints.http.http.redirections.entrypoint.scheme=https`: Garantiza que la redirección use el esquema HTTPS. Para profundizar en las redirecciones de HTTP a HTTPS, consulta [Redirección HTTP a HTTPS en Traefik](/es/traefik-redirigir-http-https/).
9. `--entrypoints.https.address=:443`: Entrypoint HTTPS en el puerto 443.
10. `--certificatesresolvers.letsencrypt.acme.tlschallenge=true`: Activa el reto TLS-ALPN-01 para la obtención de certificados de Let's Encrypt.
11. `--certificatesresolvers.letsencrypt.acme.email=you@example.com`: Tu email para el registro en Let's Encrypt y las notificaciones de caducidad.
12. `--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json`: Dónde almacenar los certificados. Este archivo necesita permisos específicos (cubierto en el Paso 9).
13. `--ping=true`: Activa el endpoint de healthcheck que usa el healthcheck de Docker.

**Etiquetas del dashboard explicadas:**

1. `traefik.enable=true`: Activa Traefik para este contenedor.
2. `traefik.http.routers.traefik-secure.rule=Host(`traefik.yourdomain.com`)`: Enruta las peticiones de este hostname al dashboard.
3. `traefik.http.routers.traefik-secure.entrypoints=https`: Usa el entrypoint HTTPS.
4. `traefik.http.routers.traefik-secure.service=api@internal`: Enruta a la API interna del dashboard de Traefik.
5. `traefik.http.routers.traefik-secure.tls.certresolver=letsencrypt`: Usa Let's Encrypt para los certificados TLS.
6. `traefik.http.routers.traefik-secure.middlewares=traefik-auth`: Aplica el middleware de autenticación.
7. `traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}`: Configura Basic Auth. Las credenciales vienen del archivo `.env`. Más sobre [Autenticación Básica en Traefik](/es/traefik-autenticacion-basica/).
8. `traefik.http.routers.traefik-secure.tls=true`: Activa TLS para este router.

Reemplaza `traefik.yourdomain.com` por tu dominio real.

### 7. Crear el archivo `.env` con las credenciales del dashboard de Traefik

Instala htpasswd:

```sh
sudo apt install apache2-utils -y
```

Genera un hash bcrypt y escríbelo en `.env` con el nombre de la variable:

```sh
echo "TRAEFIK_DASHBOARD_CREDENTIALS=$(htpasswd -nbB admin 'YourPassword123' | sed 's/\$/$$/g')" | sudo tee -a .env
```

La opción `-B` usa bcrypt. El `sed 's/\$/$$/g'` duplica cada `$`: Docker Compose interpola `$VAR` dentro de los archivos `.env`, así que un hash con un solo `$` quedaría destrozado (las letras después de `$` se tragan como una variable indefinida) y la autenticación fallaría silenciosamente con un 401. Con `$$` el contenedor recibe el hash correcto con un solo `$`.

Verifica que el `.env` contiene el hash duplicado:

```sh
cat .env
# TRAEFIK_DASHBOARD_CREDENTIALS=admin:$$2y$$05$$...hash...
```

Reemplázalo por la salida real del comando htpasswd.

<Notice type="info">
Para producción, considera usar <a href="/es/secretos-docker-compose/">secretos de Docker Compose</a> en lugar de archivos .env para las credenciales sensibles.
</Notice>

### 8. Apuntar el dominio a la IP de tu servidor

Crea un registro A para tu dominio apuntando a la IP del servidor. Para los subdominios, puedes:

- Crear registros A individuales para cada subdominio (p. ej., `traefik.yourdomain.com`, `flowise.yourdomain.com`)
- Crear un registro A wildcard (`*.yourdomain.com`) apuntando al servidor

Los registros individuales son más explícitos y fáciles de depurar. Si no usas un wildcard, asegúrate de que el registro `traefik.yourdomain.com` está creado antes de continuar.

Verifica la propagación del DNS:

```sh
dig traefik.yourdomain.com +short
```

Debería devolver la IP de tu servidor. Si no devuelve nada, espera unos minutos más. El reto TLS requiere que el DNS resuelva correctamente.

### 9. Iniciar Traefik y verificar los certificados TLS de Let's Encrypt

Antes de empezar, crea el archivo `acme.json` con los permisos correctos:

```sh
mkdir -p ./letsencrypt
touch ./letsencrypt/acme.json
chmod 600 ./letsencrypt/acme.json
```

<Notice type="warning" title="Permisos de acme.json">
Si acme.json no tiene permisos 600, Traefik se negará a arrancar o no podrá almacenar los certificados. Este es el problema n.º 1 entre los principiantes. Verifícalo con `ls -la ./letsencrypt/acme.json`: la salida debería mostrar `-rw-------`.
</Notice>

Inicia Traefik:

```sh
docker compose up -d
```

**Verifica que funciona:**

1. Comprueba el estado del contenedor: `docker ps`: el contenedor de Traefik debería mostrar "healthy" (el healthcheck tarda ~30 segundos).

2. Revisa los logs para la emisión del certificado:
```sh
docker logs traefik
```
Busca una línea sobre el certificado obtenido. Sin errores sobre `acme.json` ni permisos.

3. Prueba la redirección HTTP→HTTPS:
```sh
curl -I http://traefik.yourdomain.com
```
Espera un `301 Moved Permanently` redirigiendo a HTTPS.

4. Prueba el certificado TLS:
```sh
curl -vI https://traefik.yourdomain.com 2>&1 | grep -i "issuer"
```
Debería mostrar `issuer: CN=R3, O=Let's Encrypt, C=US` (o similar). Si ves un certificado autofirmado, el DNS aún no se ha propagado o el puerto 443 no es accesible.

5. Accede al dashboard: abre `https://traefik.yourdomain.com` en tu navegador. Deberías obtener un aviso de Basic Auth y luego ver el dashboard de Traefik.

<Notice type="info">
Durante las pruebas, descomenta la línea del servidor CA de staging en tu archivo compose para no agotar los límites de tasa de Let's Encrypt. Vuelve al servidor de producción cuando todo funcione. Para más comandos esenciales de depuración de Docker, consulta: <a href="/docker-commands/">comandos esenciales de Docker</a>
</Notice>

**Nota sobre los certificados de Let's Encrypt:** actualmente los certificados son válidos durante 90 días. Traefik los renueva automáticamente (empezando 30 días antes de su caducidad). Let's Encrypt está [transicionando a certificados de 45 días para febrero de 2028](https://letsencrypt.org/2025/12/02/from-90-to-45). La renovación automática de Traefik lo gestionará de forma transparente, pero `acme.json` debe seguir teniendo permisos de escritura y el contenedor debe permanecer en ejecución para que las renovaciones funcionen.

### 10. Desplegar tu primera app detrás del proxy inverso Traefik

Ahora que Traefik está en marcha, podemos añadir aplicaciones. Aquí tienes un ejemplo de FlowiseAI con una base de datos PostgreSQL. Anteriormente usé [FlowiseAI con Docker Compose](/es/instalar-flowise-docker/) detrás de Cloudflare Tunnels. Ahora usamos etiquetas de Traefik en su lugar:

```yaml
services:
  flowise-db:
    image: postgres:16-alpine
    hostname: flowise-db
    networks:
      - traefik-net
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - ./flowise-db-data:/var/lib/postgresql/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 5s
      timeout: 5s
      retries: 5

  flowise:
    image: flowiseai/flowise:latest
    container_name: flowiseai
    hostname: flowise
    healthcheck:
      test: wget --no-verbose --tries=1 --spider http://localhost:${PORT}
    volumes:
      - ./flowiseai:/root/.flowise
    environment:
      DEBUG: false
      PORT: ${PORT}
      FLOWISE_USERNAME: ${FLOWISE_USERNAME}
      FLOWISE_PASSWORD: ${FLOWISE_PASSWORD}
      APIKEY_PATH: /root/.flowise
      SECRETKEY_PATH: /root/.flowise
      LOG_LEVEL: info
      LOG_PATH: /root/.flowise/logs
      DATABASE_TYPE: postgres
      DATABASE_PORT: 5432
      DATABASE_HOST: flowise-db
      DATABASE_NAME: ${POSTGRES_DB}
      DATABASE_USER: ${POSTGRES_USER}
      DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
    restart: on-failure:5
    networks:
      - traefik-net
    depends_on:
      flowise-db:
        condition: service_healthy
    entrypoint: /bin/sh -c "sleep 3; flowise start"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.flowise.rule=Host(`flowise.domain.com`)"
      - "traefik.http.routers.flowise.entrypoints=https"
      - "traefik.http.routers.flowise.tls.certresolver=letsencrypt"
      - "traefik.http.services.flowise.loadbalancer.server.port=${PORT}"

networks:
  traefik-net:
    external: true
```

<Notice type="warning">
La etiqueta `flowiseai/flowise:latest` siempre descarga la imagen más reciente. Para mayor estabilidad, consulta las <a href="https://github.com/FlowiseAI/Flowise/releases">versiones de Flowise</a> y fija una versión concreta en su lugar.
</Notice>

Algunas cosas a tener en cuenta sobre esta configuración:

Tanto `flowise-db` como `flowise` están en `traefik-net`. La BD y Flowise también pueden compartir una red interna separada para el tráfico de la base de datos. Ambos solo necesitan `traefik-net` para que Traefik enrute el tráfico externo.

Las etiquetas específicas de Traefik le indican que enrute el tráfico de `flowise.domain.com` a este contenedor en el entrypoint HTTPS, usando Let's Encrypt para TLS.

No publicamos ningún puerto del host. Traefik enruta el tráfico internamente a través de la red Docker. La etiqueta `loadbalancer.server.port` le indica a Traefik en qué puerto escucha la app dentro del contenedor.

Reemplaza `flowise.domain.com` por tu dominio real.

Crea el archivo `.env` para Flowise:

```sh
PORT=3000
POSTGRES_USER='user'
POSTGRES_PASSWORD='pass'
POSTGRES_DB='flowise'
FLOWISE_USERNAME=bitdoze
FLOWISE_PASSWORD=bitdoze
```

Si el subdominio no usa un wildcard, asegúrate primero de que el registro A de `flowise.domain.com` apunta a la IP de tu servidor. Luego:

```sh
source .env
docker compose up -d
```

Verifica: `docker logs flowiseai` y abre `https://flowise.domain.com` en tu navegador.

Para más ideas de contenedores Docker que desplegar detrás de Traefik, echa un vistazo a [Contenedores Docker para tu servidor casero](/es/contenedores-docker-servidor-casa/).

### 11. Instalar Dockge para gestionar tus archivos Docker Compose

Dockge es un gestor ligero de Docker Compose con interfaz web. Escribí una guía de instalación detallada de [Dockge, gestor de Docker Compose](/es/instalar-dockge/). Así es como ejecutarlo detrás de Traefik.

Crea un directorio:

```sh
mkdir /opt/dockge
cd /opt/dockge
```

Crea un archivo `compose.yml`:

```yaml
services:
  dockge:
    image: louislam/dockge:1
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /opt/stacks:/opt/stacks
    environment:
      - DOCKGE_STACKS_DIR=/opt/stacks
    networks:
      - traefik-net
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dockge.rule=Host(`dockge.domain.com`)"
      - "traefik.http.routers.dockge.entrypoints=https"
      - "traefik.http.routers.dockge.tls.certresolver=letsencrypt"
      - "traefik.http.services.dockge.loadbalancer.server.port=5001"

networks:
  traefik-net:
    external: true
```

La etiqueta `louislam/dockge:1` sigue la versión principal, que es la práctica correcta para la estabilidad. Dockge 1.5.0+ desactiva por defecto la terminal/consola integrada por seguridad. Si necesitas acceso a la terminal, añade `DOCKGE_ENABLE_CONSOLE=true` a la sección de entorno.

Si no usas un wildcard para los subdominios, asegúrate de que el registro A de `dockge.domain.com` apunta a la IP de tu servidor. Luego:

```sh
docker compose up -d
```

Verifica: `docker logs dockge` y abre `https://dockge.domain.com` en tu navegador.

Para una comparativa más amplia de herramientas de gestión autoalojadas, consulta [paneles de gestión de servidores autoalojados](/best-self-hosted-panels/).

## Solución de problemas comunes

<Accordion label="Traefik no arranca / errores de acme.json" group="troubleshooting">
La causa más común son permisos incorrectos en `acme.json`. Traefik requiere permisos `600` en este archivo.

```sh
ls -la ./letsencrypt/acme.json
# Should show: -rw------- 1 root root ...
```

Si los permisos son incorrectos:

```sh
chmod 600 ./letsencrypt/acme.json
docker compose restart traefik
```

Revisa también `docker logs traefik` para otros errores (conflictos de puertos, problemas de red).
</Accordion>

<Accordion label="Sin certificado / aviso de certificado autofirmado" group="troubleshooting">
Esto significa que el reto TLS falló. Causas comunes:

1. **DNS no propagado:** verifica con `dig traefik.yourdomain.com +short`: debe devolver la IP de tu servidor.
2. **Puerto 443 no accesible:** el reto TLS-ALPN-01 requiere conexiones entrantes en el puerto 443. Revisa tu firewall y los grupos de seguridad de tu proveedor de nube.
3. **Proxy de Cloudflare activado:** si usas Cloudflare con la nube naranja (proxy), el reto TLS puede fallar. Prueba con la nube gris (solo DNS) durante la configuración.

Usa el servidor de staging mientras depuras para evitar los límites de tasa. Descomenta la línea `caserver` en tu archivo compose.
</Accordion>

<Accordion label="Ya se emitieron demasiados certificados" group="troubleshooting">
Límites de tasa de Let's Encrypt: 5 certificados duplicados por dominio por semana. Si has estado depurando, puede que hayas llegado a ese límite.

Solución: cambia al servidor de staging mientras pruebas:

```yaml
- --certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
```

Los certificados de staging muestran avisos en el navegador, pero te permiten verificar que la configuración funciona. Vuelve a producción cuando todo esté confirmado.
</Accordion>

<Accordion label="Traefik no detecta los contenedores Docker" group="troubleshooting">
Comprueba dos cosas:

1. El contenedor está en la red `traefik-net`:
```sh
docker network inspect traefik-net
```
Tu contenedor debería aparecer en la salida.

2. El contenedor tiene la etiqueta `traefik.enable=true`:
```sh
docker inspect your-container | grep -i traefik.enable
```
</Accordion>

<Accordion label="El dashboard muestra 401 / la autenticación no funciona" group="troubleshooting">
La causa más común es un hash con un solo `$` en `.env` que Docker Compose destroza al interpolarlo. Regenéralo con el escape `$$` del Paso 7:

```sh
echo "TRAEFIK_DASHBOARD_CREDENTIALS=$(htpasswd -nbB admin 'YourPassword123' | sed 's/\$/$$/g')" | sudo tee .env
```

Asegúrate de que el `.env` está en el mismo directorio que el archivo compose y de que la directiva `env_file: .env` está presente. Verifica también que la etiqueta del middleware referencia `traefik-auth` correctamente.
</Accordion>

<Accordion label="Bucle de redirección HTTP" group="troubleshooting">
Si estás detrás de Cloudflare, la causa más común es el modo SSL/TLS configurado en "Flexible" en lugar de "Full" (o "Full (strict)"). El modo "Flexible" de Cloudflare conecta con tu origen por HTTP, Traefik redirige a HTTPS, Cloudflare vuelve a conectar por HTTP, creando un bucle infinito.

Solución: en el panel de Cloudflare, ve a SSL/TLS y configúralo en **Full** (o **Full (strict)** si tienes un certificado válido).
</Accordion>

<Notice type="info">
Usa el servidor de staging de Let's Encrypt mientras pruebas para no agotar los límites de tasa. Descomenta la línea caserver en tu archivo compose y vuelve a producción cuando todo funcione.
</Notice>

## Notas de hardening y producción

Una vez que la configuración básica funciona, esto es lo que hay que hacer para producción:

<ListCheck>
<ul>
<li>**Proxy de socket** (ya incluido en la configuración recomendada). Limita el acceso de Traefik a la API de Docker a información de solo lectura de contenedores/redes/servicios</li>
<li>**Middleware de cabeceras de seguridad**: añade HSTS, protección contra sniffing de content-type, filtro XSS</li>
<li>**Middleware de limitación de tasa**: protege el dashboard y las apps contra abusos</li>
<li>**Copia de seguridad de `acme.json`**: perderlo significa reemitir todos los certificados (y toparte con los límites de tasa). Haz copias periódicas o usa un volumen Docker en almacenamiento persistente</li>
<li>**Usa secretos de Docker** para las credenciales en lugar de archivos `.env` en producción</li>
<li>**Mantén Traefik actualizado**. `traefik:v3.7` sigue las versiones de parche v3.7.x. Comprueba periódicamente si hay nuevas versiones menores</li>
</ul>
</ListCheck>

**Middleware de cabeceras de seguridad**: añade estas etiquetas a los contenedores de tus apps:

```yaml
- traefik.http.middlewares.sec-headers.headers.sslredirect=true
- traefik.http.middlewares.sec-headers.headers.stsseconds=63072000
- traefik.http.middlewares.sec-headers.headers.stsincludeSubdomains=true
- traefik.http.middlewares.sec-headers.headers.stspreload=true
- traefik.http.middlewares.sec-headers.headers.contentTypeNosniff=true
- traefik.http.middlewares.sec-headers.headers.browserXssFilter=true
```

**Middleware de limitación de tasa**: añádelo a tu router:

```yaml
- traefik.http.middlewares.rate-limit.ratelimit.average=100
- traefik.http.middlewares.rate-limit.ratelimit.burst=50
- traefik.http.routers.traefik-secure.middlewares=traefik-auth,rate-limit
```

<Notice type="info">
Explora los plugins de la comunidad en <a href="https://plugins.traefik.io/">plugins.traefik.io</a> para integración con CrowdSec, filtrado geográfico y más. Para un hardening más amplio del VPS, consulta: <a href="/es/crowdsec-servidor-seguro/">asegura tu VPS con CrowdSec</a>
</Notice>

## Conclusiones

Configurar Traefik como proxy inverso Docker para tus apps autoalojadas es sencillo una vez que sigues los pasos. Hemos cubierto la creación del VPS, la instalación de Docker, Traefik v3.7 con certificados TLS automáticos de Let's Encrypt, la seguridad del dashboard con autenticación bcrypt, un proxy de socket para reducir el radio de impacto y el despliegue de tu primera app con etiquetas de Traefik.

Las mejoras clave sobre una configuración básica: el proxy de socket limita la exposición de la API de Docker, `acme.json` con los permisos adecuados previene el fallo más común entre principiantes, los healthchecks detectan problemas pronto y la autenticación bcrypt con el escape `$$` gestionado en el Paso 7 mantiene el dashboard protegido.

Una vez que Traefik está en marcha, añadir nuevos servicios es solo cuestión de añadir etiquetas a un contenedor Docker y ponerlo en `traefik-net`. Dockge facilita aún más la gestión de esos archivos compose desde una interfaz web.

<Button text="Los Mejores Contenedores Docker para tu Servidor Casero" link="/es/contenedores-docker-servidor-casa/" variant="solid" color="blue" size="md" icon="arrow-right" />