Files
pangolin/infra/cloud-init/node.yaml.tmpl
T
wangjia 8de32eb611 merge: 弹性节点基建:Terraform + 一键更换 [tsk_6u0FxmbC7Yeq]
# Conflicts:
#	.gitignore
#	infra/cloud-init/node.yaml.tmpl
2026-06-13 17:30:37 +08:00

110 lines
4.9 KiB
Cheetah
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#cloud-config
# Pangolin 加速节点一段式安装模板(与 #14 弹性开机共用)。
#
# 渲染:控制面 provisioner 用 sed 替换所有 __PLACEHOLDER__(沿用 deploy/ 约定)。
# __CONTROL_PLANE__ 控制面 gRPC 地址 host:port
# __SERVER_NAME__ 校验控制面证书的 TLS SNI(留空则取 host 部分)
# __BOOTSTRAP_TOKEN__ 一次性引导 token(由 mtls.BootstrapTokenManager.IssueToken 预签发,15min TTL
# __DERIVE_KEY__ Hy2 口令派生密钥(与控制面同源,见 agentd.DeriveHy2Password
# __AGENT_VERSION__ pangolin-agent 版本(与产物命名/SHA 锁定一致)
# __ARTIFACT_BASE__ 二进制与安装脚本下载根 URL
# __INSTALL_SHA256__ install-node.sh 的 SHA-256(整链可复现校验)
#
# 安全:agent.env 内含 bootstrap token,权限 0600token 一次性消费后即失效。
# 节点无状态:除 /etc/pangolin-agent/{node.key,node.crt,ca.crt,state.json} 与
# /etc/sing-box 外不落任何持久数据,且 state.json 仅含 dp_uuid + expires_at。
write_files:
- path: /etc/pangolin-agent/agent.env
permissions: '0600'
owner: root:root
content: |
PANGOLIN_AGENT_CONTROL_PLANE=__CONTROL_PLANE__
PANGOLIN_AGENT_SERVER_NAME=__SERVER_NAME__
PANGOLIN_AGENT_BOOTSTRAP_TOKEN=__BOOTSTRAP_TOKEN__
PANGOLIN_AGENT_DERIVE_KEY=__DERIVE_KEY__
PANGOLIN_AGENT_STATE_DIR=/etc/pangolin-agent
PANGOLIN_AGENT_SINGBOX_CONFIG=/etc/sing-box/config.json
PANGOLIN_AGENT_SINGBOX_UNIT=sing-box
PANGOLIN_AGENT_VERSION=__AGENT_VERSION__
runcmd:
- |
set -euo pipefail
mkdir -p /opt/pangolin
tmp="$(mktemp)"
# 下载安装脚本并按锁定 SHA-256 校验后再执行(拒绝被篡改的脚本)。
curl -fsSL --retry 3 "__ARTIFACT_BASE__/install-node.sh" -o "$tmp"
echo "__INSTALL_SHA256__ $tmp" | sha256sum -c -
install -m 0755 "$tmp" /opt/pangolin/install-node.sh
rm -f "$tmp"
ARTIFACT_BASE="__ARTIFACT_BASE__" AGENT_VERSION="__AGENT_VERSION__" \
bash /opt/pangolin/install-node.sh
# 整机 35 分钟内可服务:cloud-init 完成 → agent 首启 Enroll → Register 取全量配置 →
# 渲染 sing-box config 并 restart sing-box → REALITY/Hy2 入站上线。
## template: jinja-free Go text/template — rendered by
## server/internal/provision (CloudInitRenderer). Fields:
## {{.NodeUUID}} {{.BootstrapToken}} {{.Region}} {{.Role}} {{.Tier}} {{.ControlPlaneURL}}
##
## "Nodes are cattle, not pets" (doc/04 §2): this is the ENTIRE persistent
## footprint of a data-plane node — sing-box + agent binaries + a one-time
## bootstrap token. Zero user DB, zero logs, zero persistent state.
##
## SECURITY: the rendered output carries a one-time bootstrap token. It MUST NOT
## be logged. The token is consumed exactly once during mTLS enrollment (task #5)
## and is useless afterwards.
#cloud-config
write_files:
# Node identity + enrollment parameters consumed by the agent on first boot.
- path: /etc/pangolin/bootstrap.env
permissions: "0600"
owner: root:root
content: |
PANGOLIN_NODE_UUID={{.NodeUUID}}
PANGOLIN_BOOTSTRAP_TOKEN={{.BootstrapToken}}
PANGOLIN_CONTROL_PLANE_URL={{.ControlPlaneURL}}
PANGOLIN_REGION={{.Region}}
PANGOLIN_ROLE={{.Role}}
PANGOLIN_TIER={{.Tier}}
# systemd unit: agent enrolls (mTLS) then pulls runtime config from control plane.
- path: /etc/systemd/system/pangolin-agent.service
permissions: "0644"
owner: root:root
content: |
[Unit]
Description=Pangolin node agent (self-register + config pull)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
EnvironmentFile=/etc/pangolin/bootstrap.env
ExecStart=/usr/local/bin/pangolin-agent run
# No-log node: agent does not persist connection logs.
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
runcmd:
# 1. Harden: key-only SSH, no root password (doc/06 §3).
- sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
- sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
- systemctl restart sshd || true
# 2. Install the agent binary (pinned, checksum-verified by the install script,
# delivered out-of-band by task #6). Placeholder URL resolved at build time.
- install -d -m 0755 /etc/pangolin
- /usr/local/bin/pangolin-agent-install || true
# 3. Enroll + start. The agent reads bootstrap.env, performs mTLS enrollment,
# and the control plane flips the node provisioning → probing → up.
- systemctl daemon-reload
- systemctl enable --now pangolin-agent.service
# 4. Shred the one-time token from disk after enrollment (defence in depth).
- bash -c 'sleep 60; shred -u /etc/pangolin/bootstrap.env 2>/dev/null || rm -f /etc/pangolin/bootstrap.env'
# No swap file written to disk, no persistent data dirs — a destroyed node leaks nothing.