前言
Chrome 新版本已經會自動跳轉 HTTPS 了,ACool 一直想著沒有 HTTPS 的部落格網站不是很完美,但是礙於平時比較忙,難以抽出時間來折騰。今天終於有空,完成了 HTTPS 在 Django 上面的部署。網上關於 Django 框架下 HTTPS 部署的文章很少,故此記錄一下部署過程。
配置環境:
- django >= 1.8
- nginx
Let's Encrypt 是一個免費的,自動的,開放的認證機構(CA),為公眾的利益而執行。它是由網際網路安全研究組(ISRG)提供的一項服務。本文使用 Let's Encrypt 提供的免費 SSL 證書。
因為手動獲取和維護證書特別麻煩,所以我們採用自動客戶端 Cettbot 部署 SSL 證書。下面是官方介紹:
Certbot是 EFF 為了加密整個網際網路而做的一部分努力。Web上的安全通訊依賴於HTTPS,它需要使用數字證書來讓瀏覽器驗證Web伺服器的身份(例如,是否真的是 google.com ?)。Web 伺服器從名為證書頒發機構(CA)的可信第三方獲取證書。Certbot 是一個易於使用的客戶端,可從 Let's Encrypt(由 EFF,Mozilla 和其他人啟動的開放式證書頒發機構)獲取證書,並將其部署到Web伺服器。
採用以上組合 ( Let's Encrypt + Certbot )方式簡單,方便,快捷。
獲取 SSL 證書
預先工作
在建立證書之前,我們需要確保 Web 伺服器可以在根目錄下的該路徑下提供靜態檔案:/.well-know
。由於django 應用程式引入的所有路徑都通過 wsgi 提供服務,因此我們需要編寫nginx 配置以便於靜態地提供這些資源:將以下內容新增到域名的 nginx 配置檔案中:
server {
location /.well-known/acme-challenge {
alias /path/to/yoursite/.well-known/acme-challenge;
}
}
複製程式碼
請根據自己的情況修改 /path/to/yoursite/
欄位,比如 改成/home/User/Blogof33.com
,這個路徑便是 Django app 的絕對路徑,即 manage.py
檔案所在目錄。
下載Certbot
從 github 上面下載原始碼,可以不用管 Linux 伺服器發行版的區別:
git clone https://github.com/certbot/certbot.git
複製程式碼
生成證書
因為我們是 nginx 而不是 Apache,所以使用 webroot
選項獲取證書:
certbot certonly --webroot -w /path/to/yoursite -d blogof33.com -d www.blogof33.com
複製程式碼
請修改 /path/to/yoursite
欄位,和上面預先工作的修改一樣,然後後面的 blogof33.com
和 www.blogof33.com
請修改成自己的域名,如果現在的域名不能加 www 訪問的話(即沒有提供 WWW 的解析),請去掉最後這條欄位。
這條命令成功的輸出類似於這樣(有Congratulations):
Output: IMPORTANT NOTES:
If you lose your account credentials, you can recover through e-mails sent to sammy@digitalocean.com
Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will expire on 2018-08-31. To obtain a new version of the certificate in the future, simply run Let's Encrypt again.
Your account credentials have been saved in your Let's Encrypt configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Let's Encrypt so making regular backups of this folder is ideal.
If like Let's Encrypt, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
上述命令會為blogof33.com
和www.blogof33.com
生成一個單獨的證書。證書儲存於 /etc/letsencrypt/live/blogof33.com/fullchain.pem
.
Django配置
參考官方連結:
docs.djangoproject.com/en/1.10/top…
修改配置檔案setting.py
,將以下行加入進去:
SESSION_COOKIE_SECURE=True
SESSION_COOKIE_HTTPONLY=True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
複製程式碼
注意:對於執行 django <1.8 的應用程式,您應該安裝並配置 django-secure 。
Nginx配置
最後一步便是配置 nginx,配置檔案位於 /etc/nginx/sites-available/blogof33.com
, 配置與說明如下:
server {
charset utf-8;
listen 80;
server_name www.blogof33.com blogof33.com;
return 301 https://blogof33.com$request_uri;
}
server {
listen 443 default ssl;
server_name blogof33.com;
ssl_certificate /etc/letsencrypt/live/blogof33.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/blogof33.com/privkey.pem;
error_log /var/log/nginx/error.log;
location /.well-known/acme-challenge {
alias /home/ACool/sites/blogof33.com/DjangoBlog/.well-known/acme-challenge;
}
location /static {
alias /home/ACool/sites/blogof33.com/DjangoBlog/static;
}
location / {
proxy_set_header Host $host;
proxy_pass http://unix:/tmp/blogof33.com.socket;
}
}
複製程式碼
其中 ,第一段 Server 程式碼:
server {
charset utf-8;
listen 80;
server_name www.blogof33.com blogof33.com;
return 301 https://blogof33.com$request_uri;
}
複製程式碼
含義為將所有 HTTP 流量重定向到 HTTPS,我們只需要根據自己域名修改其中域名,其他部分不變。
這一行是用來監聽 443 埠( HTTPS 埠號):
listen 443 default ssl;
複製程式碼
這兩行則是指向證書和金鑰(域名替換成自己的):
ssl_certificate /etc/letsencrypt/live/blogof33.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/blogof33.com/privkey.pem;
複製程式碼
這一行是用來建立證書的:
location /.well-known/acme-challenge {
alias /home/ACool/sites/blogof33.com/DjangoBlog/.well-known/acme-challenge;
}
複製程式碼
修改 nginx 配置以後,重新載入一下:
sudo nginx -s reload
複製程式碼
至此配置完成。記得重新整理一下瀏覽器快取哦 。
Let’s Encrypt 自動續期
Let’s Encrypt 的證書90天就過期了,所以,我們還需要設定自動化更新指令碼,最容易的莫過於使用 crontab
了。使用 crontab -e
命令加入如下的定時作業(每週都強制更新一下,如果需要 root 許可權,需要切換到 root 下執行):
45 2 * * 2 cd /etc/letsencrypt/ && ./certbot-auto renew --deploy-hook "service nginx reload"
複製程式碼
crontab 六個欄位含義:
minute hour day month week command
其中:
- minute: 表示分鐘,(整數 0 -59)。
- hour:表示小時,可以是從0到23之間的任何整數。
- day:表示日期,可以是從1到31之間的任何整數。
- month:表示月份,可以是從1到12之間的任何整數。
- week:表示星期幾,可以是從0到7之間的任何整數,這裡的0或7代表星期日。
- command:要執行的命令,可以是系統命令,也可以是自己編寫的指令碼檔案。
如果欄位使用 * 號,如 month 欄位為 * 號,則為滿足其他欄位約束的每月都執行該命令。
這裡是每週 2 的 2 點 45 分嘗試更新證書,如果證書在 30 天內到期,則會更新證書,否則不會更新, --deploy-hook
選項表示在更新成功以後才執行過載 nginx 的命令。
至此,在 Django 框架下部署 HTTPS 全部完成。
Welcome to the https world!再也不用擔心網站被劫持了。