Configurar Traefik 2 + OAuth con Authelia

Isengard

EDIT: Como han comentado, es verdad que no puse la fuente porque lo dejé un poco a medias. Me basé casi al completo en esto:

https://www.smarthomebeginner.com/traefik-reverse-proxy-tutorial-for-docker/#Traefik_v16_and_Wildcard_Certificates

Bueno lo prometido es deuda y algunos me pedisteis si os podía poner en un hilo como publicar contenedores Docker con SSL a través de Traefik pues aquí va. Lo primero lo que vamos a conseguir:

  • Traefik2 publicado en nuestro dominio actuando de proxy inverso sirviendo todo el contenido/servicios a través de SSL gracias a Let's Encrypt. Para que os hagáis una idea podréis publicar por ejemplo un cliente bittorrent vía bt.dominio.com
  • El certificado Let's Encrypt se renovará automáticamente.
  • Además como en este mundo hay mucho hacker que le gusta tocar las pelotas, vamos a meterle Authelia para lograr OAuth y restringir más el acceso.
  • Os dejaré un ejemplo de Heimdall (página dashboard) y de qBittorrent publicado para veáis que queda bastante apañado el asunto.

Requisitos

  • Servidor o PC que vayamos a tener prestando el servicio. Yo uso un servidor casero con Ubuntu que me monté por piezas con placas chinas y un XEON pero vaya que esto son Dockers, lo podéis montar en una Raspberry sin problemas.
  • Docker y docker-compose instalado
  • Port Forwarding en vuestro router del puerto 443 y 80 (opcional) hacia la máquina dónde pongáis Traefik
  • Dominio propio. Vale 10€ o menos no me seáis ratas... se puede montar con servicios DynDNS (DuckDNS, etc) pero entonces hay que pasar a usar formato "dominio.com/servicio" y es bastante más coñazo.
  • Gestor de DNS para poder publicar los nombres de los servicios. Yo voy a usar Cloudflare que es gratuito y además ofrece una CDN bastante apañado y la posiblidad incluso de no usarla si quieres. Si usáis Cloudflare deberéis configurarlo con la SSL/TLS "Completo"
Imagen Cloudlflare TLS Completo

Que no vas a aprender

  • Comprar un dominio y configurarlo en sitios como CloudFlare.
  • Hacer Port-Forwarding del puerto 443 a la máquina servidor dónde publiques Traefik.
  • Instalar Docker

Paso 1 - Preparar entorno de trabajo

Si no habéis usado docker antes deberíais saber que al final estos contenedores son muy de quita y pon y como no tengas cuidado acabas con el sistema operativo hecho unos zorros con carpetas de dockers desperdigadas. Así que lo mejor es que empecéis por crearos una carpeta "docker" y le demos los permisos adecuados. Es decir:

/home/USER/docker
mkdir ~/docker
sudo setfacl -Rdm g:docker:rwx ~/docker
sudo chmod -R 775 ~/docker

Vale, de esta manera tendremos todo reunido dentro de la carpeta docker. Esta carpeta contendrá en su interior una carpeta por cada uno de los servicios. Es decir, en nuestro ejemplo acabaremos teniendo 5 carpetas en docker:

  • traefik2
  • qbittorrent
  • authelia
  • heimdall
  • shared - Esta no es ningún servicio sino que simplemente es una carpeta "común" que usaran todos los dockers.

Además, como vamos a usar docker-compose necesitamos crear un fichero "docker-compose.yml" donde pondremos toda la configuración y luego un fichero ".env" (sí con "." por delante) para guardar variables comunes que usaremos en "docker-compose.yml".

touch docker-compose.yml
touch .env

En .env meteremos lo siguiente que son las variables que usarán todos los servicios dockers que montemos por lo general

PUID=1000 # User ID del usuario que ejecutará los servicios dockers
PGID=1000 # Group ID del usuario 
TZ=Europe/Madrid # Timezone que usarán los dockers
USERDIR=/path/a/la/carpeta/docker # Path del usuario que ejecutará los servicios dockers

Para hacer uso de una variable de ".env" en "docker-compose.yml" se hace con $NOMBREVARIABLE

