Use Traefik as reverse proxy - Enable https on your website

SSL的工作原理和其重要性我们在很早之前的文章中已经做了说明。前面的文章已经叫回答家如何使用Traefik搭建网站,但是那些教程都是建立在80端口也就是http之上。这篇文章会介绍如何在Traefik下设置安装SSL。

使用CA签发的SSL证书

如果是喜欢自己控制证书生成环节的朋友,或者需要安装由其他CA签发的证书的朋友,Traefik可以使用你从其他CA申请的证书来secure你的网站。

这里需要调整的主要是证书的存放位置,docker-compose.yml文件里面的traefik加载volume和traefik.toml文件的设置。由于区别集中在了traefik.toml 这里我先放上docker-compose.yml文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
version: '3.3'

services:
reverse-proxy:
image: traefik
command: --api --docker
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
#这里需要读取traefik.toml文件来定义链接方式
- ./traefik.toml:/traefik.toml
#同时也需要把SSL文件所在文件夹映射到Traefik的Continer里做引用
- ./ssl:/ssl
labels:
- "traefik.port=8080"
- "traefik.backend=reverse-proxy"
- "traefik.frontend.rule=Host:traefik.example.com"
- "traefik.enable=true"

#这里我用Whoami的image来测试
whoami:
image: emilevauge/whoami
labels:
- "traefik.frontend.rule=Host:whoami.example.com"
一张证书用在所有subdomain上

如果你需要secure的所有域名都在一张证书上(wildcard或者 SAN Certificates),你只需要引用这个证书一次即可。

1
2
3
4
5
6
7
8
9
10
11
defaultEntryPoints = ["http", "https"]
#我这里是同时只是http和https的链接。之后我会修改一些让所有的http链接被redirect去https
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "./ssl/wildcard/wildcard.crt"
keyFile = "./ssl/wildcard/wildcard.key"

可以看到我们定义所有的SSL流量都通过这种通配符来链接。

每个subdomain使用自己的证书

如果你需要每一个subdomain对应一张证书,你只需要把证书都列出来(如下),Traefik会自动配对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
defaultEntryPoints = ["http", "https"]

[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "./ssl/traefik/traefik.crt"
keyFile = "./ssl/traefik/traefik.key"
[[entryPoints.https.tls.certificates]]
certFile = "./ssl/whoami/whoami.crt"
keyFile = "./ssl/whoami/whoami.key"
...

可以看到我只是把一对一对的证书都列出来,traefik可以自动找到对应的域名

主域名用一张证书,所有其他域名用一张

这个配置跟上面一样,只是下面罗列的其他证书文件只需要用一张wildcard解决即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
defaultEntryPoints = ["http", "https"]

[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "./ssl/traefik/traefik.crt"
keyFile = "./ssl/traefik/traefik.key"
[[entryPoints.https.tls.certificates]]
certFile = "./ssl/wildcard/wildcard.crt"
keyFile = "./ssl/wildcard/wildcard.key"

Traefik自动生成SSL证书

如果你不需要从CA获取证书,而且希望系统自动更新证书,traefik可以通过两个验证方法从Let’sEncrypt帮你自动获取到证书,官方的说明在这里,官方的例子在这里。同样的docker-compose.yml文件是一样的,先贴出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3.3'

services:
reverse-proxy:
image: traefik
command: --api --docker
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.toml:/traefik.toml
#这里需要创建一个acme.json文件来放证书
- ./acme.json:/acme.json
labels:
- "traefik.port=8080"
- "traefik.backend=reverse-proxy"
- "traefik.frontend.rule=Host:traefik.example.com"
- "traefik.enable=true"

whoami:
image: emilevauge/whoami
labels:
- "traefik.frontend.rule=Host:whoami.example.com"

需要注意的是acme.json文件需要修改权限

1
2
touch acme.json
chmod 600 acme.json
httpChallenge

首先是使用http的方式来验证。其使用的traefik.toml文件内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
defaultEntryPoints = ["http", "https"]

#先打开http和https两种连接方式
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]

#Let's encrypt setup
[acme]
#随便一个你的邮箱
email = "[email protected]"
#证书的存放文件
storage = "acme.json"
#可以在下面列出你需要生成的证书,你也可以什么都不列,系统会自动帮你生成
onHostRule = true
#这里也可以用onDemand = true
entryPoint = "https"
[acme.httpChallenge]
entryPoint = "http"

########这个部分是optional的#############
#[[acme.domains]]
# main = "local1.com"
# sans = ["test1.local1.com", "test2.local1.com"]
#[[acme.domains]]
# main = "local2.com"
# sans = ["test1.local2.com", "test2x.local2.com"]
#######################################

当你通过https访问的时候,第一次会有一点延迟,traefik会自动生成一张证书来保护该域名。每一个sub domain都会有一张自己的证书。

dnsChallenge

另外的一个验证方法就是用DNS的方式。

如果想要Wildcard证书,只能使用DNS的验证方式来获取。目前Wildcard证书的生成有一些问题,开发者正在着手解决。

首先我们需要通过domain registrar来获取到API key,这是官方的文章说明目前测试过哪些提供API的域名注册上(DNS管理)

我这个域名是在阿里云上注册的,也许是我没有找对地方,我没有找到aliyun域名管理的API,因此我不得不使用CloudFlare来管理我的DNS。至于如何在Cloudflare获取api key,这个请各位Google。

拿到API Key之后,我们需要在docker-compose.yml里把这pi key作为environment加到Traefik下面

1
2
3
4
5
6
7
8
9
10
version: '3'

services:
reverse-proxy:
image: traefik
...
environment:
- "CLOUDFLARE_EMAIL=your cloudflare email"
- "CLOUDFLARE_API_KEY=your api key"
...

接下来就是traefik.toml文件的内容,跟上面的文件差不多,只是需要定义一下host name。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
defaultEntryPoints = ["http","https"]

[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]

#Let's encrypt setup
[acme]
email = "[email protected]"
storage = "acme.json"
entryPoint = "https"
[acme.dnsChallenge]
provider = "cloudflare"
delayBeforeCheck = 0

[[acme.domains]]
main = "whoami.example.com"
[[acme.domains]]
main = "traefik.example.com"

运行sudo docker-compose up -d,证书就会自动获取并正确使用。