使用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

系统的构成

system_overview.png
    • NginxはフリーかつオープンソースなWebサーバで、サーバー上の静的コンテンツを配信します。

 

    • DjangoはPythonで実装されたWebアプリケーションフレームワークです。

 

    uWSGIとはPythonでWebサービスを動かすためのアプリケーションサーバです。PythonのWebアプリケーションとWebサーバー間とのやり取りの規約であるWSGI (Web Server Gateway Interface)に準拠したアプリケーション(Djangoなど)であれば使うことができます。DjangoのアプリケーションとNginx(Webサーバー)は直接対話できないので、uWSGIがその間を取り持ちます。

获得免费域名

image.png

為了最終實現SSL化,我們首先需要先取得域名。您可以從Freenom免費獲取五種類(.tk/.ml/.ga/.cf/.gq)的域名。截至2021年11月13日,域名的有效期限為取得日期起算的三個月。接下來,假設我們已經取得了example.tk這個域名,我們將在此基礎上進行下一步操作。

安装Nginx

image.png

我将创建一个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获取证书

image.png

这次我们将向一个名为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のエラーが出た場合の対応
广告
将在 10 秒后关闭
bannerAds