Caddy反向代理:一行配置搞定HTTPS,比Nginx简单10倍

概述

你跑了一个Docker容器,想通过域名从外网访问。传统做法是装Nginx、配反代、搞SSL证书、写rewrite规则……每一步都可能出错。

Caddy把这个流程砍到了三步:安装、写一行配置、启动。它会自动申请和续期Let’s Encrypt证书,HTTP直接跳转HTTPS,连端口都不用管。

这篇文章用Docker方式部署Caddy,配一个最简单的反代示例。

准备工作

  • 一台VPS(Ubuntu 22.04+ / Debian 12+)
  • 一个指向服务器IP的域名(比如 app.example.com)
  • Docker已安装(没装的话跑一遍 curl -fsSL https://get.docker.com | sudo sh)
  • 80端口和443端口未被占用

步骤

第一步:创建Caddy数据目录

sudo mkdir -p /etc/caddy
sudo chown -R $USER:$USER /etc/caddy

Caddy需要把这些目录存证书、日志和配置文件。

第二步:写Caddyfile

在 /etc/caddy/Caddyfile 写入以下内容:

app.example.com {
    reverse_proxy localhost:3000
}

这里 localhost:3000 是你的应用地址。如果应用跑在另一个Docker容器里,改成容器名或内网IP:

app.example.com {
    reverse_proxy my-app:3000
}

就这么简单。没有server块,没有ssl指令,没有rewrite。

第三步:用Docker启动Caddy

docker run -d \
  --name caddy \
  --restart unless-stopped \
  -p 80:80 \
  -p 443:443 \
  -v /etc/caddy/Caddyfile:/etc/caddy/Caddyfile:ro \
  -v caddy_data:/data \
  -v caddy_config:/config \
  caddy:latest

启动后Caddy会自动监听80端口,检测到域名解析正确后向Let’s Encrypt申请证书。首次申请可能需要等30秒左右。

第四步:验证HTTPS是否生效

curl -I https://app.example.com

看到这些响应头就说明一切正常:

HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains
x-content-type-options: nosniff

也可以直接在浏览器打开 https://app.example.com,看地址栏有没有小锁标志。

第五步:加个路径前缀(可选)

如果你的应用本身带了 /api 之类的路径前缀:

app.example.com {
    reverse_proxy /api/* localhost:3000
    reverse_proxy /* localhost:8080
}

或者用 handle_path 去掉前缀再转发:

app.example.com {
    handle_path /api/* {
        reverse_proxy localhost:3000
    }
}

验证

完整检查清单:

# 1. Caddy容器是否在运行
docker ps | grep caddy

# 2. HTTP是否自动跳转HTTPS
curl -I http://app.example.com | head -5

# 3. 证书过期时间
echo | openssl s_client -connect app.example.com:443 -servername app.example.com 2>/dev/null | openssl x509 -noout -dates

# 4. 查看Caddy日志
docker logs caddy --tail 20

第2步应该返回 301 Moved Permanently,Location指向HTTPS地址。第3步显示证书有效期约90天,Caddy会在到期前自动续期。

常见问题

Q: 域名还没解析到服务器IP,能用吗?

不能。Caddy申请证书前会验证域名ownership,DNS必须已经指向你的服务器。否则日志里会出现 authorization failed。

Q: 容器重启后证书还在吗?

在。证书存在 caddy_data 这个Docker volume里,不会随容器删除。但如果你删了volume,就得重新申请。

Q: 想自定义证书怎么办?

app.example.com {
    tls /etc/caddy/cert.pem /etc/caddy/key.pem
    reverse_proxy localhost:3000
}

挂载你自己的证书文件就行。不过大多数场景没必要,自动申请更方便。

Q: 怎么加IP限制或速率限制?

app.example.com {
    @blocked ip 10.0.0.0/8
    respond @blocked 403

    @slow ip 10.0.0.0/8
    limit_rate @slow {
        bandwidth 10M
        connections 10
    }

    reverse_proxy localhost:3000
}

Caddy内置了这些功能,不需要额外模块。

Q: 配置文件改完怎么生效?

docker restart caddy

或者不重启容器,让Caddy热加载:

docker exec caddy caddy reload --config /etc/caddy/Caddyfile

Caddy值得每个跑服务的人试一次。它的理念就是「你只需要告诉它转发的目标,剩下的它自己处理」。配好一行之后,证书、HTTPS、HTTP跳转全都不用管了。

你的站点用的什么反代?还在手动搞Nginx证书吗?

这篇文章对你有帮助吗?