使用 Caddy 为 Flask 应用轻松添加 HTTPS

477 阅读5分钟

使用 Caddy 为 Flask 应用轻松添加 HTTPS

在 Web 开发中,将我们的应用从本地开发环境部署到服务器只是第一步。默认情况下,我们的 Flask 应用可能通过 HTTP 和服务器 IP 地址直接访问,例如 http://your_server_ip:5001

对于生产环境或任何需要保护用户数据传输的场景来说,启用 HTTPS 是必不可少的。借助 Caddy Web 服务器,为现有应用添加 HTTPS 并使用自定义域名变得异常简单。Caddy 以其开箱即用的自动 HTTPS 功能而闻名。

本文将记录如何为一个已部署的 Flask 应用(监听在 5001 端口)配置 Caddy,以实现通过自定义域名 xxx.xxx.com 进行 HTTPS 访问。

前提条件:

  • 一台可以通过 SSH 访问的 Linux 服务器。
  • 一个已部署并正在运行的 Flask 应用(本文假设它监听在 localhost:50010.0.0.0:5001)。
  • 一个域名(例如 xxx.xxx.com),并且其 DNS A 记录已指向你的服务器 IP 地址。
  • Caddy 已在服务器上安装。如果未安装,可以参考 Caddy 官方文档进行安装。

步骤 1:检查并确保 Caddy 正在运行

首先,我们需要确认 Caddy 是否已安装并检查其运行状态。

# 检查 Caddy 是否安装
command -v caddy

# 检查 Caddy 服务状态 (通常使用 systemd)
systemctl status caddy

在我们的案例中,初次检查发现 Caddy 服务处于 failed 状态。日志显示错误信息 listen tcp :80: bind: address already in use。这意味着服务器上的 80 端口已被其他程序占用。

我们需要找出哪个进程占用了 80 端口:

sudo lsof -i :80

输出显示 docker-proxy 占用了该端口。进一步检查运行中的 Docker 容器:

sudo docker ps

发现是一个名为 dnginx 的 Nginx 容器占用了 80 和 443 端口。由于我们决定使用 Caddy 来处理 HTTPS,我们需要停止这个冲突的 Nginx 容器:

sudo docker stop dnginx

停止冲突容器后,我们再次尝试启动 Caddy 服务并检查其状态:

sudo systemctl start caddy
systemctl status caddy

这次,状态显示 Active: active (running),表明 Caddy 已成功启动。

步骤 2:确认 Flask 应用监听端口

Caddy 需要知道将请求代理到哪里。我们需要确认 Flask 应用实际监听的端口。虽然我们的部署脚本和代码显示它应该在 5001 端口,但最好在服务器上确认一下:

# 查找监听 TCP 端口的 Python 进程
sudo ss -tlpn | grep python

输出确认了有 Python 进程监听在 0.0.0.0:5001

步骤 3:配置 Caddyfile 实现反向代理

Caddy 的主要配置文件是 Caddyfile,通常位于 /etc/caddy/Caddyfile。我们需要修改这个文件,告诉 Caddy 监听我们的域名,并自动处理 HTTPS,然后将流量转发给 Flask 应用。

我们将 /etc/caddy/Caddyfile 的内容修改为:

xxx.xxx.com {
    reverse_proxy localhost:5001
}

这个简单的配置块做了几件事:

  1. 定义了一个站点块,监听发往 xxx.xxx.com 的请求。
  2. Caddy 会自动为这个域名申请并续订 Let's Encrypt (或其他配置的 ACME CA) 的 TLS 证书,启用 HTTPS。所有 HTTP 请求也会自动重定向到 HTTPS。
  3. reverse_proxy localhost:5001 指令将所有接收到的请求转发给运行在同一台机器上、监听在 5001 端口的 Flask 应用。

我们可以通过 SSH 更新服务器上的文件:

# 注意:根据你的 shell 环境,可能需要调整引号和转义
echo -e 'weibo.haoxueren.com {\n    reverse_proxy localhost:5001\n}' | sudo tee /etc/caddy/Caddyfile

步骤 4:重新加载 Caddy 配置并测试

修改配置文件后,我们需要让 Caddy 重新加载配置以使更改生效:

sudo systemctl reload caddy

Caddy 会平滑地应用新配置。此时,Caddy 会在后台开始为 xxx.xxx.com 获取证书(如果是第一次配置)。这可能需要几秒到一分钟。

稍等片刻后,打开浏览器访问 https://xxx.xxx.com。如果一切顺利,你应该能看到你的 Flask 应用通过安全的 HTTPS 连接加载了!

步骤 5:增强安全性 - 限制 Flask 应用直接访问(推荐)

现在,虽然我们可以通过 https://xxx.xxx.com 访问应用,但原来的 http://your_server_ip:5001 可能仍然可以直接访问 Flask 应用,绕过了 Caddy。为了提高安全性,最佳实践是让后端应用(Flask)只监听本地回环地址 (127.0.0.1),这样只有本机上的进程(如 Caddy)可以连接到它。

我们需要修改 Flask 应用的启动方式。在我们的 app.py 文件中,找到 app.run() 的调用:

# app.py (文件末尾)

if __name__ == '__main__':
    # 将 host 从 '0.0.0.0' 修改为 '127.0.0.1'
    app.run(debug=True, host='127.0.0.1', port=5001)

修改完成后,需要将更新后的 app.py 重新部署到服务器(例如,通过运行你的 deploy.sh 脚本),并确保 Flask 应用被重启以应用新的监听地址。

完成此步骤后,你的 Flask 应用将不再能通过服务器的公共 IP 地址直接访问,所有流量都必须经过 Caddy 代理,确保了 HTTPS 的强制使用和统一的访问入口。

总结

通过 Caddy,我们仅用一个非常简洁的配置文件就为 Flask 应用启用了 HTTPS,并配置了基于域名的访问。Caddy 自动处理了 TLS 证书的获取和续订,大大简化了 HTTPS 的部署和维护工作。同时,通过限制后端应用的监听地址,我们进一步增强了应用部署的安全性。Caddy 无疑是现代 Web 服务部署中一个强大而易用的工具。