Paso 2 - Configurando Traefik2

2.1 Entendiendo Traefik
Si habéis usado Traefik antes pues me imagino que sabréis que la versión 2 introdujo un montón de cambios respecto a la 1. En concreto cambian tanto que al final trabajan con 3 releases diferentes:

  • chevrotin = 2.2.X - La actual y la que vamos a usar
  • cantal = 2.1.X - La primera versión de la 2 que ya la están descontinuando
  • maroilles = 1.7.X - Ya sólo la actualizan para temas de seguridad

Traefik2 trabaja principalmente con 3 conceptos: Routers, Middlewares y Services

  • Routers: Son el frontend por así decirlo, son los que escuchan las peticiones que llegan a traefik, los puntos de entrada y donde se definen las reglas que se aplican a las peticiones
  • Services: Son el backend, identifican hacia donde van las peticiones. Aquí es donde se define por ejemplo que qbittorrent está escuchando en el puerto 8080 y cosas así.
  • Middlewares: Es la característica reina de traefik2. Son los que hacen la verdadera función de proxy inverso modificando las peticiones añadiéndoles cosas como paths, cabeceras específicas, etc.

2.2 Creando autenticación básica y el entorno de traefik2
Aunque acabaremos con Authelia, primero habrá que empezar con un acceso básica usuario:contraseña. Para ello crearemos un fichero ".htpasswd" usando HTPASSWD Generator y lo guardaremos en "$USERDIR/docker/shared/.htpasswd" El formato es sencillo:

nombreusuario:contraseña

Aquí entra Cloudflare. Como vamos a tener Let's Encrypt + Cloudflare generando los certificados es necesario crear 3 variables en ".env"

DOMAINNAME=example.com
[email protected]
CLOUDFLARE_API_KEY=XXXXXXXXXXXX

La API Key de Cloudflare se consigue en la sección "Tokens API" de nuestro perfil en Cloudflare.

Imagen Token API Cloudlflare

Necesitamos esta información porque vamos a usar el método "DNS-Challenge" para la generación del certificado wildcard que vamos a generar en LetsEncrypt.

Por último, creamos las carpetas del servicio Traefik y el fichero acme.json que guardará la información del certificado SSL que crearemos con los permisos adecuados. También de paso, como nos gusta guardar todo lo que pasa pues creamos el fichero de log de traefik2.

mkdir traefik2
mkdir traefik2/acme
touch traefik2/acme/acme.json
chmod 600 traefik2/acme/acme.json
touch traefik2/traefik.log
mkdir traefik2/rules

2.3 Configuración de la Red docker

Todo los servicios que creemos irán alojados en una red propia dentro de la máquina donde ejecutamos Docker. Algo así como una LAN dentro de la LAN de nuestra casa. Esta red la creamos así

docker network create --gateway 10.10.10.1 --subnet 10.10.10.0/24 t2_proxy

Una vez creada la red es necesario incluirla en la configuración de "docker-compose.yml"

version: "3.7"

########################### NETWORKS
networks:
  t2_proxy:
    external:
      name: t2_proxy
  default:
    driver: bridge
    
########################### SERVICES services:

2.4 Creación del servicio traefik2 en docker-compose.yml

Podría daros todo el texto y ya pero lo voy a documentar un poco. Tenemos que meter todo esto a partir de la siguiente línea tras "services:" (cuidado con los espacios y tabulaciones!)

# Traefik 2 - Reverse Proxy
  traefik:
    container_name: traefik
    image: traefik:chevrotin # the chevrotin tag refers to v2.2.x
    restart: unless-stopped

