Co-Authored-By: Claude <noreply@anthropic.com>
11 KiB
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 + Xray(REALITY/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 -n、shellcheck、tests/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 内不写//注释,产出必须是合法 JSON(python3 -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 XHTTP;hy2 8443/UDP + CF DNS-01 泛域名证书; nftables UDP 20000-30000→8443)、用法/环境变量、供应链说明
- 上述全部工具函数、全局变量、阶段函数桩、main 分发(ACTION=uninstall → uninstall)
preflight:root 检查(DRY_RUN 跳过)、apt 系发行版检查- 测试:
bash -n、shellcheck、DRY_RUN=1冒烟(桩不报错、无 tty 时跳过交互) - Commit:
feat: add setup_caddy_xray_hysteria.sh skeleton
Task 2:collect_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/uuid;XRAY_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.com;CDN_DOMAIN可选默认空(空则不渲染 CDN 站点块);CF_API_TOKEN在未设 SKIP_HYSTERIA 时必填system_prepare:apt-get update -qq;DIST_UPGRADE=1→apt-get dist-upgrade -ysave_env:umask 077;mkdir -p /etc/caddy-xray-hy2;printf 全部变量写 ENV_FILE mode 600tests/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 3:install_caddy + render_caddyfile
Files: Modify 主脚本 + tests
install_caddy(SKIP_CADDY/DRY_RUN 跳过):cloudsmith gpg keycurl ... | gpg --batch --yes --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg; 写/etc/apt/sources.list.d/caddy-stable.list;apt-get update -qq && apt-get install -y caddyrender_caddyfile:heredoc 内嵌仓库Caddyfile,xxx.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行含/xh88ab、reverse_proxy @xhttppaths 127.0.0.1:8080;CDN_DOMAIN=cdn.example.com 时含两站点块 - Commit:
feat: caddy install + Caddyfile render
Task 4:install_xray + generate_xray_secrets + render_xray_config
Files: Modify 主脚本 + tests
install_xray(SKIP_XRAY/DRY_RUN 跳过):官方脚本bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ installgenerate_xray_secrets:UUID 空则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_KEYrender_xray_config:heredoc 内嵌仓库config.json(修正第 15 行多引号;不写//注释): 443 REALITY(dest "8003"、xver 1、serverNames__DOMAIN__、privateKey/shortIds/uuid 替换); 54442 WS(127.0.0.1,/scilad);8080 XHTTP(127.0.0.1,path__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、shortId3f9a2b1c、 serverNames、"network": "xhttp"、"port": 8080、"xPaddingObfsMode": true、"xPaddingHeader": "X-testpad"、"path": "/xh88ab" - Commit:
feat: xray install, keypair generation, config render
Task 5:install_hysteria + render_hysteria_config
Files: Modify 主脚本 + tests
install_hysteria(SKIP_HYSTERIA/DRY_RUN 跳过):bash <(curl -fsSL https://get.hy2.sh/)render_hysteria_config:heredoc 内嵌仓库config.yaml:listen: :8443;acme dns cloudflare,domains["*.__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_RUN:
chown -R hysteria:hysteria /etc/hysteria/ - 断言:渲染含
:8443、*.example.com、测试 token、密码、masquerade url - Commit:
feat: hysteria2 install + config render
Task 6:setup_nftables + validate_configs + enable_services
Files: Modify 主脚本 + tests
setup_nftables(SKIP_NFTABLES 跳过):写/etc/nftables/hysteria.nft(仓库hysteria.nft原样:table inet hysteria_nat,udp dport 20000-30000 redirect to :8443);$NFTABLES_CONFgrep 无 include 行才追加(幂等); 非 DRY_RUN:systemctl enable --now nftablesvalidate_configs(DRY_RUN 跳过):caddy validate --config /etc/caddy/Caddyfile、xray run -test -config /usr/local/etc/xray/config.json;hy2 无离线校验,靠启动后systemctl is-activeenable_services(DRY_RUN 跳过):按 SKIP_*systemctl enable --now/restartcaddy xray hysteria-server →is-active检查,失败 die- 断言:DRY_RUN 目录
hysteria.nft含20000-30000、:8443;渲染的 nftables.conf 含 include 行;include 追加逻辑跑两次不重复 - Commit:
feat: nftables port hopping, validation, service enablement
Task 7:self_check + print_summary + uninstall
Files: Modify 主脚本 + tests
self_check(DRY_RUN 跳过,失败仅 warn):curl -skI "https://$DOMAIN"、ss -lun | grep :8443、nft list table inet hysteria_natprint_summary:参数表 + 分享链接:- REALITY:
vless://$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#... - WS:
vless://$XRAY_WS_UUID@$DOMAIN:443?...&type=ws&path=%2Fscilad#... - XHTTP:
vless://$XRAY_XHTTP_UUID@$DOMAIN:443?...&type=xhttp&path=$XHTTP_PATH&mode=auto#... - CDN 变体(CDN_DOMAIN 非空):host/sni 换 CDN_DOMAIN
- Hysteria2:
hysteria2://$HY2_PASSWORD@$DOMAIN:8443/?mport=20000-30000&sni=www.$BASE_DOMAIN#...
- REALITY:
uninstall:systemctl disable --now三服务(容忍不存在);删 Caddyfile/config.json/ config.yaml;sed 删 include 行 + 删 hysteria.nft +nft delete table inet hysteria_nat;PURGE=1:apt purge caddy xray、hy2 官方卸载、删 cloudsmith 源/keyring; 默认保留 ENV_FILE,PURGE=1 且未设 KEEP_ENV 时删除- 断言:DRY_RUN 摘要含 5 条链接与端口/UUID;
ACTION=uninstall DRY_RUN=1不报错 - Commit:
feat: self-check, client summary, uninstall
Task 8:README + CLAUDE.md + 模板归档
Files: Modify README.md、CLAUDE.md;Move 5 模板 → docs/templates-original/
- README.md 追加中文小节:一键命令、必填/可选环境变量表、DRY_RUN、卸载、架构简述
- CLAUDE.md "What this repo is" 提及第二个脚本
git mv5 个模板并加存档 README("原始手工模板,已内嵌进脚本 heredoc")- 测试:最终
bash -n+shellcheck+tests/run_tests.sh全绿 - Commit:
docs: usage docs, archive original templates
执行方式
内联逐 Task 执行(executing-plans),每 Task 完成跑测试并 commit 后继续。