AWS EC2 上使用 Nginx + Let’s Encrypt 部署 Flask 應用程式

Cosine Chen
8 min readMay 12, 2023

啟動 AWS EC2 執行個體

可以參考 Django 部署 (ㄧ):啟動 AWS EC2 執行個體 文章中申請步驟進行 AWS EC2 的設置與啟用。

建立的 AWS EC2 IP 位址如下:(以下範例將會以此 EC2 執行個體為例)
Public IPv4 Address: 54.169.24.192
Private IPv4 Address: 172.31.42.195

部署 Flask 應用程式

首先,先建立一個 Flask App,並將服務運行於 ‘0.0.0.0’,指定阜為 5000。

@app.route('/hello')
def hello():
return 'Hello, World!'

if __name__ = "__main__":
app.run(host='0.0.0.0', port=5000)

啟動後終端機畫面如下:

將 Flask 應用程式啟動在 ‘0.0.0.0’ 與 5000

小知識:
host 參數用於指定 Flask 應用程式綁定的 IP 位址。預設值為 127.0.0.1,表示只能從本機訪問該應用程式。如果將 host 設置為 0.0.0.0,則表示該應用程式將會綁定到本機的所有網路介面,即可以從本機的任何 IP 位址訪問該應用程式。

新增 AWS EC2 安全規則

啟動 Flask 應用程式後,要將指定阜 5000 新增至 AWS EC2 安全規則中,才可以透過對外 IP 與指定 Port 訪問該應用程式。(設定方法可以參考 Django 部署 (二):AWS EC2 上部署 Django 專案

設定完成後,打開網址 http://54.169.24.192/hello 即可訪問該應用程式。

使用 Nginx + Let’s Encrypt 配置 HTTPS

設置 Nginx 反向代理

首先,先安裝 Nginx 套件。

$ sudo apt-get install nginx

打開網址 http://54.169.24.192 看到預設畫面如下,表示 Nginx 服務已經成功安裝並且順利運行。

Nginx 服務伺服器預設畫面

接著,新增一個 Nginx 配置文件 /etc/nginx/sites-available/flask 。其中 server_nameyour_domain.com 要換成你要使用的對外 IP 位址或是域名

server {
listen 80;
listen [::]:80;
server_name your_domain.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

將此配置文件鏈接到 /etc/nginx/sites-enabled 目錄中。

$ sudo ln -s /etc/nginx/sites-available/flask /etc/nginx/sites-enabled/

重新啟動 Nginx 服務。

$ sudo systemctl restart nginx

打開 http://your_domain/hello 可以訪問應用程式即代表成功配置。

使用 Let’s Encrypt 申請免費 SSL/TLS 憑證

使用 Let’s Encrypt 提供的 Certbot 工具來生成 SSL/TLS 證書。首先,先安裝 Certbot 與他的 Nginx 插件。

$ sudo apt-get install certbot python3-certbot-nginx

使用 Certbot 生成 SSL/TLS 證書。

$ sudo certbot --nginx -d your_domain.com -d www.your_domain.com

依照 Certbot 指示輸入 Email 並同意服務條款,申請成功會顯示訊息如下:

成功申請 SSL/TLS 憑證

Certbot Nginx 插件會更新你的 Nginx 配置。打開 /etc/nginx/sites-available/flask 查看更新的配置文件,可以看到新增的 SSL/TLS 相關配置項:

server {
listen 443 ssl;
listen [::]:443 ssl ipv6only=on;
server_name your_domain.com;

ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
listen [::]:80;
server_name your_domain.com;

if ($host = your_domain.com) {
return 301 https://$host$request_uri;
}

return 404;
}

打開 https://your_domain.com/hello 可以訪問網站,即代表成功使用 Nginx 代理並擁有合法的 SSL 憑證。這樣就完成了!

HTTPS 安全加密網址

如果想要檢視憑證內容,可以點擊網址列的鎖頭查看憑證的詳細內容。

SSL/TLS 憑證內容

自動更新 SSL/TLS 憑證

Let’s Encrypt 憑證的有效期限為90天(3個月),為了確保憑證處於最新狀態,可以使用 Certbot 工具自動更新憑證。

如果使用 Certbot 自動生成的 Nginx 配置文件,自動更新憑證的設定已經完成。自動更新的設定檔在 /etc/letsencrypt/renewal/your_domain.conf

# renew_before_expiry = 30 days
version = 1.21.0
archive_dir = /etc/letsencrypt/archive/your_domain.com
cert = /etc/letsencrypt/live/your_domain.com/cert.pem
privkey = /etc/letsencrypt/live/your_domain.com/privkey.pem
chain = /etc/letsencrypt/live/your_domain.com/chain.pem
fullchain = /etc/letsencrypt/live/your_domain.com/fullchain.pem

# Options used in the renewal process
[renewalparams]
account = deecea7de532e64c032ba93f998cd4fe
authenticator = nginx
installer = nginx
server = https://acme-v02.api.letsencrypt.org/directory

如果沒有使用自動生成的 Nginx 配置文件,請手動設定自動更新的指令。可以先使用以下命令進行更新測試:

$ sudo certbot renew --dry-run

如果測試成功,可以使用 cron 設置一個 crontab 任務來自動執行更新指令。

$ sudo crontab -e

打開文件中添加以下指令:

# m h dom mon dow command
0 0 * * 0 certbot renew --quiet --no-self-upgrade --post-hook "systemctl reload nginx"

這個設定表示每週日午夜12點,Certbot 會自動檢查憑證是否需要更新,如果需要更新就會自動更新憑證,並在更新後自動載入 Nginx 設定。(Certbot 只會在憑證到期前一個月才會進行更新)

這樣就完成 Let’s Encrypt 的自動更新憑證設定了。

--

--

Cosine Chen

Hi 我是 Cosine。我是正在前往前後端之路的菜鳥工程師,不擅長寫文章,只是隨筆紀錄自己的學習歷程。因為不喜歡看太多字的文章,也無法一次吸收太多的內容,每篇的內容都不會太長,偏向實作性質,如果你也是正在學習的 Coding 人,希望這些筆記也能夠幫助到你。如果分享的內容有誤的話,也歡迎留言指正,或直接與我聯繫!