Primero la parte sencilla, creamos el servicio y lo configuramos con nombre "traefik" que se usará la imagen docker "chevrotin" que es la correspondiente a la versión 2.2.X. Además indicamos que salvo que paremos nosotros el docker, este debe reiniciarse siempre.

    command: # CLI argument
      - --global.checkNewVersion=true
      - --global.sendAnonymousUsage=true
      - --entryPoints.http.address=:80
      - --entryPoints.https.address=:443
        # Allow these IPs to set the X-Forwarded-* headers - Cloudflare IPs: https://www.cloudflare.com/ips/
      - --entrypoints.https.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/12,172.64.0.0/13,131.0.72.0/22
      - --entryPoints.traefik.address=:8080
      - --api=true
      #- --api.insecure=true
      #- --serversTransport.insecureSkipVerify=true
      - --log=true
      - --log.level=ERROR # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
      - --accessLog=true
      - --accessLog.filePath=/traefik.log
      - --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
      - --accessLog.filters.statusCodes=400-499
      - --providers.docker=true
      - --providers.docker.endpoint=unix:///var/run/docker.sock
      - --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINNAME`)
      - --providers.docker.exposedByDefault=false
      - --providers.docker.network=t2_proxy
      - --providers.docker.swarmMode=false
      - --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory.
      #- --providers.file.filename=/path/to/file # Load dynamic configuration from a file.
      - --providers.file.watch=true # Only works on top level files in the rules folder
      - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing
      - --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL
      - --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json
      - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare
      - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53

Empezamos a complicar las cosas. Al docker le decimos que ejecute traefik utilizando una serie de comandos que configuran así a grosso modo:

  • Que traefik escuchará en el puerto 80 y 443
  • Que el log tendrá un nivel de "DEBUG", es decir todo. Tranquilos luego lo cambiamos. Además le decimos el buffer de líneas, la ruta del fichero y demás
  • trustedIPs indica las IPs en las que confiaremos para acceder a Traefik. Esto es importante ya que si no metemos aquí las IPs de Cloudlare no conseguiremos saber la IP real de quien accede a Cloudflare
  • providers.file.directory es importante ya que indicaremos el path donde estarán las reglas de Traefik2.
  • Las líneas de certificatesResolvers configuran la forma en la que crearemos el Certificado SSL. Como he comentado antes usaremos DNS Challenge. Es importante que al principio para evitar problemas la línea "certificatesResolvers.dns-cloudflare.acme.caServer" NO esté comentada. Así usaremos el entorno de pruebas de Let's Encrypt y no nos banearán por hacer muchas peticiones. Cuando ya tengamos el certificado funcionando la comentaremos.
    networks:
      t2_proxy:
        ipv4_address: 10.10.10.2
    security_opt:
      - no-new-privileges:true

Configuramos Traefik para que utilice la network que creamos antes y además le indicamos que tenga como IP la 10.10.10.2. Lo de security_opt es para que el docker no pueda escalar privilegios.

    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
      - target: 8080
        published: 8080
        protocol: tcp
        mode: host

Aquí indicamos los puertos del docker y como los usará. 80 y 443 es para acceder a los servicios y el 8080 es para la API.

    volumes:
      - $USERDIR/docker/traefik2/rules:/rules 
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - $USERDIR/docker/traefik2/acme/acme.json:/acme.json 
      - $USERDIR/docker/traefik2/traefik.log:/traefik.log 
      - $USERDIR/docker/shared:/shared

Esto indica las carpetas/ficheros de nuestra de las que hará uso el docker. Al final el docker no deja de ser un contenedor aislado con su propia estructura de carpetas y ficheros en su interior y si queremos que use algo "extra" debemos indicárselo. Le indicamos los ficheros de los que hemos hablo antes y la carpeta shared.

    environment:
      - CF_API_EMAIL=$CLOUDFLARE_EMAIL
      - CF_API_KEY=$CLOUDFLARE_API_KEY

Aquí le pasamos la información de CloudFlare para que pueda crear el certificado SSL correctamente.

2.4 Labels de Traefik2

Con todo lo anterior ya podríamos ejecutar el docker pero no podríamos acceder a él desde un navegador porque todavía no hemos configurado la otra gran gracia de Traefik, las "Labels" que son básicamente la configuración del servicio por detrás de Traefik, es decir, el router, middleware y service. Vamos poco a poco porque son unas pocas.

    labels:
      - "traefik.enable=true"
      # HTTP-to-HTTPS Redirect
      - "traefik.http.routers.http-catchall.entrypoints=http"
      - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"

Traefik.enable indica que este service docker hace uso de traefik, es decir que va a estar "proxificado". Las siguientes líneas configuran un "router" que es un redirect automático de HTTP a HTTPS de todas las peticiones que llegue a Traefik y cualquier de sus servicios. Ya que ponemos un certificado SSL que mínimo que usarlo siempre.

      # HTTP Routers
      - "traefik.http.routers.traefik-rtr.entrypoints=https"
      - "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINNAME`)"
      - "traefik.http.routers.traefik-rtr.tls=true"
      - "traefik.http.routers.traefik-rtr.tls.certresolver=dns-cloudflare" # Comment out this line after first run of traefik to force the use of wildcard certs
      - "traefik.http.routers.traefik-rtr.tls.domains[0].main=$DOMAINNAME"
      - "traefik.http.routers.traefik-rtr.tls.domains[0].sans=*.$DOMAINNAME"
      #- "traefik.http.routers.traefik-rtr.tls.domains[1].main=$SECONDDOMAINNAME" # Pulls main cert for second domain
      #- "traefik.http.routers.traefik-rtr.tls.domains[1].sans=*.$SECONDDOMAINNAME" # Pulls wildcard cert for second domain

