0%

[SSL] Nginx + Let's encrypt SSL 憑證

https

我們可以透過以下兩個網站申請免費的 SSL 憑證:

  • Let′s encrypt: 是一個提供免費 SSL 服務的網站,可以手動申請 SSL 憑證,也可以串接它的 API,讓申請憑證的流程自動化,詳細的內容可以參考官方網站
  • CloudFlare: 主要提供 CDN 的服務,多了一層的代理,可以保護網站受到攻擊,同時也能提升網站效能,另外 CloudFlare 也有提供免費的 SSL 服務。

前置作業

在申請 SSL 憑證之前,需要先有自己的 domain,如果是使用 Heroku 的話,他預設有提供免費的 domain: <app_name>.herokuapp.com,如果服務是在其他地方的話,網路上也有很多地方有提供免費申請網域的網站(例如: freenomNo-IP),或是也可以付費購買自己喜歡的 domain.

不過要注意的是:如果是想要申請 CloudFlare 的 SSL 憑證,domain 不能是以下幾個:

  • example.tumblr.com
  • example.appspot.com
  • example.wordpress.com
  • example.weebly.com
  • example.herokuapp.com
  • example.webs.com
  • example.blogspot.com
  • example.webs.com
  • example.ning.com
  • example.no-ip.com

詳細的說明可以參考: What does “ERROR Unfortunately, you can not add that domain to Cloudflare” mean?

這裡就預設我們已經有自己的 domain 了,接下來主要記錄如何申請 Let′s encrypt 的 SSL 憑證並搭配 Nginx 做設定。

我們的執行環境是 Ubuntu 16.04,搭配 Nginx 做設定,如果是要搭配 Apache 或是其他 Web server,取得憑證的步驟會不太一樣,可以參考官方網站.

安裝 Nginx

首先,需要先安裝 Nginx,可以選擇使用 apt-get 來安裝,或是自行編譯:

使用 apt-get 安裝

1
2
sudo apt-get update
sudo apt-get install -y nginx

啟動 Nginx:

1
sudo nginx -c /etc/nginx/nginx.conf

自行編譯 Nginx

下載 Nginx:

1
2
wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar zxf nginx-1.18.0.tar.gz

安裝 with-http_ssl_module 所需要的 OpenSSL Library:

1
sudo apt-get install -y openssl openssl-devel

加上 SSL Module:

1
2
3
4
5
6
7
8
# 進入 NGINX 原始碼目錄
cd nginx-1.18.0

# 設定要添加的 module
./configure --prefix=/home/<user>/nginx --with-http_ssl_module

# 開始編譯
make && make install

啟動 Nginx:

1
home/<user>/nginx/sbin/nginx -c home/<user>/nginx/nginx.conf

安裝 certbot

1
2
3
sudo add-apt-repository ppa:certbot/certbot   # 載入 certbot 的 ppa
sudo apt-get update # 更新 apt-get
sudo apt-get install -y python-certbot-nginx # 安裝 python 的 certbot for nginx

設定 Nginx

1
2
3
4
5
6
7
# file: /etc/nginx/nginx.conf

http {
# ...

include /etc/nginx/sites-enabled/*;
}
1
2
3
4
5
6
# file: /etc/nginx/sites-available/web-ssl.conf

server {
server_name mydomain.com;
# ...
}

Create link to /etc/nginx/sites-available/web-ssl.conf:

1
2
cd /etc/nginx/sites-enabled
sudo ln -s ../sites-available/web-ssl.conf .

Reload Nginx:

1
sudo nginx -s reload

申請 Let′s encrypt SSL 憑證

以上前置作業都完成後,就可以來申請憑證:

1
sudo certbot --nginx -d mydomain.com

接著可以選擇要不要自動轉址:

1
2
3
4
5
6
7
8
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 自動轉 https 可以選 2.

最後出現以下訊息就是完成了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://mydomain.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=mydomain.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/mydomain.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/mydomain.com/privkey.pem
Your cert will expire on 2021-06-30. 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"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

檢查 config 是否有被自動添加內容

檢查 Nginx config 是否有被自動增加 listen 443 及憑證:

1
2
3
4
5
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

如果申請憑證時有選擇自動轉址,再檢查以下內容是否有被設定:

1
2
3
4
5
6
if ($host = mydomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name mydomain.com;
return 404; # managed by Certbot

如果沒有選擇自動轉址,也可以自行設定:

1
2
3
4
5
6
7
# file: /etc/nginx/site-available/default-http-to-https.conf

server {
listen 80;
server_name mydomain.com;
return 301 https://$host$request_uri;
}

重啟 Nginx

確認完後,只要再重啟 Nginx, 就可以囉!

1
2
sudo nginx -s stop
sudo nginx -c /etc/nginx/nginx.conf

最後就可以測試看看 https://mydomain.com 是否可以使用~

更新憑證

要注意的是,Let’s encrypt 憑證的有效期限只有 90 天,可以使用以下指令更新憑證:

1
2
3
4
5
# --dry-run: For testing
sudo certbot renew --nginx [--dry-run]

# 過期的話, 要使用以下指令來強制更新已過期的憑證
sudo certbot --nginx --force-renew

也可以透過排程設定自動更新憑證:

1
sudo crontab -e

加上以下內容即可:

1
2
3
4
SHELL=/bin/sh
PATH=/bin:/sbin:/usr/bin:/usr/sbin

@daily /usr/bin/certbot renew --nginx --quiet

參考資料