Django部署HTTPS

ACool發表於2018-06-19

原文地址:blogof33.com/post/10/

前言

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.comwww.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.comwww.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
複製程式碼

至此配置完成。記得重新整理一下瀏覽器快取哦

7ldBu.png

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!再也不用擔心網站被劫持了。

相關文章