Ahora un "router" para configurar este service concreto, el de traefik. Primero le indicamos que sólo escuche HTTPs, luego le indicamos que el service escucha bajo el Host traefik.$DOMAINNAME. Esto es que si vuestro dominio es example.com para llegar a traefik deberéis poner en el navegador "traefik.example.com"
Luego indicamos que use sólo TLS para que sea seguro.
tls.certresolver=dns-cloudflare" es importante. Esta label sólo la usaremos la primera vez para generar el certificado wildcard *.$DOMAINNAME, luego la comentaremos y así sólo usaremos un sólo certificado y no uno diferente para cada servicio como indicamos con las labels "main" y "sans". También os dejo como poner más certificados en caso de que trabajéis con más de uno.

      ## Services - API
      - "traefik.http.routers.traefik-rtr.service=api@internal"
      ## Middlewares
      - "traefik.http.routers.traefik-rtr.middlewares=middlewares-basic-auth@file"

Aquí indicamos el servicio de la API y el middleware. Si os fijáis en middleware pone "middlewares-basic-auth@file" eso es porque vamos a hacer uso de un fichero en el que vamos a reunir todas las reglas middleware. Esto lo haremos creando el fichero "middlewares.toml" en la carpeta "rules".

touch traefik2/rules/middlewares.toml

Lo rellenamos de la siguiente manera:

[http.middlewares]
  [http.middlewares.middlewares-basic-auth]
    [http.middlewares.middlewares-basic-auth.basicAuth]
#      username=user, password=mystrongpassword (listed below after hashing)
#      users = [
#        "user:$apr1$bvj3f2o0$/01DGlduxK4AqRsTwHnvc1",
#      ]
      realm = "Traefik2 Basic Auth"
      usersFile = "/shared/.htpasswd" #be sure to mount the volume through docker-compose.yml

Aún es muy básico, aquí sólo le indicamos que Traefik usará un metodo de autenticación básico cuyas credenciales están en el fichero creado anteriormente /shared/.htpasswd.

2.5 Probando Traefik

Vale llegados a este punto ya vamos a poder ejecutar por primera vez el docker-compose.yml que si habéis ido bien y yo no la he liado... deberíais tenerlo de la siguiente manera:

docker-compose.yml

Guardamos el fichero y lo ejecutamos

docker-compose -f docker-compose.yml up -d

Si todo va Ok deberíamos de poder poner en el navegador "traefik.example.com" y tras rellenar usuario y contraseña deberíamos ver:

Imagen Traefik

En próximos posts pongo los siguientes pasos:

  • Acabar configuración SSL
  • Middleware de Seguridad
  • Configurar Authelia
  • Configurar Servicio QBittorrent
  • Configurar Servicio Heimdall
19
Isengard

2.6 Configurando el certificado SSL
Vale, tenemos Traefik2 configurado pero todavía nos faltan un par de detalles para hacerlo perfecto. El primero de ellos es usar un certificado SSL bueno ya que si os fijáis en lo que habéis desplegado pues tenéis un certifcado "fake" de Let's Encrypt.

Imagen SSL Fake

