Let’s Encrypt 已经成为免费 https 的标配,与此同时 Nginx 也成为了反向代理的标配,不管是单节点服务还是k8s集群都会默认使用 Nginx。

今天就用 Let’s Encrypt 配合 Nginx 为我们的 Discourse 添加 https 功能。

简介

Discourse 默认是提供基于 Let’s encrypt 的 https 功能,但是如果你正在使用 Nginx 为你的 Discourse 提供反向代理,抱歉,此路不通

所以接下来要使用 Let’s Encrypt 官方推荐客户端 —— Certbot 获取我们的网站添加 https 的小绿锁。

测试环境是 CentOS 7,其他环境方法类似。

安装 Certbot 并获取证书

安装 Certbot 和 ginx 插件:

1
$ yum install certbot python2-certbot-nginx

运行 Certbot:

1
$ certbot certonly --nginx
  1. 这个命令一开始会要求你输入一个邮箱,填写你自己的邮箱。

  2. 接下来是同意协议,同意。

  3. 加入 EFF 协议,可以拒绝。

  4. 选择你想要激活 https 的域名,填写数字并用逗号分隔。

整个过程还是比较清晰的。

运行成功后你会看到 Congratulations! 的字样,下一行就是生成的证书。通常是:

1
2
/etc/letsencrypt/live/<example.com>/fullchain.pem
/etc/letsencrypt/live/<example.com>/privkey.pem

配置 Nginx

我们以 discourse 的配置为例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
server {
    listen 443 ssl http2;  listen [::]:443 ssl http2;
    server_name <example.com>;
            
    ssl on; 
    ssl_certificate /etc/letsencrypt/live/<example.com>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<example.com>/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    ssl_session_tickets off;
  
    location / {                
        proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
        proxy_set_header Host $http_host;
        proxy_http_version 1.1;
        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;
    }
}
# 记得替换 <example.com>

重启 Nginx.

如果需要对 80 进行转发则:

1
2
3
4
5
server {
    listen       80;     
    server_name  <example.com>;
    return       301 https://<example.com>;$request_uri;
}

为什么没有小绿锁?

有一个很好的网站可以帮你检查你的网站为什么没有小绿锁,输入网址就可以查看原因:为什么没有挂锁

使用 Chrome 浏览器的用户可以直接按 f12 然后选择 security 查看 https 显示不安全的原因。

通常 https 显示不安全的原因有:

  1. 没有对 80 端口进行转发到 https 的操作。

  2. 没有开启强制 HTTPS(或者说在 https 网站混合使用 http)。
    对于 discourse 我们要开启强制 https 转换:点击 Setting -> security -> force https 打上勾

自动更新

Let’s encrypt 的证书有效期只有 3 个月,所以需要定期更新。

更新代码如下:

1
$ certbot renew

你也可以添加定时任务,以下代码未经验证,感兴趣的话可以自行研究:

1
echo "0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null

最后

好了,点开你的网站,点击域名旁边的小挂锁,看到 连接是安全的 字样是不是很安心?