部署 使用 acme.sh 給 Nginx 安裝 Let’ s Encrypt 提供的免費 SSL 證書

最近 Apple 在強推 SSL 了,非 SSL 的網絡請求沒法經過審覈,因而發現有好多的朋友都在給網站配置 HTTPS,同時他們也遇到了好多坑。html

其實有更簡單的方式,使用 Let’ s Encrypt,關於這個,這裏就很少講了,以前有人介紹過:nginx

以及前面還有一篇介紹用 Let's Encrypt 官方教程裏面的工具安裝的文章: https://ruby-china.org/topics/31942git

我這裏要介紹的是另一個 acme.sh 這個是用 Shell 腳本編寫的,安裝更容易,Let's Encrypt 那個 certbot 工具須要安裝一大堆系統庫以及 Python 庫,Python 的 pip 在國內還會有牆的問題...github

安裝 acme.sh

curl https://get.acme.sh | sh

PS: 第一次可能會遇到 curl: (6) Couldn't resolve host 'get.acme.sh' 重試一下就能夠了。web

而後從新載入一下 .bashrcubuntu

source ~/.bashrc

如今你就有了 acme.sh 的命令.瀏覽器

申請簽發 SSL 證書

acme.sh --issue -d www.your-app.com -w /home/ubuntu/www/your-app/current/public

NOTE! 上面這段過程將會往 /home/ubuntu/www/your-app/current/public 建立一個 .well-known 的文件夾,同時 Let’ s Encrypt 將會經過你要註冊的域名去訪問那個文件來肯定權限,它可能會去訪問 http://www.your-app.com/.well-known/ 這個路徑。ruby

 

因此你須要確保 /home/ubuntu/www/your-app/current/public 是在 Nginx 上配置成 root 目錄,裏面任意文件能夠直接域名訪問的。bash

若是成功的話,你就會看到這樣的結果:網絡

[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/ubuntu/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/ubuntu/.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/ubuntu/.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/ubuntu/.acme.sh/www.your-app.com/ca.cer 
[Fri Dec 23 11:09:04 CST 2016] And the full chain certs is there:  /home/ubuntu/.acme.sh/www.your-app.com/fullchain.cer

你的證書文件已經申請成功了,並放到了 ~/.acme.sh/ 目錄裏面。

TIP: 全部的 acme.sh 配置都記錄在 ~/.acme.sh/ 目錄裏面,acme.sh 有自動的配置讀取,並按域名劃分,下次你再次執行的時候,它知道你以前是用的那個目錄,只須要告訴它域名就行了。

將 SSL 證書安裝到網站的路徑,並配置好 restart Nginx 的動做

NOTE: 這個比較重要,由於它會讓 acme.sh 記住重啓 Nginx 的命令,之後自動更新證書的動做須要重啓 Nginx

acme.sh --installcert -d www.your-app.com \
               --keypath       /home/ubuntu/www/ssl/www.your-app.com.key  \
               --fullchainpath /home/ubuntu/www/ssl/www.your-app.com.key.pem \
               --reloadcmd     "sudo service nginx reload"

而後你會看到結果

[Fri Dec 23 11:59:57 CST 2016] Installing key to:/home/ubuntu/www/ssl/www.your-app.com.key
[Fri Dec 23 11:59:57 CST 2016] Installing full chain to:/home/ubuntu/www/ssl/www.your-app.com.key.pem
[Fri Dec 23 11:59:57 CST 2016] Run Le_ReloadCmd: sudo service nginx reload
Restarting nginx: nginx.
[Fri Dec 23 11:59:58 CST 2016] Reload success

修改一下 sudoer 文件,讓 sudo service nginx reload 不須要輸入密碼

sudo visudo

打開文件之後新增:

NOTE: ubuntu 是 acme.sh 安裝所用的帳號

ubuntu  ALL=(ALL) NOPASSWD: /usr/sbin/service nginx reload

生成 dhparam.pem 文件

openssl dhparam -out /home/ubuntu/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

驗證 SSL

訪問 ssllabs.com 輸入你的域名,檢查 SSL 的配置是否都正常:

https://ssllabs.com/ssltest/analyze.html?d=ruby-china.org

確保驗證結果有 A 以上,不然根據提示調整問題

 

後續維護

Let's Encrypt 的證書有效期是 90 天的,你須要按期 renew 從新申請,這部分 acme.sh 以及幫你作了,在安裝的時候往 crontab 增長了一行天天執行的命令 acme.sh --cron:

$ crontab -l
0 0 * * * "/home/ubuntu/.acme.sh"/acme.sh --cron --home "/home/ubuntu/.acme.sh" > /dev/null

PS: 下面這段你能夠嘗試執行一下,看看是否正確

"/home/ubuntu/.acme.sh"/acme.sh --cron --home "/home/ubuntu/.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/ubuntu/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/ubuntu/.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/ubuntu/.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/ubuntu/.acme.sh/www.your-app.com/ca.cer 
[Fri Dec 23 11:09:04 CST 2016] And the full chain certs is there:  /home/ubuntu/.acme.sh/www.your-app.com/fullchain.cer 
[Tue Dec 27 14:28:22 CST 2016] Run Le_ReloadCmd: sudo service nginx reload
 * Reloading nginx nginx                                                                                                                                     [ OK ] 
[Tue Dec 27 14:28:22 CST 2016] Reload success

一些注意事項

  • ssl_dhparam 未配置,將致使 ssllabs.com 的評分降到 B,並給 This server supports weak Diffie-Hellman (DH) key exchange parameters. Grade capped to B. 的警告。
  • ssl_prefer_server_ciphers on 也是一個必要的配置,不然會 A+ 變成 A-;
  • 若是你須要兼容老系統或老瀏覽器的話,你須要配置 ssl_ciphers,詳見 Mozilla Server_Side_TLS 的介紹,Nginx 裏面 ssl_ciphers 默認值是 HIGH:!aNULL:!MD5; ref
相關文章
相關標籤/搜索