Esto lo solucionamos rápido.. En el docker-compose iremos a la siguiente línea y la comentaremos poniendo una "#" por delante.

#- --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing

Además de esto deberemos borrar todo el contenido del siguiente fichero "$DOCKERDIR/traefik2/acme/acme.json". También sirve borrarlo y volverlo a crear, como prefiráis. Una vez hecho esto volvemos a hacer:

docker-compose -f docker-compose.yml up -d

Y voilá! Ya tenemos nuestro Traefik2 funcionando con un SSL bueno, bonito y barato de Let's Encrypt. Además si revisáis la información del certificado veréis que os sirve tanto para "dominio.com" como para "*.dominio.com". Es un wildcard perfecto para despegar cualquier servicio con "nombre.dominio.com" aunque para forzar esto deberemos comentar la siguiente línea para obligar a Traefik a no generar más certificados y usar el que acabamos de crear.

#- "traefik.http.routers.traefik-rtr.tls.certresolver=dns-cloudflare"

2.7 Securizando Traefik2
Pues ahora que tenemos Traefik ya funcionando vamos a securizarlo un poco para que así los servicios que pongamos por detrás funcionen lo más seguros posibles.
2.7.1 Rate Limit
Vamos a comenzar por configurar el número de peticiones que recibirán los servicios. ¿Por qué? Porque hay mucho cabroncete suelto que cuando descubre servicios le da por ir a joderlos y bombardearlos con peticiones y hacer así que peten por no poder satisfacer todas las peticiones causando un DoS de manual. Para ello abrimos el fichero "middlewares.toml" que creamos antes y añadimos lo siguiente:

[http.middlewares.middlewares-rate-limit]
    [http.middlewares.middlewares-rate-limit.rateLimit]
      average = 100
      burst = 50

Vale y ahora para ponerlo en práctica modificamos la línea que teníamos en traefik de middleware para incluir esta nueva opción

- "traefik.http.routers.traefik-rtr.middlewares=middlewares-rate-limit@file,middlewares-basic-auth@file"

2.7.2 Cabeceras de Seguridad
Esta es una de las cosas que más me gustan de los middlewares en traefik. Si hay algo que no mola de los dockers es que muchos no vienen nada configurados para funcionar de forma segura y entonces muchas veces cuando los publicas pues o son un coladero o bien los navegadores ni te dejan acceder a ellos porque directamente te bloquean el acceso por no cumplir un mínimo de seguridad. Con traefik 1 se podía solucionar pero implicaba ir uno a uno configurando las cosas, con traefik 2 esto se soluciona con un middleware que podemos ir replicando sencillamente en cada servicios. De nuevo abrimos el fichero "middlewares.toml" y añadimos:

  [http.middlewares.middlewares-secure-headers]
    [http.middlewares.middlewares-secure-headers.headers]
      accessControlAllowMethods= ["GET", "OPTIONS", "PUT"]
      accessControlMaxAge = 100
      hostsProxyHeaders = ["X-Forwarded-Host"]
      sslRedirect = true
      stsSeconds = 63072000
      stsIncludeSubdomains = true
      stsPreload = true
      forceSTSHeader = true
#      frameDeny = true #overwritten by customFrameOptionsValue
      customFrameOptionsValue = "allow-from https:<TUDOMINIO.COM>" #CSP takes care of this but may be needed for organizr. 
      contentTypeNosniff = true 
      browserXssFilter = true 
#      sslForceHost = true # add sslHost to all of the services
#      sslHost = "example.com"
      referrerPolicy = "same-origin" 
#      Setting contentSecurityPolicy is more secure but it can break things. Proper auth will reduce the risk.
#      the below line also breaks some apps due to 'none' - sonarr, radarr, etc.
#      contentSecurityPolicy = "frame-ancestors '*.example.com:*';object-src 'none';script-src 'none';"
      featurePolicy = "camera 'none'; geolocation 'none'; microphone 'none'; payment 'none'; usb 'none'; vr 'none';" 
      [http.middlewares.middlewares-secure-headers.headers.customResponseHeaders]
        X-Robots-Tag = "none,noarchive,nosnippet,notranslate,noimageindex,"
        server = ""

