近期,我将个人主页(http://www.whezh.com)和博客(http://blog.whezh.com)迁移到了 HTTPS,这篇文章记录了我迁移的全过程,包括 SSL 证书的申请以及 Nginx 相应的配置,其中 HTTPS 证书使用的是 Let's Encrypt 提供的免费证书。值得庆幸的是,今天年初 Let's Encrypt 已经支持申请泛域名证书,省去了一些麻烦。
安装证书
在 Let's Encrypt 网站上介绍了如何安装证书,大致是 SSH 到服务器,然后安装 ACME Client(ACME Client 可以为我们自动完成证书的签发),并列出了可用的 ACME Client,Let's Encrypt 推荐我们使用 Certbot。
我一开始使用了 certbot-auto 并且成功安装了证书,但是后面在设置自动续期的时候遇到了一些问题,使我放弃使用 certbot-auto 转而使用了 acme.sh,最终完成了迁移工作。我先介绍使用 acme.sh 的经历,后面我会简要说明使用 certbot-auto 的过程及遇到的问题。
使用 acme.sh
acme.sh 的文档十分详细,安装和使用起来也十分的简单,只需要几个命令即可。它支持很多平台,我的服务器是 Ubuntu。
安装
acme.sh 支持两种安装方式,一种是在线安装,一种是通过 Git 安装。我使用的是在线安装的方式,即执行下面的命令:
$ curl https://get.acme.sh | sh
复制代码
在安装的时候有警告,提示安装 socat,apt-get install socat
。
安装过程经历了三个步骤:
- 将 acme.sh 安装到
~/.acme.sh/
目录下。 - 创建一个别名:
alias acme.sh=~/.acme.sh/acme.sh
。 - 创建一个计划任务,每天的 0:00 会检查并自动更新证书。
如果出现 acme.sh 没找到的情况,可以手动执行第 2 步,我当时就是这样。
生成证书
acme.sh 实现了 acme 协议支持的所有验证协议,一般有两种方式验证: HTTP 和 DNS 验证,两种验证都是为了证明域名所有权,就像百度、谷歌的站点统计服务。
HTTP 方式需要在签发证书时指定域名, 并指定域名所在的网站根目录。 acme.sh 会全自动的生成验证文件, 并放到网站的根目录, 然后自动完成验证,验证完成后会删除验证文件,整个过程没有任何副作用。如果使用了 apache 或者 nginx,acme.sh 还可以智能的读取配置文件自动完成验证,只需要指定对应的模式即可,不会修改任何配置。
我使用的是 DNS 验证方式,acme.sh 提供了两种模式,一种是手动,另一种则是自动。其中手动方式需要我们手动执行命令并设置 DNS 解析,自动方式则需要 DNS 服务商提供 API,acme.sh 目前已经支持家服务商,具体用法见文档。
因为我使用的是阿里云服务器,根据文档的说明,首先需要设置环境变量:
$ export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
$ export Ali_Secret="jlsdflanljkljlfdsaklkjflsa"
复制代码
Ali_key
和 Ali_Secret
会被保存到 ~/.acme.sh/account.conf
中用于下次使用。
设置完环境变量之后,执行下面的命令完成证书的签发:
$ acme.sh --issue --dns dns_ali -d *.whezh.com
复制代码
签发完成后,得到下图所示结果,代表成功生成证书。
证书默认安装在 ~/.acme.sh/<domain>
下,但我们不能直接使用此目录下的证书,这里面的文件是内部使用的,而且目录结构可能会变化。正确的做法是使用 installcert
命令将证书安装到指定目录。
$ acme.sh --installcert -d *.whezh.com --key-file /etc/letsencrypt/whezh.com/whezh.com.key --fullchain-file /etc/letsencrypt/whezh.com/fullchain.cer --reloadcmd "service nginx restart”
复制代码
其中 Nginx 中 ssl_certificate
配置使用 fullchain.cer
,而不是 <domain>.cer
,否则 SSL Labs 的测试会报 Chain issues Incomplete 错误。 reloadcmd
参数指定了证书自动更新后执行的重载命令。 这里指定的所有参数都会被自动记录下来,并在将来证书自动更新以后,被再次自动调用。
到这里,证书的安装工作就全部完成了,接下来只需要配置服务器即可。
使用 certbot-auto
下载安装 certbot-auto
$ wget https://dl.eff.org/certbot-auto
$ chmod a+x certbot-auto
复制代码
签发证书
$ sudo ./certbot-auto certonly -d *.whezh.com --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory
复制代码
上述命令指定完之后,弹出提示,添加 TXT 解析记录。
我们需要登录域名 DNS 服务商网站,在网页上添加一条 TXT 解析记录。添加完成后,可以使用 nslookup -type=TXT _acme-challenge.whezh.com
命令验证是否添加成功。
验证成功后,回车继续执行即可成功申请到证书。
一开始,成功申请到证书后,配置了一下 Nginx 可以正常使用。但是,当我想设置自动更新证书时,执行 certbot-auto renew
命令提示错误,大致意识是模式不正确,缺少一点东西,但是也不想多折腾,就果断放弃了。
Nginx 配置
证书实现完成后,就需要进行服务器配置了。这里需要说明的是,我将博客网址设为了二级域名 blog.whezh.com
,个人主页使用的是 www.whezh.com
,我需要缺省的 whezh.com
重定向到 www.whezh.com
,并且强制所有网页使用 HTTPS。
个人主页配置:
# www.whezh.com.conf
server {
listen 80;
server_name whezh.com www.whezh.com;
return 301 https://www.whezh.com$request_uri;
}
server {
listen 443;
server_name whezh.com;
return 301 https://www.whezh.com$request_uri;
}
server {
listen 443;
server_name www.whezh.com;
ssl on;
ssl_certificate /etc/letsencrypt/whezh.com/fullchain.cer;
ssl_certificate_key /etc/letsencrypt/whezh.com/whezh.com.key;
location / {
root /home/hezhou/www/home;
index index.html;
}
}
复制代码
博客配置:
# blog.whezh.com.conf
server {
listen 80;
server_name blog.whezh.com;
return 301 https://blog.whezh.com$request_uri;
}
server {
listen 443;
server_name blog.whezh.com;
root /var/www/ghost/system/nginx-root;
ssl on;
ssl_certificate /etc/letsencrypt/whezh.com/fullchain.cer;
ssl_certificate_key /etc/letsencrypt/whezh.com/whezh.com.key;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2368;
}
location ~ /.well-known {
allow all;
}
client_max_body_size 50m;
}
复制代码