现在新建网站基本全部都要配置 SSL ,可以通过服务器提供商提供的免费 SSL 进行部署,但是有一个缺点,就是有效期一般只有一年,需要每年重新申请,重新安装,之前一直用 Let’s Encrypt 进行部署,防止后面忘记了,写一个记录。
安装 acme.sh
curl https://get.acme.sh | sh
第一次可能会遇到
curl: (6) Couldn't resolve host 'get.acme.sh'
重试一下就可以了。
然后重新载入一下 .bashrc
source ~/.bashrc
之后就有了 acme.sh
的命令,可以直接运行。
申请签发 SSL 证书
acme.sh --issue -d www.your-app.com -w /home/www/your-app/current/public
上面这段过程将会往
/home/www/your-app/current/public
创建一个.well-known
的文件夹,同时 Let’s Encrypt 将会通过你要注册的域名去访问那个文件来确定权限,它可能会去访问 http://www.your-app.com/.well-known/ 这个路径。所以你需要确保
/home/www/your-app/current/public
是在 Nginx 上配置成 root 目录,里面任意文件可以直接域名访问的。
如果成功的话,你就会看到这样的结果:
[Fri Dec 23 11:20:15 CST 2016] Renew: 'www.your-app.com'
[Fri Dec 23 11:20:15 CST 2016] Single domain='www.your-app.com'
[Fri Dec 23 11:20:15 CST 2016] Getting domain auth token for each domain
[Fri Dec 23 11:20:15 CST 2016] Getting webroot for domain='www.your-app.com'
[Fri Dec 23 11:20:15 CST 2016] _w='/home/www/your-app/current/public/'
[Fri Dec 23 11:20:15 CST 2016] Getting new-authz for domain='www.your-app.com'
[Fri Dec 23 11:08:57 CST 2016] The new-authz request is ok.
[Fri Dec 23 11:08:57 CST 2016] Verifying:www.your-app.com
[Fri Dec 23 11:09:01 CST 2016] Success
[Fri Dec 23 11:09:01 CST 2016] Verify finished, start to sign.
[Fri Dec 23 11:09:02 CST 2016] Cert success.
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
[Fri Dec 23 11:09:02 CST 2016] Your cert is in /home/.acme.sh/www.your-app.com/www.your-app.com.cer
[Fri Dec 23 11:09:02 CST 2016] Your cert key is in /home/.acme.sh/www.your-app.com/www.your-app.com.key
[Fri Dec 23 11:09:04 CST 2016] The intermediate CA cert is in /home/.acme.sh/www.your-app.com/ca.cer
[Fri Dec 23 11:09:04 CST 2016] And the full chain certs is there: /home/.acme.sh/www.your-app.com/fullchain.cer
你的证书文件已经申请成功了,并放到了 ~/.acme.sh/
目录里面。
所有的 acme.sh 配置都记录在
~/.acme.sh/
目录里面,acme.sh 有自动的配置读取,并按域名划分,下次你再次执行的时候,它知道你之前是用的那个目录,只需要告诉它域名就好了。
将 SSL 证书安装到网站的路径,并配置好 restart Nginx 的动作
这个比较重要,因为它会让
acme.sh
记住重启 Nginx 的命令,以后自动更新证书的动作需要重启 Nginx
acme.sh --installcert -d www.your-app.com \
--keypath /home/www/ssl/www.your-app.com.key \
--fullchainpath /home/www/ssl/www.your-app.com.key.pem \
--reloadcmd "sudo service nginx force-reload"
然后你会看到结果
[Fri Dec 23 11:59:57 CST 2016] Installing key to:/home/www/ssl/www.your-app.com.key
[Fri Dec 23 11:59:57 CST 2016] Installing full chain to:/home/www/ssl/www.your-app.com.key.pem
[Fri Dec 23 11:59:57 CST 2016] Run Le_ReloadCmd: sudo service nginx force-reload
Restarting nginx: nginx.
[Fri Dec 23 11:59:58 CST 2016] Reload success
修改一下 sudoer 文件,让 sudo service nginx force-reload
不需要输入密码
sudo visudo
打开文件以后新增:
ubuntu ALL=(ALL) NOPASSWD: /usr/sbin/service nginx force-reload
ubuntu
是 acme.sh 安装所用的账号
生成 dhparam.pem 文件
openssl dhparam -out /home/www/ssl/dhparam.pem 2048
修改 Nginx 启用 SSL
http {
# 新增
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
# 兼容其他老浏览器的 ssl_ciphers 设置请访问 https://wiki.mozilla.org/Security/Server_Side_TLS
server {
listen 80 default_server;
# 新增
listen 443 ssl;
ssl_certificate /home/ubuntu/www/ssl/www.your-app.com.key.pem;
ssl_certificate_key /home/ubuntu/www/ssl/www.your-app.com.key;
# ssl_dhparam
ssl_dhparam /home/ubuntu/www/ssl/dhparam.pem;
# 其他省略
}
}
检查 Nginx 配置是否正确后重启
sudo service nginx configtest
sudo service nginx restart
后续维护
Let’s Encrypt 的证书有效期是 90 天的,你需要定期 renew
重新申请,这部分 acme.sh
以及帮你做了,在安装的时候往 crontab 增加了一行每天执行的命令 acme.sh --cron
:
$ crontab -l
0 0 * * * "/home/.acme.sh"/acme.sh --cron --home "/home/.acme.sh" > /dev/null
下面这段你可以尝试执行一下,看看是否正确
"/home/.acme.sh"/acme.sh --cron --home "/home/.acme.sh"
这样就是正常的:
[Fri Dec 23 11:50:30 CST 2016] Renew: 'www.your-app.com'
[Fri Dec 23 11:50:30 CST 2016] Skip, Next renewal time is: Tue Feb 21 03:20:54 UTC 2017
[Fri Dec 23 11:50:30 CST 2016] Add '--force' to force to renew.
[Fri Dec 23 11:50:30 CST 2016] Skipped www.your-app.com
acme.sh --cron
命令执行以后将会 申请新的证书 并放到相同的文件路径。由于前面执行 --installcert
的时候告知了重新 Nginx 的方法,acme.sh
也同时会在证书更新以后重启 Nginx。
最后走一下 acme.sh –cron 的流程看看能否正确执行
acme.sh --cron -f
这个过程应该会得到这样的结果,并在最后重启 Nginx (不需要输入密码)
[Tue Dec 27 14:28:09 CST 2016] Renew: 'www.your-app.com'
[Tue Dec 27 14:28:09 CST 2016] Single domain='www.your-app.com'
[Tue Dec 27 14:28:09 CST 2016] Getting domain auth token for each domain
[Tue Dec 27 14:28:09 CST 2016] Getting webroot for domain='www.your-app.com'
[Tue Dec 27 14:28:09 CST 2016] _w='/home/www/your-app/current/public/'
[Tue Dec 27 14:28:09 CST 2016] Getting new-authz for domain='www.your-app.com'
[Tue Dec 27 14:28:16 CST 2016] The new-authz request is ok.
[Tue Dec 27 14:28:16 CST 2016] www.your-app.com is already verified, skip.
[Tue Dec 27 14:28:16 CST 2016] www.your-app.com is already verified, skip http-01.
[Tue Dec 27 14:28:16 CST 2016] www.your-app.com is already verified, skip http-01.
[Tue Dec 27 14:28:16 CST 2016] Verify finished, start to sign.
[Tue Dec 27 14:28:19 CST 2016] Cert success.
... 省略
[Fri Dec 23 11:09:02 CST 2016] Your cert is in /home/.acme.sh/www.your-app.com/www.your-app.com.cer
[Fri Dec 23 11:09:02 CST 2016] Your cert key is in /home/.acme.sh/www.your-app.com/www.your-app.com.key
[Fri Dec 23 11:09:04 CST 2016] The intermediate CA cert is in /home/.acme.sh/www.your-app.com/ca.cer
[Fri Dec 23 11:09:04 CST 2016] And the full chain certs is there: /home/.acme.sh/www.your-app.com/fullchain.cer
[Tue Dec 27 14:28:22 CST 2016] Run Le_ReloadCmd: sudo service nginx force-reload
* Reloading nginx nginx [ OK ]
[Tue Dec 27 14:28:22 CST 2016] Reload success