De nuevo, para ponerlo en práctica modificamos la línea que teníamos en traefik de middleware para incluir esta nueva opción

      - "traefik.http.routers.traefik-rtr.middlewares=middlewares-secure-headers@file,middlewares-rate-limit@file,middlewares-basic-auth@file"

Vale si os fijáis. La línea cada vez es más larga y más compleja de recordar. Vamos a simplificar esto creando una "middleware chain" que es básicamente una "agrupación de middlewares". Para ello creamos el fichero "middleware-chains.toml" y le ponemos lo siguiente:

[http.middlewares]
  [http.middlewares.chain-no-auth]
    [http.middlewares.chain-no-auth.chain]
      middlewares = [ "middlewares-rate-limit", "middlewares-secure-headers"]

  [http.middlewares.chain-basic-auth]
    [http.middlewares.chain-basic-auth.chain]
      middlewares = [ "middlewares-rate-limit", "middlewares-secure-headers", "middlewares-basic-auth"]

De esta forma hemos creado 2 "middleware chain". Una que nos incluye la seguridad de rate limit y las secure-headers y otra que incluye ambas cosas y además solicita "autenticación". Usaremos una u otra según el servicio, por ejemplo si tenemos un docker que ya trae autenticación parece lógico usar "chain-no-auth" y si no lo trae pues usaremos "chain-basic-auth". Aunque la realidad es que una vez tengamos authelia usaremos otro que vamos a crear ahora mismo jeje.

Para usar una middleware-chain en el docker-compose de traefik basta con añadir la siguiente línea y recrear el docker:

- "traefik.http.routers.portainer-rtr.middlewares=chain-basic-auth@file"

Bien, llegados a este punto ya tenemos configurado traefik2 y además lo tendremos securizado de forma muy básica pidiendo un usuario y un login y además le habremos aplicado tanto al propio traefik2 como a los servicios que pongamos por detrás un seguridad mínima gracias a las "middleware-chains" que hemos creado. Vamos a por el siguiente paso que es poner Authelia!

Paso 3 - Configurando Authelia como servicio OAuth

3.1 ¿Qué es eso de OAuth?

Open Authorization (OAuth) es un estándar abierto que permite flujos simples de autorización para sitios web o aplicaciones informáticas. ¿Claro no? Vale lo resumo de otra manera ¿habéis visto que mediavida deja logaros usando la cuenta de Google? Mediavida y millones de sitios más. Es lo típico que os sale una opción de registraros usando Google o Facebook pincháis y os sale la ventanita para poner vuestros datos y voilá de repente estáis registrados. Pues eso es OAuth básicamente.

Authelia es un servidio OpenSource que hace lo mismo pudiendo usar un LDAP o bien una base de datos que crees a mano. Nosotros vamos a usar una base de datos a mano.

Isengard

Reservado para futuro post

HeXaN

Grande el tío. Gracias por el aporte.

3
enin

No tengo ni puta idea de lo que es Traefik pero me guardo el post para hacerme el interesante y porque te lo has currado

LLoid

Currazo enorme, me lo apunto para mirarlo con calma

JuAn4k4

Gracias por compartir muchacho!

kevin101

y por aquí dejamos la fuente del post: https://www.smarthomebeginner.com/traefik-2-docker-tutorial/

1 2 respuestas
B

.

Isengard

#8 Correcto. Eso iba a ponerlo en cuanto acabe el post, ya lo comenté por el hilo de automatización también. Básicamente es esa guía y luego pondré cosas que me he encontrado al trastear con los dockers como que los de Authelia son muy puñeteros con los cambios y a veces se te va al garete el invento sin previo aviso hasta que vas al github y lo ves...

1 respuesta
kevin101

#10 Aprovechando que te tengo aqui:

He seguido la guia de la fuente para configurar mas o menos (por ahora solo traefik con OAuth) lo mismo pero con OVH, pero cuando trato de levantar el contenedor de traefik siempre me deja de funcionar con el siguiente log: "the router traefik-rtr@docker uses a non-existent resolver: myresolver"

