Files
vpsetup/docs/superpowers/plans/2026-08-23-caddy-xray-hysteria.md

11 KiB
Raw Permalink Blame History

setup_caddy_xray_hysteria.sh 实施计划(精简版)

设计文档:docs/superpowers/specs/2026-08-23-caddy-xray-hysteria-design.md 模板原文以仓库根部的 Caddyfile / config.json / config.yaml / hysteria.nft / nftables.conf 为准,实现时直接读取转成 heredoc,本计划不再逐字复制。

Goal: 单一自包含 bash 脚本,一键部署 Caddy + XrayREALITY/WS/XHTTP+ Hysteria2 + nftables 端口跳跃,含交互参数收集、凭据自动生成/持久化、配置校验、自检、分享链接输出与卸载。

Architecture: 分阶段函数 preflight → collect_params → system_prepare → install_caddy → install_xray → generate_xray_secrets → install_hysteria → render_all_configs → setup_nftables → validate_configs → save_env → enable_services → self_check → print_summary;模板 quoted heredoc + __VAR__ 占位符,bash 参数展开替换(非 sed);DRY_RUN=1 渲染全部文件到 DRY_RUN_DIR、 跳过一切系统变更,是 dev 机可测试的核心机制。

Global Constraints

  • 脚本注释用中文;禁止 sudo(直接要求 root);apt-get + DEBIAN_FRONTEND=noninteractive
  • 占位符严格 __VARNAME__ 与变量同名;替换用 bash 参数展开;随机值限 hex 字符集
  • 每任务完成必须过:bash -nshellchecktests/run_tests.sh → commit
  • 供应链:允许 cloudsmith apt 源、Xray/hy2 官方安装脚本;头部注释说明与 setup_warp_zerotrust.sh 的约束差异
  • /etc/nftables.conf幂等追加 include 行(先 grep 再 append);其余四个配置整体覆盖
  • xray 模板第 15 行 ""uuid-uuid 多引号笔误在 heredoc 中修正;xray heredoc 内不写 // 注释,产出必须是合法 JSONpython3 -m json.tool 可验证)
  • Caddyfile 伪装反代 @notpaths 排除列表必须包含 XHTTP 路径

文件结构

  • Create setup_caddy_xray_hysteria.sh — 主脚本(唯一交付物)
  • Create tests/run_tests.sh — DRY_RUN 集成测试
  • Modify README.md / CLAUDE.md
  • Move 5 个手写模板原件 → docs/templates-original/ 存档

全局接口约定(各任务共享,不得改名)

info / warn / die
gen_hex_bytes N                     # → 2N 位小写 hex
prompt_var VAR_NAME "提示语"          # 仅交互模式;已有值作默认值
render                              # stdin 模板 → stdout,按 RENDER_VARS 替换 __X__
write_file PATH MODE CONTENT        # DRY_RUN 时写到 $DRY_RUN_DIR/<basename>

RENDER_VARS="DOMAIN BASE_DOMAIN EMAIL CF_API_TOKEN CDN_DOMAIN
  XRAY_UUID XRAY_WS_UUID XRAY_XHTTP_UUID XRAY_PRIVATE_KEY XRAY_PUBLIC_KEY XRAY_SHORT_ID
  XHTTP_PATH XHTTP_PORT XPADDING_HEADER XPADDING_KEY
  HY2_PASSWORD HY2_MASQUERADE_URL"

# 环境变量:ACTION(install/uninstall) DRY_RUN DRY_RUN_DIR(默认 ./dry-run-output)
#   SKIP_CADDY SKIP_XRAY SKIP_HYSTERIA SKIP_NFTABLES DIST_UPGRADE PURGE KEEP_ENV
#   ENV_FILE=/etc/caddy-xray-hy2/setup.env  NFTABLES_CONF=/etc/nftables.conf
#   INTERACTIVE BASE_DOMAIN XRAY_PUBLIC_KEY(全局,跨函数共享)

# 阶段函数(Task 1 为 no-op 桩,后续逐个替换):
preflight collect_params system_prepare install_caddy install_xray
generate_xray_secrets install_hysteria render_all_configs setup_nftables
validate_configs save_env enable_services self_check print_summary uninstall main

Task 1:脚本骨架与工具函数

