目标:一台云服务器,两个域名,通过nginx,分别指向同服务器上的两个Django网站,并分别配置ssl证书。
先下载nginx:
yum -y install openssl openssl-devel
yum -y install gcc pcre-devel zlib zlib-devel
wget http://nginx.org/download/nginx-1.18.0.tar.gz -P /usr/src
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
make && make install
熟悉的欢迎界面
配置nginx服务脚本,方便控制nginx
vim /usr/lib/systemd/system/nginx.service
[Unit]
# 20210310 zhangxiaofei
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
# Nginx will fail to start if nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true
[Install]
WantedBy=multi-user.target
systemctl daemon-reload # 重启以生效
配置elinks,无缓存测试
yum install elinks lynx
elinks ip -source
重温nginx系列学习文章
- Nginx源码编译安装及配置文件初步学习
- Nginx作为web服务器的功能以及虚拟主机的作用
- Nginx反向代理、限速、url重写
- Nginx优化
- Nginx如何制作缓存\镜像服务器?
- Nginx构建高可用集群,实现负载均衡应对高并发
两个域名均以A记录类型指向测试服务器IP 111.22.44.121(下称X)。将TTL设置为最短600,方便快速生效。
分别测试两个域名,可以看到已经生效
elinks *****b.com -source
elinks *****3.com -source
开始制作两个测试html文件,分别命名为WEB1,WEB2
cd /usr/local/nginx/html
mkdir web1 web2
echo "web1" > web1/index.html; echo "web2" >web2/index.html
配置nginx文件server段,为了测试方便,我是直接在nginx.conf文件上进行修改,大概在34行左右,我将原有server段修改如下,并增加了一个server段
server{
listen 80;
server_name domain1.com;
location /{
root html/web1;
index index.html;
}
}
server {
listen 80;
server_name domain2.com;
location /{
root html/web2;
index index.html index.htm;
}
}
/usr/local/nginx/sbin/nginx -t
显示syntax is ok,那么可以重启nginx服务了。
systemctl restart nginx.service
此时在服务器上,测试如下
elinks host1.com -source
elinks host2.com -source
到这里,基本就可以确定,不同的域名可以解析到同一台云服务器上(单一公网IP),利用nginx对80端口的监听,分配到不同的网页内容,这也是预料之中的,不然nginx如何与如日中天的Apache抗衡呢。
通过uwsgi挂载不同项目
首先,需要制作一个测试的django项目。为了仿制正式环境,还是配置了一个python的虚拟环境,因为我的服务器版本比较高,centos8.2,所以如下命令安装比较顺畅。
pip3 install virtualenvwrapper
vim /etc/profile
# 在末尾加入以下内容
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
# 保存后让其生效
source /etc/profile
创建虚拟环境
mkvirtualenv web-3; mkvirtualenv web-b;lsvirtualenv
分别在两个虚拟环境中配置Django
pip install django==3.1.7
在本地创建一个django项目,待会第二个项目类似,这里主要是测试nginx与uwsgi的对接
django-admin startproject domainB
打开url配置文件,将其完全改写如下
cd domainB/domainB
vim urls.py
from django.urls import path
from django.http import HttpResponse
def index(request):
return HttpResponse("domain ****B")
urlpatterns = [
path('', index),
]
第二个项目
django-admin startproject domain3
只需要修改上方的HttpResponse内容,方便待会测试区分
def index(request):
return HttpResponse("33333 domain")
这样我就得到了两个可以用于测试的django项目,将其传到云服务上的srv目录下,方便待会指定路径
ls /srv/
>> domain3 domainB
安装、配置uwsgi(uwsgi必须安装在系统级别的Python环境中)
pip install uwsgi
报错如下:
我的python版本
Python 3.6.8 (default, Mar 19 2021, 05:13:41)
安装相关依赖如下:
yum install gcc python36-devel
再次安装uwsgi即可。
测试uwsgi是否正常工作,我当前所在路径
/srv/domain3
uwsgi --http :8000 --module domain3.wsgi --venv=/root/.virtualenvs/web-3
几个注意事项,http和:8000之间有空格,domain3.wsgi的是wsgi.py文件所在的文件夹名(别瞎改名),而--venv指向的是虚拟环境所在路径。
这个时候访问服务器公网IP的8000端口,应该可以看到网页内容
elinks http://101.33.66.170:8000 -source
33333 domain
如果你想在公网进行访问,记得修改django项目配置文件的ALLOWED_HOSTS
ALLOWED_HOSTS = ["*"]
可以看到uwsgi正常工作,由于这一长串的参数启动比较麻烦,所以,写一个ini配置文件来启动,当前目录/srv/domain3
touch demo1.ini
vim demo1.ini
[uwsgi]
chdir = /srv/domain3
module = domain3.wsgi
http = :8000
home = /root/.virtualenvs/web-3
接下来启动配置文件,网站可以正常访问
uwsgi demo1.ini
那么配置文件已经配置成功,修改配置文件,将内部通讯换成更为高效的sock文件:
[uwsgi]
chdir = /srv/domain3
module = domain3.wsgi
#http = :8000
home = /root/.virtualenvs/web-3
master = true
# 最大数量的工作进程
processes = 4
# socket文件路径,绝对路径,会自动创建
socket = /srv/domain3/domain3.sock
# 设置socket的权限
chmod-socket = 666
# 退出的时候是否清理环境
vacuum = true
依葫芦画瓢,制作第二个项目的ini配置文件
cp /srv/domain3/demo1.ini /srv/domainB/demo2.ini
[uwsgi]
chdir = /srv/domainB
module = domainB.wsgi
home = /root/.virtualenvs/web-b
master = true
processes = 4
socket = /srv/domainB/domainB.sock
chmod-socket = 666
vacuum = true
开始配置nginx配置文件,将之前配置的两个测试server删除掉
html{
upstream demo1site {
# 设定目录自动创建,即ngnix和uwsgi通讯的sock位置
# 一定要和demo1.ini中定义的socket一致
server unix:///srv/domain3/domain3.sock;
}
upstream demo2site {
server unix:///srv/domainB/domainB.sock;
}
server{
listen 80;
server_name *****b.com;
# 最后,发送所有非静态文件请求到django服务器
location / {
# 这个uwsgi_pass对应的参数一定要和upstream定义的一样
uwsgi_pass demo1site;
# uwsgi_params文件地址
include /usr/local/nginx/conf/uwsgi_params;
}
}
server {
listen 80;
server_name z***3.com
location / {
uwsgi_pass demo2site;
include /usr/local/nginx/conf/uwsgi_params;
}
}
}
配置完成之后,重启nginx,并启动uwsgi
uwsgi demo1.ini
uwsgi demo2.ini
访问两个域名,成功返回了各自网站的内容
但是这样还有点小问题,就是两个网站的日志混杂在一起,检查起来不是很方便,所以可以考虑将日志处理一下,在原来的nginx的配置文件http段中,增加一行包含代码
mkdir conf.d
vim nginx.conf
include conf.d/*.conf;
在conf.d目录下新建web1.conf和web2.conf文件,web1.conf文件如下
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
upstream demo1site {
server unix:///srv/domain3/domain3.sock;
}
server{
listen 80;
server_name ****b.com;
access_log logs/web1.access.log main;
location / {
uwsgi_pass demo1site;
include /usr/local/nginx/conf/uwsgi_params;
}
}
web2.conf
upstream demo2site {
server unix:///srv/domainB/domainB.sock;
}
server{
listen 80;
server_name ****3.com;
access_log logs/web2.access.log main;
location / {
uwsgi_pass demo2site;
include /usr/local/nginx/conf/uwsgi_params;
}
}
可以看到,两个域名的日志不再混杂了
配置supervisor控制uwsgi。
pip3 install supervisor
创建配置文件,只需一个supervisord进程可控制多个django项目
echo_supervisord_conf > demo_supervisor.conf
vim demo_supervisor.conf
主要是命名需要注意,需要保存日志的话,需要提前创建日志目录
[program:web1]
command=uwsgi --ini demo1.ini
directory=/srv/domain3
stdout_logfile=/srv/domain3/log/s.log
stderr_logfile=/srv/domain3/log/err.log
[program:web2]
command=uwsgi --ini demo2.ini
directory=/srv/domainB
stdout_logfile=/srv/domainB/log/s.log
stderr_logfile=/srv/domainB/log/err.log
接下来就可以正常启动、管理项目了
supervisord -c demo_supervisor.conf
supervisorctl -c demo_supervisor.conf
为多个网站申请SSL证书
照例,还是使用python的方法。由于之前我在测试,80端口一直是只对固定IP开放,但申请证书必须全部放开(80,443)
pip install certbot
standalone,运行独立的Web服务器进行身份验证;-d,DOMAINS,以逗号分隔的域列表,以获取证书;certonly,获取或续订证书
certbot certonly --standalone -d example.com -d www.example.com
按照要求申请完证书,再来配置nginx配置文件,web1.conf文件如下
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
upstream demo1site {
server unix:///srv/domain3/domain3.sock;
}
server{
listen 80;
server_name ****b.com;
rewrite ^(.*) https://$host$1 permanent;
}
server {
listen 443 ssl;
server_name ****b.com;
access_log logs/web1.access.log main;
ssl_certificate /etc/letsencrypt/live/****3.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/****3.com/privkey.pem;
ssl_protocols TLSv1.3;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
location / {
uwsgi_pass demo1site;
include /usr/local/nginx/conf/uwsgi_params;
}
}
web2.conf文件最终配置如下
upstream demo2site {
server unix:///srv/domainB/domainB.sock;
}
server{
listen 80;
server_name ****3.com;
rewrite ^(.*) https://$host$1 permanent;
}
server {
listen 443 ssl;
server_name ****3.com;
access_log logs/web2.access.log main;
ssl_certificate /etc/letsencrypt/live/****3.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/****3.com/privkey.pem;
ssl_protocols TLSv1.3;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
location / {
uwsgi_pass demo2site;
include /usr/local/nginx/conf/uwsgi_params;
}
}
重启nginx
测试完成!
参考:
https://stackoverflow.com/questions/29640868/compile-failed-with-error-code-1-in-tmp-pip-build-root-uwsgi