Dejo aqui mi compose de traefik por si se viese algo extraño:

    traefik:
      container_name: traefik
      image: traefik:chevrotin # the chevrotin tag refers to v2.2.x
      restart: unless-stopped
      command: # CLI arguments
        - --global.checkNewVersion=true
        - --global.sendAnonymousUsage=true
        - --entryPoints.http.address=:80
        - --entryPoints.https.address=:443
                # Allow these IPs to set the X-Forwarded-* headers - Cloudflare IPs: https://www.cloudflare.com/ips/
        - --entrypoints.https.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/12,172.64.0.0/13,131.0.72.0/22
        - --entryPoints.traefik.address=:8080
        - --api=true
        #      - --api.insecure=true
        #      - --serversTransport.insecureSkipVerify=true
        - --log=true
        - --log.level=DEBUG # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
        - --accessLog=true
        - --accessLog.filePath=/traefik.log
        - --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
        - --accessLog.filters.statusCodes=400-499
        - --providers.docker=true
        - --providers.docker.endpoint=unix:///var/run/docker.sock
        - --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINNAME`)
        - --providers.docker.exposedByDefault=false
        - --providers.docker.network=t2_proxy
        - --providers.docker.swarmMode=false
        - --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory.
        #      - --providers.file.filename=/path/to/file # Load dynamic configuration from a file.
        - --providers.file.watch=true # Only works on top level files in the rules folder
        # - --certificatesResolvers.myresolver.acme.dnschallenge=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing
        # - --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL
        - --certificatesResolvers.myresolver.acme.storage=/letsencrypt/acme.json
        - --certificatesresolvers.myresolver.acme.email=<my-email>
        - --certificatesResolvers.myresolver.acme.dnsChallenge=true
        - --certificatesResolvers.myresolver.acme.dnsChallenge.provider=ovh
        - --certificatesResolvers.myresolver.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53
      networks:
        t2_proxy:
         # ipv4_address: 192.168.90.254 # You can specify a static IP
        #    networks:
        #      - t2_proxy
      security_opt:
        - no-new-privileges:true
      ports:
        - target: 80
          published: 80
          protocol: tcp
          mode: host
        - target: 443
          published: 443
          protocol: tcp
          mode: host
        - target: 8080
          published: 8082
          protocol: tcp
          mode: host
      volumes:
        - $USERDIR/traefik/rules:/rules 
        - /var/run/docker.sock:/var/run/docker.sock:ro
        - $USERDIR/traefik/acme/acme.json:/acme.json 
        - $USERDIR/traefik/traefik.log:/traefik.log 
        - $USERDIR/shared:/shared
      
environment: - OVH_ENDPOINT=ovh-eu - OVH_APPLICATION_KEY=<ovh_application_key> - OVH_APPLICATION_SECRET=<ovh_application_secret> - OVH_CONSUMER_KEY=<ovh_consumer_key> labels: - "traefik.enable=true" # HTTP-to-HTTPS Redirect - "traefik.http.routers.http-catchall.entrypoints=http" - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)" - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" # HTTP Routers - "traefik.http.routers.traefik-rtr.entrypoints=https" - "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINNAME`)" - "traefik.http.routers.traefik-rtr.tls=true" - "traefik.http.routers.traefik-rtr.tls.certresolver=myresolver" # Comment out this line after first run of traefik to force the use of wildcard certs - "traefik.http.routers.traefik-rtr.tls.domains[0].main=$DOMAINNAME" - "traefik.http.routers.traefik-rtr.tls.domains[0].sans=*.$DOMAINNAME" # - "traefik.http.routers.traefik-rtr.tls.domains[1].main=$SECONDDOMAINNAME" # Pulls main cert for second domain # - "traefik.http.routers.traefik-rtr.tls.domains[1].sans=*.$SECONDDOMAINNAME" # Pulls wildcard cert for second domain ## Services - API - "traefik.http.routers.traefik-rtr.service=api@internal" ## Middlewares - "traefik.http.routers.traefik-rtr.middlewares=middlewares-basic-auth@file"

Ves algo extraño o que no encaje?

2 respuestas
Isengard