Files: Create setup_caddy_xray_hysteria.sh

  • 头部中文注释:用途、架构(Caddy 127.0.0.1:8003 PROXY protocol 收 REALITY 回落; Xray 443 REALITY + 54442 WS + 8080 XHTTPhy2 8443/UDP + CF DNS-01 泛域名证书; nftables UDP 20000-30000→8443)、用法/环境变量、供应链说明
  • 上述全部工具函数、全局变量、阶段函数桩、main 分发(ACTION=uninstall → uninstall
  • preflightroot 检查(DRY_RUN 跳过)、apt 系发行版检查
  • 测试bash -nshellcheckDRY_RUN=1 冒烟(桩不报错、无 tty 时跳过交互)
  • Commit: feat: add setup_caddy_xray_hysteria.sh skeleton

Task 2collect_params + system_prepare + save_env + 测试脚手架

Files: Modify 主脚本;Create tests/run_tests.sh

  • collect_params[ -f "$ENV_FILE" ] && source 作默认值;prompt_var 仅当变量为空且有 /dev/tty 时交互;DOMAIN 正则 ^([A-Za-z0-9-]+\.)+[A-Za-z]{2,}$,无 tty 且无值 die BASE_DOMAIN="${DOMAIN#*.}";默认 EMAIL="admin@$BASE_DOMAIN" UUID×3 用 /proc/sys/kernel/random/uuidXRAY_SHORT_ID=$(gen_hex_bytes 4) XHTTP_PATH="/$(gen_hex_bytes 4)"XHTTP_PORT=8080 XPADDING_HEADER="X-$(gen_hex_bytes 2)"XPADDING_KEY="_$(gen_hex_bytes 2)" HY2_PASSWORD=$(openssl rand -hex 16)HY2_MASQUERADE_URL 默认 https://www.people.comCDN_DOMAIN 可选默认空(空则不渲染 CDN 站点块); CF_API_TOKEN 在未设 SKIP_HYSTERIA 时必填
  • system_prepareapt-get update -qqDIST_UPGRADE=1apt-get dist-upgrade -y
  • save_envumask 077mkdir -p /etc/caddy-xray-hy2printf 全部变量写 ENV_FILE mode 600
  • tests/run_tests.sh:注入固定测试值(DOMAIN=test.example.com 等)→ DRY_RUN 跑 → 断言 $DRY_RUN_DIR/setup.env 存在且含 DOMAIN、BASE_DOMAIN=example.com
  • Commit: feat: parameter collection, env persistence, test scaffold

Task 3install_caddy + render_caddyfile

Files: Modify 主脚本 + tests

  • install_caddySKIP_CADDY/DRY_RUN 跳过):cloudsmith gpg key curl ... | gpg --batch --yes --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg/etc/apt/sources.list.d/caddy-stable.listapt-get update -qq && apt-get install -y caddy
  • render_caddyfileheredoc 内嵌仓库 Caddyfilexxx.yyy.zzz__DOMAIN__、 email→__EMAIL__;新增 @xhttppaths path __XHTTP_PATH__ __XHTTP_PATH__/*@notpaths 必须同时排除 xhttp 路径reverse_proxy @xhttppaths 127.0.0.1:__XHTTP_PORT__ CDN_DOMAIN 非空时追加第二站点块(仅 xhttp + /scilad + 伪装反代)
  • 断言:渲染含测试 domain/email、@xhttppaths path /xh88ab@notpaths 行含 /xh88abreverse_proxy @xhttppaths 127.0.0.1:8080CDN_DOMAIN=cdn.example.com 时含两站点块
  • Commit: feat: caddy install + Caddyfile render

Task 4install_xray + generate_xray_secrets + render_xray_config

Files: Modify 主脚本 + tests

  • install_xraySKIP_XRAY/DRY_RUN 跳过):官方脚本 bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
  • generate_xray_secretsUUID 空则 xray uuid(回退 /proc uuid)补齐; XRAY_PRIVATE_KEY 空则 xray x25519 生成,否则 xray x25519 -i $KEY 推公钥; 解析私钥 grep -i 'private'、公钥 grep -iE 'public|password',失败 die DRY_RUN 回退 XRAY_PUBLIC_KEY=DRYRUN_PUBLIC_KEY
  • render_xray_configheredoc 内嵌仓库 config.json(修正第 15 行多引号;不写 // 注释): 443 REALITYdest "8003"、xver 1、serverNames __DOMAIN__、privateKey/shortIds/uuid 替换); 54442 WS127.0.0.1/scilad);8080 XHTTP127.0.0.1path __XHTTP_PATH__mode auto extra 块:xPaddingObfsMode/tokenish/queryInHeader/__XPADDING_HEADER__/__XPADDING_KEY__); outbounds/dns/routing 保留模板原样(geoip:cn、私有网段、tg-out、域名阻断、bittorrent
  • 断言python3 -m json.tool 通过;含 3 个测试 UUID、privateKey、shortId 3f9a2b1c、 serverNames、"network": "xhttp""port": 8080"xPaddingObfsMode": true"xPaddingHeader": "X-testpad""path": "/xh88ab"
  • Commit: feat: xray install, keypair generation, config render

Task 5install_hysteria + render_hysteria_config

Files: Modify 主脚本 + tests

  • install_hysteriaSKIP_HYSTERIA/DRY_RUN 跳过):bash <(curl -fsSL https://get.hy2.sh/)
  • render_hysteria_configheredoc 内嵌仓库 config.yamllisten: :8443acme dns cloudflaredomains ["*.__BASE_DOMAIN__"]、email __EMAIL__cloudflare_api_token: __CF_API_TOKEN__dir: /etc/hysteria/acme_certs auth password __HY2_PASSWORD__masquerade proxy url __HY2_MASQUERADE_URL__ rewriteHost true
  • 非 DRY_RUNchown -R hysteria:hysteria /etc/hysteria/
  • 断言:渲染含 :8443*.example.com、测试 token、密码、masquerade url
  • Commit: feat: hysteria2 install + config render

Task 6setup_nftables + validate_configs + enable_services

Files: Modify 主脚本 + tests

  • setup_nftablesSKIP_NFTABLES 跳过):写 /etc/nftables/hysteria.nft (仓库 hysteria.nft 原样:table inet hysteria_natudp dport 20000-30000 redirect to :8443);$NFTABLES_CONF grep 无 include 行才追加(幂等); 非 DRY_RUN:systemctl enable --now nftables
  • validate_configsDRY_RUN 跳过):caddy validate --config /etc/caddy/Caddyfilexray run -test -config /usr/local/etc/xray/config.jsonhy2 无离线校验,靠启动后 systemctl is-active
  • enable_servicesDRY_RUN 跳过):按 SKIP_* systemctl enable --now/restart caddy xray hysteria-server → is-active 检查,失败 die
  • 断言DRY_RUN 目录 hysteria.nft20000-30000:8443;渲染的 nftables.conf 含 include 行;include 追加逻辑跑两次不重复
  • Commit: feat: nftables port hopping, validation, service enablement

Task 7self_check + print_summary + uninstall

Files: Modify 主脚本 + tests

  • self_checkDRY_RUN 跳过,失败仅 warn):curl -skI "https://$DOMAIN"ss -lun | grep :8443nft list table inet hysteria_nat
  • print_summary:参数表 + 分享链接:
    • REALITYvless://$XRAY_UUID@$DOMAIN:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=$DOMAIN&fp=chrome&pbk=$XRAY_PUBLIC_KEY&sid=$XRAY_SHORT_ID&type=tcp#...
    • WSvless://$XRAY_WS_UUID@$DOMAIN:443?...&type=ws&path=%2Fscilad#...
    • XHTTPvless://$XRAY_XHTTP_UUID@$DOMAIN:443?...&type=xhttp&path=$XHTTP_PATH&mode=auto#...
    • CDN 变体(CDN_DOMAIN 非空):host/sni 换 CDN_DOMAIN
    • Hysteria2hysteria2://$HY2_PASSWORD@$DOMAIN:8443/?mport=20000-30000&sni=www.$BASE_DOMAIN#...
  • uninstallsystemctl disable --now 三服务(容忍不存在);删 Caddyfile/config.json/ config.yamlsed 删 include 行 + 删 hysteria.nft + nft delete table inet hysteria_nat PURGE=1apt purge caddy xray、hy2 官方卸载、删 cloudsmith 源/keyring 默认保留 ENV_FILEPURGE=1 且未设 KEEP_ENV 时删除
  • 断言:DRY_RUN 摘要含 5 条链接与端口/UUID;ACTION=uninstall DRY_RUN=1 不报错
  • Commit: feat: self-check, client summary, uninstall

Task 8README + CLAUDE.md + 模板归档

Files: Modify README.md、CLAUDE.mdMove 5 模板 → docs/templates-original/

  • README.md 追加中文小节:一键命令、必填/可选环境变量表、DRY_RUN、卸载、架构简述
  • CLAUDE.md "What this repo is" 提及第二个脚本
  • git mv 5 个模板并加存档 README("原始手工模板,已内嵌进脚本 heredoc"
  • 测试:最终 bash -n + shellcheck + tests/run_tests.sh 全绿
  • Commit: docs: usage docs, archive original templates

执行方式

内联逐 Task 执行(executing-plans),每 Task 完成跑测试并 commit 后继续。