Talking Lab

如何配置traefik通过Cloudflare自动配置反向代理并生成、更新SSL证书

To be happy is to be able to become aware of oneself without fright.
— Walter Benjamin

Traefik介绍

Traefik是一款开源的反向代理服务器,支持服务热发现,在首次配置完成后,就能将其忘在一边,接下来只需花时间配置和部署新应用,而不再需要反复配置和维护Traefik自身。

Traefik支持且不限于Docker、k8s、Docker Swarm、AWS在内多种集群,可以部署到其中、或者直接以服务方式运行。本文将介绍基于Docker的安装配置方式,并会给出一个基于Cloudflare自动获取、更新SSL证书的示例。

安装

使用docker

开始之前,请先准备一个配置文件。本文将基于traefik官方的配置示例以进行,你可以从以下链接下载:

下载后,将其更名为traefik.yml,使用编辑器打开,将api段修改如下:

# Enable API and dashboard
#
# Optional
#
api:
  # Enable the API in insecure mode
  #
  # Optional
  # Default: false
  #
  insecure: true

  # Enabled Dashboard
  #
  # Optional
  # Default: true
  #
  dashboard: true

然后在traefik.yml的所在目录,执行以下命令:

docker run -d -p 8080:8080 -p 80:80 \
    -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v3.1

如果没有任何问题的话,上述命令将会输出新创建的traefik容器的ID。这时候,你就可以使用下面这个URL访问其管理页面了:

使用Docker Compose

直接使用docker的话,管理起来不太方便,所以我习惯使用Docker Compose进行管理。

准备docker-compose.yml文件

首先创建一个名为docker-compose.yml的文件,文件内容如下:

version: '3'

services:
  traefik:
    image: traefik:v3.1
    container_name: "traefik"
    restart: always
    ports:
      - 80:80
      - 443:443
      - 8443:8443
    networks:
      - web
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"     # 使得traefik可以通过docker进行服务自发现
      - "./config/traefik.yml:/etc/traefik/traefik.yml" # 主配置文件
      - "./config/letsencrypt:/etc/traefik/letsencrypt" # Let's Encrypt的证书存放路径
    environment:
      - CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL}
      - CLOUDFLARE_API_KEY=${CLOUDFLARE_API_KEY}
    labels:
      - "traefik.enable=true"

      - "traefik.http.routers.traefik.rule=Host(`traefik.your-domain.com`)"
      - "traefik.http.routers.traefik.service=api@internal"

networks:
  web:
    external: true

注意:上面文件中的traefik.your-domain.com应该已在你的Cloudflare的DNS配置中配置完成。之后会使用此域名访问你的traefik面板。

准备基于Docker环境的traefik.yml配置文件

请参考以下文件准备你的traefik.yml,放到当前目录的config子目录中。注意,为了节省篇幅,我移除了大部分注释内容,你可以参考traefik.sample.yml中的注释以更多了解各配置项的含义:

global:
  checkNewVersion: true
  sendAnonymousUsage: true

entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure  # 自动转到https://your-domain:8443
          scheme: https

  https:
    address: :443
    http:
      tls:
        certResolver: cfresolver
      redirections:
        entryPoint:
          to: websecure  # 自动转到https://your-domain:8443
          scheme: https

  websecure:
    address: :8443
    http:
      tls:
        certResolver: cfresolver # 使用ID为cfresolver的证书生成器,注意与下面"certificatesResolvers"中的定义需要能匹配起来

api:
  # Enabled Dashboard
  dashboard: true

providers:
  # Enable Docker configuration backend
  docker: {} # 一般情况下,使用默认值即可

certificatesResolvers:
  cfresolver:
    # Enable ACME (Let's Encrypt): automatic SSL.
    acme:
      email: "admin@your-domain.com"                # 会放到证书中的联系方式,可以随意填
      storage: "/etc/traefik/letsencrypt/acme.json" # 存放Let's Encrypt证书的文件,注意路径与docker-compose.yml中的路径保持一致,以便于管理

      dnsChallenge:
        provider: cloudflare  # 这里使用免费的Cloudflare
        delayBeforeCheck: 10  # 注意,如果你的网络比较慢的话,可以适当加大这个数值

