不能直接用Uvicorn暴露到公网,因其不支持TLS终止、请求限流、静态文件服务等生产必需功能,易遭慢速攻击、暴露健康端点、引发内存泄漏,并导致502/504错误及不安全连接提示。

为什么不能直接用 Uvicorn 暴露到公网
Uvicorn 本身是 ASGI 服务器,设计上不处理 TLS 终止、请求限流、静态文件服务、HTTP/2 升级等生产必需功能。直接监听 0.0.0.0:8000 并开放到公网,会暴露健康端点、触发慢速攻击、无法复用域名和证书,还可能因长连接未正确关闭导致内存泄漏。
常见错误现象包括:502 Bad Gateway(Uvicorn 进程崩溃或未启动)、504 Gateway Timeout(Nginx 等待超时但 Uvicorn 响应太慢)、浏览器提示不安全连接(没配 SSL)。
基础反向代理配置要写对这三处
Nginx 配置核心是把请求“转给 Uvicorn”,同时确保协议头、连接保持、路径传递不出错。以下是最小可行配置片段(放在 /etc/nginx/sites-enabled/myapp):
upstream uvicorn_backend {
server 127.0.0.1:8000;
}
<p>server {
listen 80;
server_name example.com;</p><pre class="brush:python;toolbar:false;">location / {
proxy_pass http://uvicorn_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_redirect off;
}
}
-
proxy_http_version 1.1必须显式设置,否则 Nginx 默认用 HTTP/1.0,会断开 WebSocket 和长轮询 -
Upgrade和Connection头只在需要 WebSocket 或 Server-Sent Events 时才生效;如果不用,可删,但留着也无害 -
X-Forwarded-Proto决定 FastAPI 的request.url是http还是https;若用 Let’s Encrypt,必须配好,否则重定向会跳回http
Uvicorn 启动参数别忽略 --forwarded-allow-ips
Uvicorn 默认不信任任何 X-Forwarded-* 头,哪怕 Nginx 已设好,它仍会把客户端 IP 认作 127.0.0.1,导致日志、限流、鉴权全乱套。
启动命令必须加这个参数:
uvicorn main:app --host 127.0.0.1 --port 8000 --forwarded-allow-ips="127.0.0.1"
- 如果 Nginx 和 Uvicorn 不在同一台机器(比如 Docker 容器网络),要把
--forwarded-allow-ips改成对应网关 IP,例如172.18.0.1 - 值不能写
*(不安全),也不能为空(默认拒绝所有) - FastAPI 中用
request.client.host获取真实 IP 时,依赖这个配置生效
HTTPS 和静态文件得靠 Nginx 接手
Uvicorn 不管证书,也不高效服务 CSS/JS/图片。Nginx 需接管这两块:
- SSL 终止:在
server块加listen 443 ssl,并指定ssl_certificate和ssl_certificate_key - 静态文件:在
location /static下用alias指向本地路径,比如alias /var/www/myapp/static/;,避免把请求转发给 Uvicorn - HTTP → HTTPS 强制跳转:在
listen 80的 server 块里加return 301 https://$host$request_uri;
容易被忽略的是:Uvicorn 日志里的 127.0.0.1 - - [..] "GET /static/main.css" 表明静态文件还在走 Python,说明 Nginx 的 location /static 规则没匹配上——常见原因是路径末尾斜杠不一致或 alias 拼写错误。











