生产环境必须用Nginx反向代理做TLS终止,Flask仅处理HTTP;开发时可用app.run(ssl_context=...)本地调试,但禁用于生产——因Werkzeug单线程、无HTTP/2、不支持OCSP Stapling及证书热更新。

生产环境别让 Flask 自己扛 HTTPS,直接用 Nginx 反向代理做 TLS 终止是最稳妥的选择;开发调试时可以用 app.run(ssl_context=...) 快速验证,但必须清楚它的限制边界。
Flask 开发服务器怎么启用 HTTPS(仅限本地调试)
Werkzeug 内置服务器支持 HTTPS,但必须显式传入 ssl_context 参数,否则访问 https://localhost:5000 会直接报 ERR_SSL_PROTOCOL_ERROR 或空响应。
-
ssl_context='adhoc'最快:需先pip install pyOpenSSL,每次启动生成新自签名证书,适合单人本地调试;CI/容器中禁用——浏览器反复提示“不安全”,且无法被信任 - 用真实证书文件:传元组
ssl_context=('fullchain.pem', 'privkey.pem'),注意顺序不能反;fullchain.pem是 Let’s Encrypt 提供的完整链文件,不是cert.pem - 路径必须可读:相对路径基于当前工作目录,出错时常见
FileNotFoundError或ssl.SSLError: [SSL] PEM lib;私钥若带密码、权限为644(而非600),也会失败 - Flask 2.3+ 不再支持
ssl.PROTOCOL_TLSv1_2,改用ssl.PROTOCOL_TLS_SERVER
为什么生产环境绝不能用 app.run(ssl_context=...)?
这不是“能不能”的问题,而是“扛不住”:Werkzeug 开发服务器是单线程、无连接复用、不支持 HTTP/2,更无法处理 OCSP Stapling 和证书热更新。
- 压测时 CPU 飙升、TLS 握手超时增多,
curl -I https://api.example.com可能返回Empty reply from server - 证书续签要重启服务,无法自动完成;私钥权限配置错误(比如
chmod 644 server.key)可能直接导致密钥泄露 - 缺少关键安全头(如
Strict-Transport-Security)、不支持 TLS 1.3 完整特性(旧版 Gunicorn 尤其明显) - 所有加密、重定向、协议协商都该由专业反向代理承担,Flask 只需专注业务逻辑
Nginx 反向代理 + Flask HTTP 的标准配置要点
这是当前最主流、最安全的部署方式。Nginx 负责 TLS 终止,Flask 只监听 127.0.0.1:8000 的纯 HTTP 流量。
立即学习“Python免费学习笔记(深入)”;
-
ssl_certificate必须指向 Let’s Encrypt 的fullchain.pem,ssl_certificate_key指向privkey.pem;混用cert.pem会导致证书链不完整,iOS/macOS 设备易报错 - 必须加
proxy_set_header X-Forwarded-Proto $scheme;,否则 Flask 无法判断原始请求是否为 HTTPS - HTTP → HTTPS 重定向不能靠
request.url.startswith('https')判断——代理后永远是http://,得用request.headers.get('X-Forwarded-Proto') == 'https' - Flask 应用里完全不需要任何 SSL 配置,
app.run()保持默认 HTTP 启动即可
Gunicorn 直接配 HTTPS 的注意事项
如果因架构限制必须跳过 Nginx,用 Gunicorn 承载 TLS,务必确认版本和参数:
- Gunicorn ≥ 21.2 才完整支持 TLS 1.3;旧版本在高并发下 handshake 失败率显著上升
- 启动命令必须带
--certfile fullchain.pem --keyfile privkey.pem,不能只写--keyfile单独一项 - 仍需在 Gunicorn 前加一层负载均衡或防火墙,它本身不提供 HSTS、OCSP Stapling 等企业级 TLS 功能
- 证书热更新需 reload 进程,不如 Nginx 的
nginx -s reload平滑
真正容易被忽略的点不在代码里,而在证书路径、文件权限、代理头传递这三处;一个 fullchain.pem 写成 cert.pem 或漏掉 X-Forwarded-Proto,就能让整个 HTTPS 链路降级为 HTTP。


