NOTE:

  • docker: {}
    • 激活对docker环境的支持。这样的话,以后可以自动发现并支持新创建的容器
    • 全部使用默认值。注意docker-compose.ymlvolumes中一定要包括以下内容:
      • "/var/run/docker.sock:/var/run/docker.sock"
  • certificatesResolvers下的cfresolver
    • 使用DNS-01 ACME challenge的方式生成证书
      • 需要你将DNS解析指向Cloudflare的服务器,并且提供API Key(稍后会提到如何获取API Key)
    • 不使用HTTP-01 challenge的原因是,这种方式需要访问http://your-domain.com:80以确定域名指向与服务器的external IP的一致性。但是我们的家宽一般禁止了80/443端口的访问,所以没法使用HTTP-01 challenge
    • 更多DNS challenge type的细节:
      • https://letsencrypt.org/docs/challenge-types/
      • https://doc.traefik.io/traefik/https/acme/#the-different-acme-challenges

准备Cloudflare的API Key

获取Cloudflare的Global API Key

创建.env文件

docker-compose.yml的所在目录,创建.env文件,将上一步骤中获取的API Key填入:

CLOUDFLARE_EMAIL=your-cloudflare-account-email@example.com
CLOUDFLARE_API_KEY=xxxxxxxxx

启动

执行以下命令启动traefik:

docker network create web # 创建名为web的外部网络
docker-compose up -d      # 创建并启动traefik容器
docker-compose logs -f    # 跟踪traefik启动日志

如果执行docker-compose logs -f之后应该没有任何输出,则表明一切正常。

访问traefik的dashboard

在浏览器中访问如下网址:

注意:

一切正常的话,你将看到如下所示的dashboard页面:

第三方应用示例

当traefik如上所示配置完成后,再增加任何http应用时,不再需要修改该traefik容器上的任何配置。

以下是一个示例,展示了如何通过Docker Compose的labels,配置traefik服务发现的标签。该容器启动后,traefik会自动根据其配置的labels,自动生成证书与转发规则。

httpbin示例

新建一个目录httpbin,在之下创建一个docker-compose.yml文件,内容如下:

version: '3'

services:
  httpbin:
    image: mccutchen/go-httpbin
    container_name: httpbin
    networks:
      - web
    labels:
      - "traefik.enable=true"        # 在本容器启用traefik
      - "traefik.docker.network=web" # 使用名为web的容器网络,可以连接traefik与本容器
      - "traefik.http.routers.httpbin.rule=Host(`httpbin.your-domain.com`)" # 如果访问域名是"httpbin.your-domain.com",则将请求转发到本容器
      - "traefik.http.routers.httpbin.tls.certresolver=cfresolver" # 使用cfresolver这个certResolver来生成SSL证书
      - "traefik.http.services.httpbin.loadbalancer.server.port=8080" # 本容器对外暴露服务的接口/traefik将http请求转发的目标端口。如果本容器只expose了一个端口的话,本行可忽略。

networks:
  web:
    external:
      true

启动示例容器:

docker-compose up -d

执行以下命令以验证:

curl -v https://httpbin.your-domain.com:8443/user-agent

一切顺利的话,你会见到类似如下的输出:

* About to connect() to httpbin.your-domain.com port 8443 (#0)
*   Trying 192.168.6.22...
* Connected to httpbin.your-domain.com (192.168.6.22) port 8443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
*     subject: CN=httpbin.your-domain.com
*     start date: Sep 13 05:48:11 2024 GMT
*     expire date: Dec 12 05:48:10 2024 GMT
*     common name: httpbin.your-domain.com
*     issuer: CN=R10,O=Let's Encrypt,C=US
> GET /user-agent HTTP/1.1
> User-Agent: curl/7.29.0
> Host: httpbin.your-domain.com:8443
> Accept: */*
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: *
< Content-Length: 34
< Content-Type: application/json; charset=utf-8
< Date: Fri, 13 Sep 2024 06:53:05 GMT
<
{
  "user-agent": "curl/7.29.0"
}
* Connection #0 to host httpbin.your-domain.com left intact

总结

本文介绍了如果通过docker compose安装管理traefik反向代理,并通过httpbin展示了traefik的服务自发现能力。

通过以上示例,大家可以看出,traefik是一个非常灵活且方便的反向代理,通过其服务自发现能力,大大减轻了反向代理、以及SSL证书的难度,增强了http应用快捷程度以及易用性。

退出移动版