Caddy 实战:5 分钟给域名开启 HTTPS,自动申请 SSL 证书并反向代理

在服务器部署 Web 服务时,我们经常会遇到这样一个需求:

程序已经运行在服务器的某个端口,例如:

text 复制代码
http://127.0.0.1:8080

但是对外访问时,希望变成:

text 复制代码
https://api.example.com

如果使用 Nginx,一般还需要:

  • 配置 Nginx
  • 安装 Certbot
  • 申请 SSL 证书
  • 配置证书路径
  • 设置证书自动续期
  • 配置 HTTP 跳转 HTTPS

而使用 Caddy,这些工作可以简化很多。

Caddy 最大的特点之一就是支持 Automatic HTTPS。只要配置中使用了一个有效域名,并且 DNS 已经正确指向服务器、80 和 443 端口可以访问,Caddy 就可以自动申请并管理 HTTPS 证书。

本文就通过一个实际案例,演示如何使用 Caddy:

text 复制代码
域名
        ↓
https://api.example.com
        ↓
      Caddy
        ↓
http://127.0.0.1:8080
        ↓
    Python / Go / Java / Node.js 服务

整个过程不需要手动下载 SSL 证书。


一、准备环境

假设现在有:

text 复制代码
服务器公网 IP:203.0.113.10

域名:
api.example.com

后端程序:
http://127.0.0.1:8080

我们的最终目标是:

text 复制代码
https://api.example.com

访问这个地址时,由 Caddy 转发到:

text 复制代码
http://127.0.0.1:8080

服务器这里以 Ubuntu 为例。


二、首先配置域名 DNS

在域名服务商后台添加一条 A 记录。

例如:

text 复制代码
类型:A

主机记录:
api

记录值:
203.0.113.10

最终:

text 复制代码
api.example.com

解析到:

text 复制代码
203.0.113.10

可以通过下面的命令检查:

bash 复制代码
ping api.example.com

也可以:

bash 复制代码
nslookup api.example.com

例如:

text 复制代码
Name:    api.example.com
Address: 203.0.113.10

说明 DNS 已经基本生效。

这里非常重要。

如果域名没有正确解析到当前服务器,Caddy 就无法正常完成公网 HTTPS 证书的申请。


三、检查 80 和 443 端口

Caddy 对外主要使用:

text 复制代码
80    HTTP
443   HTTPS

因此需要保证服务器防火墙以及云服务器安全组已经放行这两个端口。Caddy 官方 HTTPS 文档同样要求公网 HTTPS 场景下域名正确解析,并确保 80、443 可以从外部访问。

如果 Ubuntu 开启了 UFW,可以执行:

bash 复制代码
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

查看:

bash 复制代码
sudo ufw status

如果使用的是阿里云、腾讯云、AWS、Azure 等云服务器,还需要检查云平台的:

text 复制代码
安全组
Firewall
Security Group

确认:

text 复制代码
TCP 80
TCP 443

允许访问。


四、安装 Caddy

Ubuntu / Debian 推荐直接使用官方软件源安装,官方安装包同时支持将 Caddy 作为 systemd 服务运行。

首先安装依赖:

bash 复制代码
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl

添加 Caddy 官方 GPG Key:

bash 复制代码
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

添加软件源:

bash 复制代码
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list

更新:

bash 复制代码
sudo apt update

安装:

bash 复制代码
sudo apt install caddy

查看版本:

bash 复制代码
caddy version

如果能够看到类似:

text 复制代码
v2.x.x

说明安装成功。


五、查看 Caddy 服务状态

安装完成后,可以执行:

bash 复制代码
systemctl status caddy

如果正常,应该可以看到:

text 复制代码
Active: active (running)

也可以执行:

bash 复制代码
sudo systemctl enable caddy

设置开机启动。

然后:

bash 复制代码
sudo systemctl start caddy

六、找到 Caddyfile

通过官方 Ubuntu 软件包安装后,我们一般直接编辑:

text 复制代码
/etc/caddy/Caddyfile

执行:

bash 复制代码
sudo nano /etc/caddy/Caddyfile

也可以使用 vim:

bash 复制代码
sudo vim /etc/caddy/Caddyfile

七、最简单的 HTTPS 配置

假设域名为:

text 复制代码
api.example.com

最简单的配置甚至可以写成:

caddy 复制代码
api.example.com {
    respond "Hello HTTPS"
}

保存配置。

然后检查配置:

bash 复制代码
sudo caddy validate --config /etc/caddy/Caddyfile

没有问题后重新加载:

bash 复制代码
sudo systemctl reload caddy

现在浏览器访问:

text 复制代码
https://api.example.com

