原文地址:https://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.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.comCongratulations! 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配置
参考官方链接:
https://docs.djangoproject.com/en/1.10/topics/security/#ssl-https
修改配置文件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!再也不用担心网站被劫持了。