Traefik 使用进阶

2025 年 12 月 03 日

上个月搭建了家庭服务器,然后简单配置了 traefik 做为应用网关。虽然能用,但存在几个问题:

  • 配置时需要手动修改文件,明显不方便。
  • 安全性上,简单配置了 basic-auth 作为 middleware,但如果后端服务也依赖 basic-auth(比如 webssh2),就会产生冲突。

针对这两个问题,做了以下几个改进:

  • 将原来的静态配置直接放到 docker-compose.yml 中,减少了配置文件。
  • 使用 mantrae 提供 web 配置界面,免去手动修改配置文件。
  • 使用 tinyauth 做 forward-auth,避免跟后端产生冲突。

记录一下对这部分的理解。

概念整理

域名 DDNS 映射和防火墙配置的思路前面都记录过,不再重复了。这里只需要整理一下概念。

Traefik 相关

  • 入口点(entrypoint),可以简单理解为端口,比如 web(80)和 websecure(443)。
  • 路由(router),即 traefik 提供的反向代理的配置描述。
  • 静态配置,即 traefik 启动时必须的配置,可以通过 配置文件 或 command 提供。
  • 动态配置,即 traefik 运行期所需的配置。
  • 动态配置提供者(provider),可以选择以下几种的组合:
    • 文件(file),通常是监视一个目录,目录下配置文件改动后就立刻生效。
    • docker,traefik 会扫描 docker 节点,当新增 docker 包含对应的 labels 时,则自动生成路由。
    • http,可以从 http 获取动态配置,比如 mantrae 即可以采用此方式提供配置。
  • 中间件(middleware),在外部请求到达真正的服务(service)之前,traefik 会先让配置的 middleware 处理。所以 auth 就是很典型的中间件。

可以这样简单的理解 traefik 的工作方式。

  1. traefik 启动时,读取静态配置,按照配置开始工作。
  2. traefik 启动后,通过 provider 读取动态配置,然后动态添加 router,提供反向代理服务。
    1. 如果 provider 是 docker,则动态配置可以从 docker labels 读取。
    2. 如果 provider 是 file,则动态配置根据文件内容变更。
    3. 如果 provider 是 http,则动态配置为定时拉取。
  3. 外部请求到达 traefik 的 entrypoint 之后,traefik 根据 router 规则,如果有 middleware,就先由 middleware 处理。如果接下来还需要进一步处理,则转给真正的 service。

Mantrae 相关

本质上,mantrae 只是为 traefik 提供动态配置的一个 provider(注意:可以不包括全部动态配置)。

虽然好像也可以把证书交给 mantrae 处理,但我觉得……没必要啊。

Tinyauth 相关

tinyauth 是一个 forward-auth 中间件,traefik 对于这类中间件的处理方式是:

  1. 先将原始请求转发给 forward-auth 中间件处理,如果通过,则继续转发给 service。
  2. 如果不通过,则跳转到 forward-auth 中间件提供的登录页面,携带下一步跳转的 service 目标地址。
    1. 如果登录成功,则跳转 service。
    2. 如果登陆失败,则停在 forward-auth 的登录页面。

所以这里,tinyauth 本身就需要是一个 router。

完整配置示例及解析

该配置将 tinyauth,mantrae,traefik 放在一个 docker compose 中,共享同一个网络,也方便使用。

下面是脱敏后的 docker-compose.yml 示例:

services:
  tinyauth:
    image: ghcr.io/steveiliop56/tinyauth:v4
    container_name: tinyauth
    restart: unless-stopped
    environment:
      - APP_URL=https://tinyauth.example.com
      - USERS=TINYAUTH_USER
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.tinyauth.rule=Host(`tinyauth.example.com`)"
      - "traefik.http.routers.tinyauth.tls.certResolver=myresolver"
      - "traefik.http.services.tinyauth.loadbalancer.server.port=3000"
    networks:
      - ipv6_network

  mantrae:
    image: ghcr.io/mizuchilabs/mantrae:latest
    container_name: mantrae
    environment:
      - SECRET=MANTRAE_SECRET
      - ADMIN_PASSWORD=MANTRAE_ADMIN_PASSWORD
    ports:
      - "9000:3000"
    volumes:
      - ./mantrae:/data
    restart: unless-stopped
    networks:
      - ipv6_network

  traefik:
    image: "traefik:latest"
    container_name: "traefik"
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "9080:8080"
    volumes:
      - "./config:/etc/traefik"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    command:
      - --log.level=INFO
      - --api.dashboard=true
      - --api.insecure=true
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      - --entrypoints.web.http.redirections.entrypoint.permanent=true
      - --entrypoints.websecure.address=:443
      - --entrypoints.traefik.address=:8080
      - --providers.docker=true
      - --providers.http.endpoint=http://mantrae:3000/api/default?token=MANTRAE_PROFILE_TOKEN
      - --providers.http.pollinterval=5s
      - [email protected]
      - --certificatesresolvers.myresolver.acme.storage=/etc/traefik/acme.json
      - --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
    networks:
      - ipv6_network
    depends_on:
      - tinyauth 
      - mantrae

networks:
  ipv6_network:
    enable_ipv6: true

接下来是对于各部分配置的讲解。

tinyauth 配置要点

tinyauth 首先是个独立的服务。不受其他服务影响。

就像前面提到的,tinyauth 本身就是一个 router,因此这部分通过 labels 配置。

APP_URL 必须指向 router 对应的域名。

TINYAUTH_USER 可以通过docker run -i -t --rm ghcr.io/steveiliop56/tinyauth:v4 user create --interactive命令生成。多个用户以逗号隔开。

其他配置参考文档

mantrae 配置要点

mantrae 用来管理 traefik,也是个独立服务,不过我觉得没必要把它暴露到外部,就没配置 router。

SECRET 可以通过 openssl rand -hex 16 命令生成,16/24/32 位都可以。

MANTRAE_ADMIN_PASSWORD 是明码。

MANTRAE_PROFILE_TOKEN 必须先启动一次 mantrae 后,在界面上获取。

traefik 配置要点

traefik 依赖于上面两个服务。

traefik 接管 80/443 端口,另外提供一个 dashboard 是只读的。

使用 command 配置,可以省掉静态配置文件。使用 mantrae 配置,可以省掉动态配置文件。

entrypoint 配置将 80 端口强制转向 443。

映射 volume 的 config 目录下需要有一个 acme.json 文件,权限 600。

provider 用 docker 的话,需要映射 docker volume。

MANTRAE_PROFILE_TOKEN 需要改写成从 mantrae 主界面获取的 token。

调试方式

结合 mantrae 和 traefik 的 dashboard(在上面例子中配置成了 9000 和 9080 端口),根据配置的状态进行分析。

Top