就应该可以看到:

text 复制代码
Hello HTTPS

注意我们整个过程中:

没有手动申请 SSL 证书。

也没有配置:

text 复制代码
ssl_certificate
ssl_certificate_key

因为这些事情 Caddy 会自动处理。


八、Caddy 自动 HTTPS 的原理

这是 Caddy 相比传统 Web Server 非常方便的地方。

当 Caddyfile 中出现:

caddy 复制代码
api.example.com {
}

这样的域名配置后,Caddy 会识别这是一个需要 HTTPS 的站点。

在满足公网证书申请条件时,它会自动完成类似下面的流程:

text 复制代码
读取 Caddyfile
        ↓
发现 api.example.com
        ↓
检查域名
        ↓
向 CA 申请 TLS 证书
        ↓
安装证书
        ↓
启动 HTTPS
        ↓
监听 443
        ↓
HTTP 自动跳转 HTTPS

而且证书生命周期由 Caddy 自动管理,不需要自己写一个定时任务每隔几个月执行 Certbot。Caddy 官方将这套能力称为 Automatic HTTPS,包括自动证书管理以及默认的 HTTP → HTTPS 重定向。


九、实战:反向代理到 8080

真实项目一般不会直接让 Caddy 返回文本。

例如我们有一个 Python 服务运行:

text 复制代码
127.0.0.1:8080

或者:

text 复制代码
localhost:8080

我们希望:

text 复制代码
https://api.example.com

转发到:

text 复制代码
http://127.0.0.1:8080

修改:

bash 复制代码
sudo nano /etc/caddy/Caddyfile

配置:

caddy 复制代码
api.example.com {
    reverse_proxy 127.0.0.1:8080
}

就这么几行。

Caddy 官方提供的 HTTPS reverse proxy 用法也是直接使用域名作为站点地址,然后通过 reverse_proxy 指向后端。

检查配置:

bash 复制代码
sudo caddy validate --config /etc/caddy/Caddyfile

重新加载:

bash 复制代码
sudo systemctl reload caddy

现在:

text 复制代码
https://api.example.com

实际上访问的是:

text 复制代码
http://127.0.0.1:8080

十、完整请求流程

现在服务器结构就变成:

text 复制代码
浏览器
   │
   │ HTTPS
   ▼
https://api.example.com
   │
   │ 443
   ▼
 Caddy Server
   │
   │ HTTP
   ▼
127.0.0.1:8080
   │
   ▼
后端程序

对于 Python、Go、Node.js 等程序来说,可以只监听:

text 复制代码
127.0.0.1

例如:

text 复制代码
127.0.0.1:8080

而不需要直接暴露:

text 复制代码
8080

到公网。

公网用户只访问:

text 复制代码
443

十一、加入 gzip / zstd 压缩

可以继续修改 Caddyfile:

caddy 复制代码
api.example.com {

    encode zstd gzip

    reverse_proxy 127.0.0.1:8080
}

然后:

bash 复制代码
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

对于 Web 页面、JSON、文本接口等,可以降低一定的网络传输量。


十二、同时配置多个域名

Caddy 配置多个网站同样非常方便。

例如:

caddy 复制代码
api.example.com {
    reverse_proxy 127.0.0.1:8080
}

admin.example.com {
    reverse_proxy 127.0.0.1:9000
}

www.example.com {
    reverse_proxy 127.0.0.1:3000
}

对应:

text 复制代码
api.example.com
        ↓
localhost:8080


admin.example.com
        ↓
localhost:9000


www.example.com
        ↓
localhost:3000

只需要保证这几个域名的 DNS 都已经指向当前服务器。

Caddy 会分别处理相应的 HTTPS 配置。


十三、配置 API 服务

如果部署的是 FastAPI、Flask、Go API 或 Node.js API,例如:

text 复制代码
http://127.0.0.1:8083

那么配置只需要:

caddy 复制代码
api.example.com {
    reverse_proxy 127.0.0.1:8083
}

前端调用:

text 复制代码
https://api.example.com/api/users

请求会经过:

text 复制代码
Internet
   ↓
443
   ↓
Caddy
   ↓
127.0.0.1:8083

十四、后端使用 Docker 也没问题

例如 Docker:

bash 复制代码
docker run -d \
  --name my-api \
  -p 127.0.0.1:8080:8080 \
  my-api:latest

注意这里我特意写成:

text 复制代码
127.0.0.1:8080:8080

而不是:

text 复制代码
8080:8080

这样 8080 只绑定到本机。

公网不能直接:

text 复制代码
http://服务器IP:8080

访问。

但是 Caddy 可以:

caddy 复制代码
api.example.com {
    reverse_proxy 127.0.0.1:8080
}

