使用Nginx+uWSGI+SSL(Let’s Encrypt)将OCI上的Django应用程序发布出来
首先
Django + Nginx + uWSGI + SSL的设置也许已经被重复了好几次,但是实际尝试过程中我遇到了一些问题,所以我写了本文章作为备忘录(因此,省略了OCI和Django设置没有问题的说明)。
本次使用的服务器(Oracle Cloud Infrastructure)、域名和证书发行都是免费的。
环境
我在Oracle云基础设施(OCI)的虚拟机免费套餐中创建了一个环境。镜像版本为Oracle-Linux-7.9-2021.10.20-0,虚拟机型号为VM.Standard.E2.1.Micro。
$ cat /etc/oracle-release
Oracle Linux Server release 7.9
系统的构成
-
- NginxはフリーかつオープンソースなWebサーバで、サーバー上の静的コンテンツを配信します。
-
- DjangoはPythonで実装されたWebアプリケーションフレームワークです。
- uWSGIとはPythonでWebサービスを動かすためのアプリケーションサーバです。PythonのWebアプリケーションとWebサーバー間とのやり取りの規約であるWSGI (Web Server Gateway Interface)に準拠したアプリケーション(Djangoなど)であれば使うことができます。DjangoのアプリケーションとNginx(Webサーバー)は直接対話できないので、uWSGIがその間を取り持ちます。
获得免费域名
為了最終實現SSL化,我們首先需要先取得域名。您可以從Freenom免費獲取五種類(.tk/.ml/.ga/.cf/.gq)的域名。截至2021年11月13日,域名的有效期限為取得日期起算的三個月。接下來,假設我們已經取得了example.tk這個域名,我們將在此基礎上進行下一步操作。
安装Nginx
我将创建一个Yum存储库文件。
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
安装。
sudo yum install -y nginx
确认版本。
$ nginx -v
nginx version: nginx/1.20.1
防火墙的设置
为了从外部访问服务器上的端口,我们需要在firewall-cmd中注册所需的端口。 这次我们要注册的是http,https和8000 / tcp(用于uWSGI验证)。 在OCI中,我们还需要从安全列表中打开端口。
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --permanent --add-port=8000/tcp
sudo firewall-cmd --reload
使用uWSGI来启动Django应用程序。
假设已经事先创建了一个名为django_project的Django项目。
首先,我们将验证Django应用程序是否能成功启动。我们将使用runserver命令,在8000端口上尝试启动它。
python manage.py runserver 0.0.0.0:8000
如果在这里出现以下类似的SQLite错误
django.core.exceptions.ImproperlyConfigured: SQLite 3.9.0 or later is required (found 3.7.17).
请参考「解决 Django2.2 在启动开发服务器时出现 SQLite3 错误」的文章,并解决问题。最终成功的标志是能够通过 http://example.tk:8000 访问 Django 应用程序。
接下来,使用uWSGI来启动Django应用程序。
使用pip命令安装uWSGI。
pip install uwsgi
在Django项目的文件夹下创建uwsgi_params。
https://github.com/nginx/nginx/blob/master/conf/uwsgi_params
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
通过以下命令启动。在这里,我们使用–http来通过浏览器等进行调试,但是当与Nginx通信时,使用Unix socket(–socket)。
uwsgi --http :8000 --module /path/to/your/django_project.wsgi
使用Certbot获取证书
这次我们将向一个名为Let’s Encrypt的认证机构申请证书。在此过程中,Certbot将与Let’s Encrypt进行通信并提供验证文件。
通常情况下,首先需要准备安装certbot所需的EPEL仓库。然而,针对Oracle Linux 7的ol7_developer_EPEL与原始的EPEL非常相似,因此大多数情况下无需额外安装EPEL。因此,我们需要确认ol7_developer_EPEL是否已启用。
$ sudo yum repolist all | grep -i epel
ol7_developer_EPEL/x86_64 Oracle Linux 7Server EPE disabled
如果没有无效化的话,就将其有效化。
sudo yum-config-manager --enable ol7_developer_EPEL
我会再次确认是否有效。
$ sudo yum repolist all | grep -i epel
ol7_developer_EPEL/x86_64 Oracle Linux 7Server EPE enabled: 40,406
当准备好EPEL之后,将安装certbot和python2-certbot-nginx(用于Nginx的附加功能)。
$ sudo yum -y install certbot python2-certbot-nginx
首先,将Nginx配置文件/etc/nginx/conf.d/default.conf中的域名从localhost更改为example.tk。
sudo sed -i 's/localhost/example.tk/g' /etc/nginx/conf.d/default.conf
执行以下命令可进行交互式生成证书操作。此外,通过添加–nginx选项,将自动编辑/etc/nginx/conf.d/default.conf文件。
sudo certbot --nginx -d example.tk
将uWSGI和Nginx进行协同工作
首先,需要准备Django的静态文件。
在settings.py中,需要在django_project/static/目录下指定收集静态文件的设置。
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
将静态文件收集到static目录中。
python manage.py collectstatic
在进行Nginx配置之前,我们先创建原始配置文件default.conf的备份,以防万一。
sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.copy
我要编辑/etc/nginx/conf.d/default.conf文件。
server {
server_name example.tk;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.tk/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.tk/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = example.tk) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name example.tk;
return 404; # managed by Certbot
}
以下是主要的变更点:
-
- uWSGIとUnix socketを用いて通信する設定を追記
-
- Djangoのstaticパスを指定
location /をDjangoのプロジェクトに変更
请根据你自己的环境修改路径为`/path/to/your/`,并将`example.tk`和`djang_project`更改为适合你的环境。
upstream django {
server unix:///path/to/your/django_project.sock; # for a file socket
}
# configuration of the server
server {
server_name example.tk; # substitute your machine's IP address or FQDN
charset utf-8;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# Django media
location /media {
alias /path/to/your/media; # your Django project's media files - amend as required
}
location /static {
alias /path/to/your/static; # your Django project's static files - amend as required
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /path/to/your/uwsgi_params; # the uwsgi_params file you installed
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/example.tk/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.tk/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = example.tk) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name example.tk;
return 404; # managed by Certbot
}
将 “/etc/nginx/conf.d/default.conf” 在 “/etc/nginx/nginx.conf” 中包含。
http {
...
include /etc/nginx/conf.d/default.conf;
...
}
启动(重新启动)Nginx。
sudo systemctl start nginx
使用uWSGI来启动Django应用程序。
uwsgi --socket django_project.sock --module django_project.wsgi --chmod-socket=664
如果能够从https://example.tk访问到Django应用程序,则表示成功。
如果从ini文件启动应用程序,操作如下:
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = /path/to/your/django_project
# Django's wsgi file
module = django_project.wsgi
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10
# the socket (use the full path to be safe
socket = /path/to/your/django_project/django_project.sock
# ... with appropriate permissions - may be needed
chmod-socket = 664
# clear environment on exit
#vacuum = true
uwsgi --ini uwsgi.ini
请为以下内容提供中文的同义词 :
参考
-
- 仮想マシン – Oracle Cloud Infrastructure
-
- OCI Always Free Compute (Oracle Linux・CentOS 7) に nginx をインストールする
-
- 無料のドメインを取得する
-
- CentOS7にnginxとcertbotを導入してHTTPS環境をさくっと作るの巻
-
- あらためてEPELリポジトリの使い方をまとめてみた
-
- Setting up Django and your web server with uWSGI and nginx
- Django2.2で開発サーバー起動時にSQLite3のエラーが出た場合の対応