在當今數字化時代,保障網站數據傳輸的安全性至關重要。HTTPS 協議通過使用 SSL/TLS 加密技術,能夠有效防止數據在傳輸過程中被竊取或篡改。本教程將詳細介紹如何在 Ubuntu 22.04 系統上,使用 Python 3.11 和 FastAPI 框架搭建一個帶有免費 SSL 證書的 HTTPS 服務器。
準備工作
在開始之前,你需要確保滿足以下條件:
- 擁有一臺運行 Ubuntu 22.04 的服務器。
- 具備一個有效的域名,并將其 DNS 解析指向你的服務器 IP 地址。因為 Let's Encrypt 不支持為 IP 地址頒發證書,所以域名是必需的。
- 服務器已經連接到互聯網,并且能夠正常訪問外部網絡。
步驟 1:安裝必要的軟件包?
首先,我們需要更新系統的軟件包列表,并安裝 Python 3.11、pip(Python 包管理工具)、Certbot(用于獲取免費 SSL 證書)和 Nginx(作為反向代理服務器)。?
# 更新系統軟件包列表
sudo apt update
# 安裝 Python 3.11 和 pip
sudo apt install python3.11 python3.11-venv python3-pip
# 安裝 Certbot 和 Nginx
sudo apt install certbot python3-certbot-nginx nginx
?解釋
sudo apt update
:該命令用于更新系統軟件包列表,確保我們能夠獲取到最新的軟件包信息。sudo apt install python3.11 python3.11-venv python3-pip
:安裝 Python 3.11 及其虛擬環境創建工具?venv
?和包管理工具?pip
。虛擬環境可以幫助我們隔離不同項目的依賴,避免版本沖突。sudo apt install certbot python3-certbot-nginx nginx
:安裝 Certbot 及其 Nginx 插件,用于獲取和管理 Let's Encrypt 免費 SSL 證書,同時安裝 Nginx 服務器。
步驟 2:創建 Python 虛擬環境并安裝 FastAPI
為了避免全局 Python 環境的污染,我們將創建一個虛擬環境,并在其中安裝 FastAPI 和 Uvicorn(一個用于運行 FastAPI 應用的 ASGI 服務器)。
?注意:也可以用conda來創建pyhton的虛擬環境。以下代碼用的python3的source來創建的建議虛擬環境,也夠用。
# 創建虛擬環境
python3.11 -m venv fastapi_env
# 激活虛擬環境
source fastapi_env/bin/activate
# 安裝 FastAPI 和 Uvicorn
pip install fastapi uvicorn
解釋
python3.11 -m venv fastapi_env
:使用 Python 3.11 的?venv
?模塊創建一個名為?fastapi_env
?的虛擬環境。source fastapi_env/bin/activate
:激活虛擬環境,激活后,我們在該終端中執行的所有 Python 命令都將使用該虛擬環境中的 Python 和相關包。pip install fastapi uvicorn
:在虛擬環境中安裝 FastAPI 和 Uvicorn。
步驟 3:編寫 FastAPI 應用
創建一個名為?main.py
?的 Python 文件,并編寫一個簡單的 FastAPI 應用。
from fastapi import FastAPIapp = FastAPI()@app.get("/")
def read_root():return {"..."}
?解釋
from fastapi import FastAPI
:導入 FastAPI 類。app = FastAPI()
:創建一個 FastAPI 應用實例。@app.get("/")
:定義一個 HTTP GET 請求處理函數,當用戶訪問根路徑?/
?時,將返回一個包含?{"..."}
?的 JSON 響應。
?步驟 4:配置 Nginx 作為反向代理
Nginx 可以作為反向代理服務器,將客戶端的請求轉發到我們的 FastAPI 應用。
?4.1 創建 Nginx 配置文件
創建一個新的 Nginx 配置文件?/etc/nginx/sites-available/fastapi_app
。
sudo nano /etc/nginx/sites-available/fastapi_app
在文件中添加以下內容:?
server {listen 80;server_name your_domain; # 替換為你的實際域名location / {proxy_pass http://127.0.0.1:8000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
解釋
listen 80;
:指定 Nginx 監聽 HTTP 端口 80。server_name your_domain;
:指定服務器的域名,需要將?your_domain
?替換為你自己的域名。proxy_pass http://127.0.0.1:8000;
:將客戶端的請求轉發到本地的 8000 端口,即我們的 FastAPI 應用運行的端口。proxy_set_header
:設置一些代理請求頭,確保 FastAPI 應用能夠獲取到客戶端的真實信息。
4.2 創建符號鏈接并測試配置
將配置文件鏈接到?sites-enabled
?目錄,并測試 Nginx 配置是否正確。
# 創建符號鏈接到 sites-enabled 目錄
sudo ln -s /etc/nginx/sites-available/fastapi_app /etc/nginx/sites-enabled/
# 測試 Nginx 配置
sudo nginx -t
# 重啟 Nginx 服務
sudo systemctl restart nginx
?步驟 5:獲取免費 SSL 證書
使用 Certbot 工具獲取 Let's Encrypt 免費 SSL 證書。
sudo certbot --nginx -d your_domain # 替換為你的實際域名
多個域名時,申請方法如下:?
sudo certbot --nginx -d your_domain.com -d www.your_domain.com
詳細提示和輸入說明
5.1 郵箱地址輸入
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):
Let's Encrypt 需要一個有效的郵箱地址,用于在證書即將到期或有安全通知時聯系你。輸入你的常用郵箱地址,然后按回車鍵。
5.2 協議條款確認
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:
你需要同意 Let's Encrypt 的服務條款才能繼續注冊并獲取證書。輸入?Y
?然后按回車鍵表示同意。
5.3 訂閱郵件選項
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:
?這是一個可選的訂閱選項,詢問你是否愿意與電子前沿基金會(EFF)共享你的郵箱地址,以便接收他們的相關新聞和活動信息。如果你愿意接收相關郵件,輸入?Y
?并回車;如果不愿意,輸入?N
?并回車。
5.4 域名驗證與證書安裝確認
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for your_domain
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/fastapi_appPlease 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):
?Certbot 會驗證你的域名所有權,并在驗證通過后部署證書。這里會詢問你是否要將所有 HTTP 請求重定向到 HTTPS。
- 如果你希望將所有 HTTP 請求重定向到 HTTPS,輸入?
2
?并回車。 - 如果你暫時不想進行重定向,輸入?
1
?并回車。
5.5 完成提示
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Account registered.
Requesting a certificate for ftpeak.comSuccessfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/ftpeak.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/ftpeak.com/privkey.pem
This certificate expires on 2025-06-15.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.Deploying certificate
Successfully deployed certificate for ftpeak.com to /etc/nginx/sites-enabled/fastapi_app
Congratulations! You have successfully enabled HTTPS on https://ftpeak.com- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
這表示證書已經成功獲取并安裝,同時會顯示證書和私鑰的保存路徑以及證書的到期日期等重要信息。
步驟 6:在配置中增加SSL
6.1 編輯配置文件
打開配置文件進入編輯狀態:
sudo nano /etc/nginx/sites-available/fastapi_app
?代碼修改如下:
# HTTP 服務器塊,用于將所有 HTTP 請求重定向到 HTTPS
server {listen 80;server_name ftpeak.com;# 永久重定向 HTTP 請求到 HTTPSreturn 301 https://$host$request_uri;
}# HTTPS 服務器塊,處理實際的 HTTPS 請求
server {listen 443 ssl;server_name ftpeak.com;# SSL 證書和私鑰配置ssl_certificate /etc/letsencrypt/live/ftpeak.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/ftpeak.com/privkey.pem;# 包含 Certbot 提供的 SSL 配置選項include /etc/letsencrypt/options-ssl-nginx.conf;# SSL Diffie-Hellman 參數配置ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;# 反向代理配置,將請求轉發到本地的 FastAPI 應用location / {proxy_pass http://127.0.0.1:8000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
6.1 啟動 FastAPI 應用
在激活的虛擬環境中啟動 FastAPI 應用。
uvicorn main:app --host 127.0.0.1 --port 8000
解釋
uvicorn main:app
:指定要運行的 FastAPI 應用,main
?是 Python 文件名,app
?是 FastAPI 應用實例的名稱。--host 127.0.0.1
:指定應用監聽的 IP 地址為本地回環地址。--port 8000
:指定應用監聽的端口為 8000。
步驟 7:驗證 HTTPS 訪問
現在,你可以通過瀏覽器訪問?https://your_domain
(替換為你的實際域名)來驗證 HTTPS 服務器是否正常工作。如果一切正常,你應該能看到?{"..."}
?的響應。
注意事項
- 確保服務器的防火墻允許 HTTP(端口 80)和 HTTPS(端口 443)流量。可以使用以下命令開放端口:?
sudo ufw allow 80
sudo ufw allow 443
sudo ufw allow 443
步驟8:自動更新證書
自動更新測試
Let's Encrypt 證書的有效期為 90 天,為了避免證書過期導致服務中斷,建議設置定期自動更新證書。可以使用以下命令測試自動更新:
sudo certbot renew --dry-run
測試結果如果通過如下:
Saving debug log to /var/log/letsencrypt/letsencrypt.log- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/ftpeak.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Account registered.
Simulating renewal of an existing certificate for ftpeak.com- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/ftpeak.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
可以使用系統的定時任務(如?crontab -e
)來定期執行?certbot renew
?命令。
crontab -e
?如果你是第一次使用該命令,系統可能會提示你選擇一個文本編輯器,你可以根據自己的喜好選擇,例如選擇?nano
?編輯器,輸入對應的數字并回車即可。
添加定時任務
在打開的?crontab
?文件中,添加如下一行內容:
0 2 * * 1 /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"
代碼解釋
-
時間設置部分(
0 2 * * 1
):0
?表示分鐘,即每小時的第 0 分鐘(整點)。2
?表示小時,即凌晨 2 點。*
?表示任意值,這里前兩個?*
?分別表示每月的任意天和每年的任意月。1
?表示星期,即星期一。
綜合起來,
0 2 * * 1
?表示每周一凌晨 2 點執行該任務。你可以根據自己的需求調整時間,例如你也可以設置為每月執行一次,將時間設置為?0 2 1 * *
?,表示每月 1 號凌晨 2 點執行。 -
命令部分(
/usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"
):/usr/bin/certbot renew
:這是執行 Certbot 證書更新的命令。--quiet
:表示以安靜模式運行,避免在更新過程中輸出過多的信息,減少不必要的干擾。--deploy-hook "systemctl reload nginx"
:這是一個部署鉤子選項,當 Certbot 成功更新證書后,會執行雙引號內的命令。這里的?systemctl reload nginx
?表示重新加載 Nginx 服務,使新的證書配置生效。
保存并退出
在?nano
?編輯器中,按下?Ctrl + X
?組合鍵,然后輸入?Y
?確認保存修改,最后按下回車鍵退出編輯器。?
列出你設置的定時任務
你可以使用以下命令查看當前用戶的?crontab
?任務列表,確認剛才添加的任務是否已經正確保存:
crontab -l
如果輸出中包含你添加的定時任務,說明配置成功。之后,系統會按照你設置的時間定期執行證書更新操作。
注意事項
- 確保?
certbot
?命令的路徑?/usr/bin/certbot
?是正確的。你可以使用?which certbot
?命令來確認其實際路徑。 - 在使用?
systemctl reload nginx
?之前,要確保當前用戶有足夠的權限來執行該命令。如果遇到權限問題,可能需要調整?sudo
?配置或使用其他方式來重新加載 Nginx 服務。