用 Caddy 与 Cloudflare 部署哪吒面板
在单机上部署哪吒 Dashboard,并正确配置 Caddy、TLS、Cloudflare gRPC、真实 IP 与验证闭环。
用 Caddy 与 Cloudflare 部署哪吒面板
[!info] related notes
- 所属地图:哪吒监控 MOC
- 原理:哪吒 Dashboard、Agent 与 gRPC 的协作架构
- Agent:安装和重装哪吒 Agent
- 排障:哪吒 Agent 无法上线排查
- 恢复:备份、升级和恢复哪吒 Dashboard
目标与成功状态
在一台 Linux VPS 上运行 Dashboard,使浏览器能通过 HTTPS 打开面板,Agent 能通过 gRPC 上线,并且重启服务器后服务自动恢复。
- Dashboard 只监听
127.0.x.x:8008。 - Caddy 对外监听
80/443并负责证书与协议分流。 - Cloudflare 橙云用于 Web 入口时,必须启用 gRPC;更稳妥的架构是额外准备一个 DNS-only 通信域名。
- 数据目录、配置和数据库有可恢复备份。
推荐拓扑
flowchart LR
B[浏览器] --> CF[Cloudflare Web 域名]
CF --> C[Caddy :443]
A[Agent] --> D[通信域名 :443]
D --> C
C --> N[Dashboard 127.0.x.x:8008]
N --> DB[(SQLite)]
若 Web 与 Agent 共用一个橙云域名,D 与 CF 是同一入口;若采用官方更推荐的双域名,D 应为 DNS-only。
前置条件
- 一台至少约 1 核、512 MiB 内存的 Linux 服务器。
- 一个 Web 域名;使用 CDN 时建议再准备一个通信域名。
- 云防火墙与主机防火墙放行
80/tcp、443/tcp。 - 已安装 Caddy,且 443 没有被其他服务占用。
- 已决定使用官方脚本、Docker 或独立二进制;本篇不混用多种安装生命周期。
安装 Dashboard
官方脚本入口:
curl -L https://raw.githubusercontent.com/nezhahq/scripts/main/install.sh \
-o nezha.sh
chmod +x nezha.sh
sudo ./nezha.sh
生产环境应立即修改默认管理员密码,并确认实际数据目录。独立 systemd 部署常见路径为 /opt/nezha/dashboard,数据库常见路径为 /opt/nezha/dashboard/data/sqlite.db,但应以本机 unit 与配置为准。
配置 Dashboard
关键值示例:
listen_host: 127.0.x.x
listen_port: 8008
dashboard_host: status.example.com
install_host: data.example.com:443
reserved_hosts: status.example.com,data.example.com
tls: true
web_real_ip_header: CF-Connecting-IP
agent_real_ip_header: CF-Connecting-IP
install_host 和 tls 影响前端生成的 Agent 安装命令,不代表 Dashboard 自己开启 TLS。TLS 通常由 Caddy 终止。
[!warning] 真实 IP 信任边界 只有当源站只接受可信反向代理/CDN 流量时,才能信任
CF-Connecting-IP等外部头。若客户端能绕过代理直达源站,就可能伪造头部。
按协议分流 Caddy
status.example.com, data.example.com {
@grpcProto {
path /proto.NezhaService/*
}
reverse_proxy @grpcProto {
header_up Host {host}
header_up nz-realip {http.request.header.CF-Connecting-IP}
transport http {
versions h2c
read_buffer 4096
}
to 127.0.x.x:8008
}
reverse_proxy {
header_up Host {host}
header_up Origin https://{host}
header_up nz-realip {http.request.header.CF-Connecting-IP}
transport http {
read_buffer 16384
}
to 127.0.x.x:8008
}
}
核心不是“加一条 reverse_proxy”,而是 gRPC 路径必须使用 h2c 连接明文 HTTP/2 后端。Caddy 是最外层、没有 CDN 时,应把真实 IP 值改为 {remote_host}。
修改后验证:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
sudo systemctl status caddy --no-pager
Cloudflare 设置
若通信域名启用橙云:
- SSL/TLS 模式至少使用 Full。
- Network → gRPC 切换为 On。
- 保留 HTTP/2。
- 确认 Access、WAF、自定义规则不会挑战或拦截 Agent 通信路径。
Cloudflare 官方明确说明:Zone 未启用 gRPC 时,gRPC 请求会返回 403 Forbidden。普通 GET 仍可能返回 200,所以必须做协议探测。
四层验证
# 1. Dashboard 本地监听
sudo ss -ltnp | grep ':8008'
# 2. Caddy 对外监听
sudo ss -ltnp | grep -E ':(80|443)\b'
# 3. Web 入口
curl -I https://status.example.com/
# 4. gRPC 入口
curl --http2 -v -X POST \
-H 'Content-Type: application/grpc' \
https://data.example.com/proto.NezhaService/
第四步应看到 HTTP/2、content-type: application/grpc 和 gRPC 状态,而不是 HTML、Cloudflare 403、普通 404 或代理 502。
回滚与恢复
- Caddy 修改前备份
/etc/caddy/Caddyfile。 - Dashboard 修改前备份配置和 SQLite。
- 若新配置使面板不可访问,先恢复 Caddy,再恢复 Dashboard 配置;不要直接删除 WAF 或用户表。
- 数据恢复流程见 备份、升级和恢复哪吒 Dashboard。