#11 Pues no veo mucho la verdad:
Me aseguraría que la ruta /letsencrypt/acme.json existe y tengas creado el fichero aunque sea vacío
Y luego pondría la línea

Para evitar un posible baneo mientras andas probando.

1
Luthenis

Excelente guía. Hace poco hice algo parecido pero usando oauth de google. ¿Que diferencias hay entre authelia y oauth de google? ¿Merece la pena cambiar?

1 respuesta
Isengard

#13 Authelia es “selfhosted” y OAuth es de Google. Si te da la mismo tener que pasar por Google pues no yay diferencia. Yo lo puse por probar y porque lo uso y tal... si lo fuese con mucha gente que tendría que llevar yo la creación de los usuarios y tal... Google

2 1 respuesta
JuAn4k4

#14 Cómo que OAuth es de google ? O Te refieres a que el 2FA lo hace usando Google Authenticator que nada tiene que ver con OAuth ? O hay un servicio que se llama OAuth y me he perdido ?

1 respuesta
Isengard

#15 Me refería a que con OAuth tiras de Google por el Google Authenticator. Respondí deprisa disculpa.

1 comentario moderado
9 días después
Isengard

Post updateado. A ver si mañana puedo continuarlo!
#11 ¿conseguiste arreglar el problema?

1 respuesta
kevin101

#18 Me fui de vacaciones y lo deje como estaba.

1 año después
hda

Hey @Isengard ! No había visto este post, por lo visto estoy haciendo lo mismo, llevo unos cuantos días configurando. Viendo el docker-compose estamos siguiendo la misma guía, la de smarthomebeginner (tal como indica #8 ). Recomiendo encarecidamente que pongas la fuente en #1 , si no tú, algún admin que edite ( @gonya707 , @Jastro ), pues es un poco feo de otro modo.

Ocurre, no sé si a ti te habrá pasado lo mismo, que esta web de smarthomebeginner, de tanto tiempo que lleva y lo activa que es, resulta ligeramente caótica. Sobre todo porque su github se encuentra en un estado siempre más avanzado que los posts de ese blog. Por eso pienso que es mejor ir poco a poco digiriendo cada cosa que él hace y adaptando el asunto para lo que uno quiere. Por ejemplo y en mi caso, pretendo maximizar la securización del sistema así que parto de socket_proxy, secrets y utilizo, por ejemplo, otro gestor de ddns (el de hotio/cloudflareddns ), entre otras cosas.

En algún momento haré el segundo hilo de la serie de tres que pretendo (que empezó con este), y trataré el asunto de traefik y demás. Citaré este para quitarme algo de trabajo, jejeje. Ahora bien, tengo que revisar #1 para saber qué has adaptado de la guía de smarthomebeginner.

¡Un saludo y gracias por el aporte!

2 1 respuesta
Isengard

#20 Hecho!!!

hda

Estoy contento, ayer conseguí rular el traefik (última versión), con Docker-Compose (formato de archivo 3.8, el último), en un usuario con privilegios mínimos, integrando por el momento todos los contenedores base que uso a través de socket proxy. Este proxy lo sirve un contenedor, el cual es el único con acceso directo al socket de docker. En el futuro me pensaré si meter subredes dependiendo de la topología e integración entre contenedores.

Además, toda la información sensible como email, contraseñas, API tokens, htpsswd, etc, la tengo integrada en los contenedores a través de SECRETS desde una carpeta (voy con swarm off) y no en variables de entorno. Los contenedores que lo aceptan van con UID y GID de user limitado.

Del traefik he configurado hasta 4 middlewares de seguridad básica y diferentes combinaciones entre cadenas de estos. El siguiente paso es meter OAuth.

Es todo un logro para mí, porque hasta la semana pasada había jugado con docker infructuosamente en dos ocasiones, y ni sabía de la existencia de compose o de qué era un proxy inverso. Este no es mi campo para nada. Ha sido mucho leer y mucho aprehender de diferentes documentaciones. Para la mayoría de este subforo lo que he logrado será trivial, para mí es una victoria XD

5

Usuarios habituales

  • hda
  • Isengard
  • kevin101
  • TraefikTeam
  • JuAn4k4
  • Luthenis
  • HeXaN