← [ BACK_TO_NOTES ]

用 Caddy 与 Cloudflare 部署哪吒面板

在单机上部署哪吒 Dashboard,并正确配置 Caddy、TLS、Cloudflare gRPC、真实 IP 与验证闭环。

#howto #evergreen #ops #network #nezha #caddy #cloudflare #grpc #server

用 Caddy 与 Cloudflare 部署哪吒面板

[!info] related notes

目标与成功状态

在一台 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 等外部头。若客户端能绕过代理直达源站,就可能伪造头部。

生产主题维护策略

当前生产面板使用 Dashboard 内置的 Nazhua 主题:

user_template: nazhua-dist

不要在 /opt/nezha/dashboard/ 下创建同名的 nazhua-dist/ 目录。Dashboard 会优先读取本地同名模板文件,本地目录会覆盖二进制内嵌的 Nazhua,因此一旦 Dashboard / Nazhua 升级,本地 index.html、config.js、CSS 或哈希资源和内嵌资源生命周期不同步,就容易出现模块加载、MIME 或运行时错误。

2026-09-08 已停止维护本地 Nazhua 二改:生产目录不再存在 /opt/nezha/dashboard/nazhua-dist,user_template 仍保持 nazhua-dist,由 Dashboard 直接提供内嵌主题。旧定制已备份到 /opt/nezha/dashboard/theme-backups/20260908T042214Z/。

后续原则:

  • 优先使用 Nazhua 原生能力和哪吒后台设置。
  • 不再 patch Nazhua 的 Vue 源码,不再自行构建并覆盖 nazhua-dist。
  • 必须定制时,先确认官方支持的配置接口,并把改动限制在最小范围;默认仍以零本地覆盖为基线。
  • 升级 Dashboard 后先验证原生 Nazhua,再考虑任何外观调整。

按协议分流 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 设置

若通信域名启用橙云:

  1. SSL/TLS 模式至少使用 Full。
  2. Network → gRPC 切换为 On。
  3. 保留 HTTP/2。
  4. 确认 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。

资料来源

创建于 2026/6/18 更新于 2026/9/8
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本