整个结构就是:

text 复制代码
Internet
   │
   │ HTTPS :443
   ▼
 Caddy
   │
   │ HTTP :8080
   ▼
 Docker Container

这是我比较推荐的一种部署方式。


十五、修改 Caddyfile 后不要直接重启

每次修改配置后,最好先执行:

bash 复制代码
sudo caddy validate --config /etc/caddy/Caddyfile

确认配置没有问题。

然后使用:

bash 复制代码
sudo systemctl reload caddy

而不是:

bash 复制代码
sudo systemctl restart caddy

reload 可以让 Caddy 加载新的配置,同时减少服务中断。

正常流程:

bash 复制代码
sudo nano /etc/caddy/Caddyfile

然后:

bash 复制代码
sudo caddy validate --config /etc/caddy/Caddyfile

最后:

bash 复制代码
sudo systemctl reload caddy

可以记成:

text 复制代码
修改
 ↓
validate
 ↓
reload

十六、查看 Caddy 日志

如果 HTTPS 申请失败,首先不要反复修改配置。

直接看日志:

bash 复制代码
sudo journalctl -u caddy

查看最近内容:

bash 复制代码
sudo journalctl -u caddy -n 100

实时查看:

bash 复制代码
sudo journalctl -u caddy -f

这条命令非常有用:

bash 复制代码
sudo journalctl -u caddy -f

然后重新加载:

bash 复制代码
sudo systemctl reload caddy

就能实时看到:

text 复制代码
证书申请
域名验证
配置错误
端口占用
后端连接失败

等信息。


十七、502 Bad Gateway 怎么解决?

如果浏览器出现:

text 复制代码
502 Bad Gateway

通常说明:

Caddy 已经正常工作,但是 Caddy 无法访问后端。

例如配置:

caddy 复制代码
api.example.com {
    reverse_proxy 127.0.0.1:8080
}

首先在服务器执行:

bash 复制代码
curl http://127.0.0.1:8080

如果这里都失败:

text 复制代码
Connection refused

那么不是 Caddy 的问题。

而是后端:

text 复制代码
8080

根本没有启动。

执行:

bash 复制代码
ss -lntp | grep 8080

看看有没有程序监听:

text 复制代码
127.0.0.1:8080

十八、HTTPS 证书申请失败怎么办?

常见原因基本集中在以下几个方面。

1. DNS 没生效

检查:

bash 复制代码
nslookup api.example.com

确认解析出来的是当前服务器 IP。


2. 80 端口没有开放

检查:

bash 复制代码
sudo ufw status

以及云服务器:

text 复制代码
Security Group

3. 443 端口没有开放

同样需要检查:

text 复制代码
TCP 443

4. Nginx 占用了 80 / 443

检查:

bash 复制代码
sudo ss -lntp | grep ':80 '

以及:

bash 复制代码
sudo ss -lntp | grep ':443 '

如果看到:

text 复制代码
nginx

说明 Nginx 已经占用了端口。

如果准备完全使用 Caddy,可以先:

bash 复制代码
sudo systemctl stop nginx

再启动 Caddy:

bash 复制代码
sudo systemctl restart caddy

十九、检查 HTTPS

配置完成后,可以直接:

bash 复制代码
curl -I https://api.example.com

或者:

bash 复制代码
curl -v https://api.example.com

如果正常,就会看到 TLS 握手以及 HTTP Response。

浏览器中打开:

text 复制代码
https://api.example.com

地址栏也应该出现 HTTPS 安全标识。


二十、只用一条命令也能启动 HTTPS 反向代理

如果只是测试,并不一定要写 Caddyfile。

Caddy 本身提供:

bash 复制代码
caddy reverse-proxy \
    --from api.example.com \
    --to localhost:8080

这样同样可以快速创建一个 HTTPS reverse proxy。官方命令行文档也说明,当 --from 使用主机名时,Caddy 默认会尝试为该地址提供 HTTPS。

不过正式生产环境中,我还是更建议:

text 复制代码
/etc/caddy/Caddyfile

配合:

text 复制代码
systemd

运行。

方便管理,也方便以后增加更多域名。


二十一、生产环境推荐配置

一个普通 API 项目,我一般可以从下面这个配置开始:

caddy 复制代码
api.example.com {

    encode zstd gzip

    reverse_proxy 127.0.0.1:8080
}

如果有多个项目:

caddy 复制代码
api.example.com {

    encode zstd gzip

    reverse_proxy 127.0.0.1:8080
}


admin.example.com {

    encode zstd gzip

    reverse_proxy 127.0.0.1:9000
}


