生产环境下Nginx、Gunicorn与Django的SSL路由及登录跳转异常问题
解决Nginx无法传递路由给Django及登录500错误的排查方案
我来帮你一步步捋清楚这个问题——登录页面能正常打开,但提交就报500,说明静态资源请求没问题,但登录的POST请求要么没被Nginx正确转发给Django/Gunicorn,要么Django后端处理请求时出了内部错误。结合你的Ubuntu16.04、Python3.5+virtualenv环境,给你几个排查方向:
一、先核对Nginx配置是否正确转发所有请求
你提到有Nginx配置但没贴出来,先给你一个标准的Django+Nginx配置模板,对照着检查你的配置:
server { listen 80; server_name 你的域名或服务器IP; # 静态文件交给Nginx直接处理,别让Django费劲儿 location /static/ { root /你的Django项目根目录路径; expires 30d; # 缓存静态资源提升速度 } location /media/ { root /你的Django项目根目录路径; } # 核心:把所有非静态/媒体的请求全转给Gunicorn location / { proxy_pass http://127.0.0.1:8000; # 这里要和Gunicorn监听的地址完全一致 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
重点检查这几点:
location /块里的proxy_set_header不能少,尤其是Host头,Django靠它生成正确的URL,缺了很容易出问题- 确认
proxy_pass的地址和Gunicorn启动时的监听地址匹配——如果Gunicorn用的是Unix套接字(比如gunicorn --bind unix:/tmp/gunicorn.sock ...),那配置要改成proxy_pass http://unix:/tmp/gunicorn.sock; - 别单独给
/login路径加location规则,不然POST请求可能被Nginx拦截,没传到Django手里
二、查日志找真正的错误原因
500是内部错误,Nginx的日志可能只会说“上游服务器出错”,但真正的问题在Django或Gunicorn的日志里:
- 如果Gunicorn用systemd管理,执行
journalctl -u gunicorn.service就能看日志 - 如果是直接启动的Gunicorn,看启动终端的输出,或者你配置的日志文件
- 也可以看Django自己的日志(如果在
settings.py里配置了LOGGING)
常见的登录请求500原因:
- 生产环境的
SECRET_KEY没配置对(开发环境用默认的就行,生产必须设一个安全的密钥) - 数据库连接失败(生产环境的数据库账号、密码、主机和开发环境不一样,容易配错)
- 虚拟环境里缺依赖库(比如登录视图用到的第三方库没装)
- CSRF验证异常(不过这个一般返403,但如果代码里没处理好也可能出500)
三、确认Gunicorn和虚拟环境的配置没问题
- 检查Gunicorn是不是装在你的virtualenv里:执行
which gunicorn,路径应该是/你的虚拟环境目录/bin/gunicorn,要是系统全局的Gunicorn,很可能和虚拟环境的Python版本不兼容 - 如果用systemd管理Gunicorn,服务文件里必须指定虚拟环境的Python路径,比如:
[Unit] Description=gunicorn daemon After=network.target [Service] User=你的服务器用户名 Group=www-data WorkingDirectory=/你的Django项目根目录 ExecStart=/你的虚拟环境目录/bin/gunicorn --access-logfile - --workers 3 --bind 127.0.0.1:8000 你的项目名.wsgi:application [Install] WantedBy=multi-user.target - 直接测试Gunicorn能不能处理登录请求:在服务器上执行
curl -X POST http://127.0.0.1:8000/login -d "username=你的测试账号&password=你的测试密码",如果也返回500,那问题肯定在Django后端,和Nginx没关系
四、临时开DEBUG看详细错误(仅排查用!)
注意:生产环境绝对不能一直开DEBUG=True,但临时开一下能直接看到错误栈:
- 修改Django的
settings.py:把DEBUG改成True,ALLOWED_HOSTS加上你的域名或IP(比如ALLOWED_HOSTS = ['your-domain.com', '127.0.0.1']) - 重启Gunicorn和Nginx
- 再提交登录,页面会显示详细的错误信息,一眼就能看到哪行代码出问题
排查完记得立刻把DEBUG改回False,安全第一!
内容的提问来源于stack exchange,提问作者Justin Snyder
相关产品推荐
相关产品推荐

