約三個月前幫這個部落格加上了 https,用免費的 Let's Encrypt CA (Certicate Authority)。Let's Encrypt 雖然免費,但效期只有 90 天,因此每三個月必須更新憑證,

我原本是用 SSL For Free 這個網站來申請和更新憑證,但後來發現 Let's Encrypt 的 client — certbot 相當好用,也會自動幫你更新憑證。

前提

  • 我是使用 Ubuntu v16.04 擁有 sudo 的權限,並安裝 nginx。
  • 擁有該網域。
  • 設定好正確的 DNS record,比如你要幫 www.hellojcc.twhellojcc.tw 加上 https,就必須先把 DNS 設定到對應的 IP,因為 Let's Encrypt 在發憑證前會先來 challenge 這兩個網域。

安裝 certbot

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot # 載入 certbot 的 ppa
sudo apt-get update # 更新 apt-get
sudo apt-get install python-certbot-nginx # 安裝 python 的 certbot for nginx

設定 http server

certbot 在申請完憑證之後,會自動幫你修改 nginx 的設定,前提是你的 nginx 原本就要有該網域的相關設定。certbot 會去找 nginx 設定中 server block 裡 server_name directive 相符的設定去作修改。e.g:

server {
    # server_name 和產生的憑證網域相符,certbot 會把設定加在這個 block 裡
    server_name hellojcc.tw, www.hellojcc.tw
}

產生憑證

目前 certbot 在 Ubuntu 上面還不支援 wildcard 的方式,因此必須把子網域都透過 -d 加上去

sudo certbot --nginx -d hellojcc.tw -d www.hellojcc.tw

如果這是你第一次執行 certbot 的話,它會請你同意使用者條款和輸入 email 地址,方便寄信聯絡。

接著會讓你選需不需要作 https 轉址的設定:

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

如果你還沒設定 http redirect 到 https 的話就選 2。

看到下面這個訊息就是完成了。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/hellojcc.tw/fullchain.pem. Your cert will
   expire on 2018-08-01. To obtain a new or tweaked version of this
   certificate in the future, simply run certbot again with the
   "certonly" option. To non-interactively renew *all* of your
   certificates, run "certbot renew"

certbot 會自動 reload nginx,你可以去 SSL Server Test 是測試你的網站,分數應該會是 A。

ps. 如果你希望 certbot 不要動你的 nginx 設定,只要去取得憑證,請加上 certonly 參數。

nginx 設定說明

certbot 會在對應的 server block 加上下面的設定:

server {
    # ... other configs
    
    # SSL setting
    listen 443 ssl;

    # set crt and key
    ssl_certificate /etc/letsencrypt/live/hellojcc.tw/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hellojcc.tw/privkey.pem;
    # include 基本的 ssl 設定
    include /etc/letsencrypt/options-ssl-nginx.conf;
    # certbot 也會產生一把 Diffie-Hellman 密鑰
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # ... other configs
}

自動更新憑證

certbot 還會自動起一個 cronjob,每個禮拜會去確認憑證狀態,如果效期低於一個月就會自動更新憑證,可輸入 systemctl list-timers 作確認。
systemctl timer

接著可以輸入下列指令 dry run 一下,確認更新憑證沒有問題。

sudo certbot renew --dry-run

(2020/3/15 更新)
跑 dryrun 如果出現

Attempting to renew cert (your_domain.com) from /etc/letsencrypt/renewal/your_domain.com.conf produced an unexpected error: urn:ietf:params:acme:error:malformed :: The request message was malformed :: Method not allowed. Skipping.

你可以 (參考)

# 確認 python 是 v3 以上
python --version 
# 如果還是 v2 輸入指令更新
update-alternatives --install /usr/bin/python python /usr/bin/python3.5 1 
# 更新 python3-acme
apt update && apt install --only-upgrade python3-acme

另外 certbot 的 log 預設路徑在 /var/log/letsencrypt,有需要可以去確認。

確認憑證狀態

(2019/5/13 更新)
有時候會收到 letsencrypt 寄來的「憑證即將到期通知 Let's Encrypt certificate expiration notice for domain "your_domain.com"」。這時候可以輸入下面的指令確認狀態。

sudo certbot certificates