app.example.com {

    encode zstd gzip

    reverse_proxy 127.0.0.1:3000
}

非常直观。


二十二、Caddy 和 Nginx 最大的区别

对于简单的个人项目、小型 API、Docker 服务来说,Caddy 的优势非常明显。

Nginx 通常需要考虑:

text 复制代码
域名配置
+
反向代理
+
SSL证书
+
证书路径
+
Certbot
+
自动续期
+
HTTP → HTTPS

Caddy 则可以简化为:

caddy 复制代码
api.example.com {
    reverse_proxy localhost:8080
}

这是 Caddy 最吸引我的地方。

它并不是说 Nginx 不好。

复杂、高度定制化的 Web 架构中,Nginx 依然非常成熟。

但是对于:

text 复制代码
个人服务器
独立开发者
Side Project
Python API
Go API
Node.js
Docker 服务
内部工具
MCP Server
Webhook

这种场景,Caddy 的配置体验确实非常舒服。


二十三、最终部署结构

完成之后,我们的服务器架构实际上非常简单:

text 复制代码
                Internet
                    │
                    │
            api.example.com
                    │
                    │ HTTPS :443
                    ▼
              ┌───────────┐
              │   Caddy   │
              └─────┬─────┘
                    │
                    │ HTTP
                    │
              127.0.0.1:8080
                    │
                    ▼
            ┌───────────────┐
            │  Backend API  │
            │ Python / Go   │
            │ Node / Java   │
            └───────────────┘

公网只需要开放:

text 复制代码
80
443

业务端口:

text 复制代码
8080
9000
3000

则可以只监听:

text 复制代码
127.0.0.1

不直接暴露到公网。


二十四、常用命令汇总

最后把 Caddy 常用命令整理一下。

查看版本

bash 复制代码
caddy version

查看运行状态

bash 复制代码
systemctl status caddy

启动

bash 复制代码
sudo systemctl start caddy

停止

bash 复制代码
sudo systemctl stop caddy

重启

bash 复制代码
sudo systemctl restart caddy

平滑重新加载配置

bash 复制代码
sudo systemctl reload caddy

检查 Caddyfile

bash 复制代码
sudo caddy validate --config /etc/caddy/Caddyfile

格式化 Caddyfile

bash 复制代码
sudo caddy fmt --overwrite /etc/caddy/Caddyfile

查看日志

bash 复制代码
sudo journalctl -u caddy

实时查看日志

bash 复制代码
sudo journalctl -u caddy -f

总结

如果只是想给一个运行在服务器上的 Web 服务快速增加 HTTPS,Caddy 确实非常适合。

整个流程可以总结成:

text 复制代码
1. 域名解析到服务器 IP
        ↓
2. 开放 80 / 443
        ↓
3. 安装 Caddy
        ↓
4. 编辑 /etc/caddy/Caddyfile
        ↓
5. 配置 reverse_proxy
        ↓
6. Caddy 自动申请 HTTPS 证书
        ↓
7. https://域名 直接访问

最终真正核心的配置可能只有:

caddy 复制代码
api.example.com {
    reverse_proxy 127.0.0.1:8080
}

几行配置,就完成了:

text 复制代码
域名绑定
HTTPS
SSL 证书申请
证书管理
HTTP → HTTPS
反向代理

如果经常在 Ubuntu 服务器上部署各种 Python、Go、Node.js、Docker API 服务,Caddy 是一个非常值得掌握的工具。

相关推荐
xixingzhe24 小时前
正确认知HTTPS:并非万能加密,通信安全需要多层防护
网络协议·安全·https
网络小江4 小时前
组网第九课:光纤与光接口——一根玻璃丝,把千里外的机房“连“起来
网络协议
XiaoMaqqqq15 小时前
市面上正规的IP驱动产业新场景新工具哪家强
运维·python·网络协议·tcp/ip
ShyanZh15 小时前
【Python3基础】19-Socket 与 TCP、UDP 编程
python·网络协议·tcp/ip·udp
Lsetea16 小时前
OpenSSL verify报unhandled critical extension:error 34与关键扩展排查
运维·https·ssl证书·openssl·证书链
DP DPharness17 小时前
StudyMate 从安装到第一节课的完整操作路径
人工智能·websocket·网络协议·智能手机·dpharness
剑锋所指,所向披靡!21 小时前
HTTP服务器的基本相关概念
服务器·网络协议·http
2301_7779983421 小时前
TCP协议:滑动窗口与流量控制
服务器·网络·网络协议·tcp/ip·php
Lsetea1 天前
OpenSSL verify报CA certificate key too weak:auth_level与弱密钥链排查
运维·https·ssl证书·openssl·证书链