千问 AI 云部署 快速路径 1. 路由任务 — 匹配到 3 种模式之一:全栈部署 · 热更新 · 删除/清理。 2. 部署(默认) — 严格按步骤 1→14 顺序执行,不跳步/不乱序;门禁与可跳过项见 「执行顺序」。 3. 创建资源前确认费用 — 人民币(¥)展示小时单价,取得用户确认。 4. 记录状态 — 成功后写入 。 范围 | 范围内 | 范围外 | |--------|--------| | 本地项目/Git → 阿里云国内站 | 国际站 → 用 | | 全栈 ROS 编排、热更新、清理 | AWS/GCP/Azure/其他云 | | ECS + 可选 RDS + OSS + 公网 IP | K8s/Serverless/容器编排 | | OAuth/AK 认证(不收集凭证) | 域名/HTTPS(不涉及) | | 部署用户提供的代码/项目 | 审查或修改用户代码的业务逻辑、为代码正确性背书 | 关于用户代码 本 skill 负责把用户提供的代码/项目构建并部署上线,不审查、不修改其业务逻辑,也不保证代码本身正确。 代码的 bug、安全问题及部署上线后由代码引发的后果,由用户自行承担;如需改代码,由用户自行决定并执行。 假设 - CLI 3.x 已安装;无有效凭证时按 引导认证。 - 默认地域 。 --- 入口路由 | 信号 | 模式 | |------|------|…

\n InstanceType:\n Type: String\n ImageId:\n Type: String\n Default: aliyun_3_x64_20G_alibase_20240528.vhd\n Password:\n Type: String\n NoEcho: true\n MinLength: 8\n MaxLength: 30\n SystemDiskSize:\n Type: Number\n Default: 40\n MinValue: 20\n MaxValue: 500\n ZoneId:\n Type: String\n Description: 可用区 ID(ECS ∩ RDS 交集可用区,见 reference/deploy/08_check_stock.md)\n AppPort:\n Type: Number\n Default: 8080\n DbInstanceClass:\n Type: String\n Description: RDS MySQL 实例规格\n DbInstanceStorage:\n Type: Number\n MinValue: 20\n MaxValue: 6000\n Description: RDS 存储空间 GB\n DbName:\n Type: String\n Default: appdb\n AllowedPattern: '^[a-z][a-z0-9_]{0,62}

千问 AI 云部署 快速路径 1. 路由任务 — 匹配到 3 种模式之一:全栈部署 · 热更新 · 删除/清理。 2. 部署(默认) — 严格按步骤 1→14 顺序执行,不跳步/不乱序;门禁与可跳过项见 「执行顺序」。 3. 创建资源前确认费用 — 人民币(¥)展示小时单价,取得用户确认。 4. 记录状态 — 成功后写入 。 范围 | 范围内 | 范围外 | |--------|--------| | 本地项目/Git → 阿里云国内站 | 国际站 → 用 | | 全栈 ROS 编排、热更新、清理 | AWS/GCP/Azure/其他云 | | ECS + 可选 RDS + OSS + 公网 IP | K8s/Serverless/容器编排 | | OAuth/AK 认证(不收集凭证) | 域名/HTTPS(不涉及) | | 部署用户提供的代码/项目 | 审查或修改用户代码的业务逻辑、为代码正确性背书 | 关于用户代码 本 skill 负责把用户提供的代码/项目构建并部署上线,不审查、不修改其业务逻辑,也不保证代码本身正确。 代码的 bug、安全问题及部署上线后由代码引发的后果,由用户自行承担;如需改代码,由用户自行决定并执行。 假设 - CLI 3.x 已安装;无有效凭证时按 引导认证。 - 默认地域 。 --- 入口路由 | 信号 | 模式 | |------|------|…

\n DbAccount:\n Type: String\n Default: appuser\n AllowedPattern: '^[a-z][a-z0-9_]{0,15}

千问 AI 云部署 快速路径 1. 路由任务 — 匹配到 3 种模式之一:全栈部署 · 热更新 · 删除/清理。 2. 部署(默认) — 严格按步骤 1→14 顺序执行,不跳步/不乱序;门禁与可跳过项见 「执行顺序」。 3. 创建资源前确认费用 — 人民币(¥)展示小时单价,取得用户确认。 4. 记录状态 — 成功后写入 。 范围 | 范围内 | 范围外 | |--------|--------| | 本地项目/Git → 阿里云国内站 | 国际站 → 用 | | 全栈 ROS 编排、热更新、清理 | AWS/GCP/Azure/其他云 | | ECS + 可选 RDS + OSS + 公网 IP | K8s/Serverless/容器编排 | | OAuth/AK 认证(不收集凭证) | 域名/HTTPS(不涉及) | | 部署用户提供的代码/项目 | 审查或修改用户代码的业务逻辑、为代码正确性背书 | 关于用户代码 本 skill 负责把用户提供的代码/项目构建并部署上线,不审查、不修改其业务逻辑,也不保证代码本身正确。 代码的 bug、安全问题及部署上线后由代码引发的后果,由用户自行承担;如需改代码,由用户自行决定并执行。 假设 - CLI 3.x 已安装;无有效凭证时按 引导认证。 - 默认地域 。 --- 入口路由 | 信号 | 模式 | |------|------|…

\n DbPassword:\n Type: String\n NoEcho: true\n MinLength: 8\n MaxLength: 32\n Description: RDS 账号密码(8-32 位,含大小写字母+数字+特殊字符)\n\nResources:\n Vpc:\n Type: ALIYUN::ECS::VPC\n Properties:\n VpcName:\n Fn::Sub: qianwenai-${AppName}-vpc\n CidrBlock: 10.0.0.0/16\n Tags:\n - Key: from\n Value: qianwenai\n - Key: qianwenai-appName\n Value:\n Ref: AppName\n\n VSwitch:\n Type: ALIYUN::ECS::VSwitch\n Properties:\n VpcId:\n Ref: Vpc\n ZoneId:\n Ref: ZoneId\n CidrBlock: 10.0.1.0/24\n VSwitchName:\n Fn::Sub: qianwenai-${AppName}-vsw\n Tags:\n - Key: from\n Value: qianwenai\n\n SecurityGroup:\n Type: ALIYUN::ECS::SecurityGroup\n Properties:\n SecurityGroupName:\n Fn::Sub: qianwenai-${AppName}-sg\n VpcId:\n Ref: Vpc\n SecurityGroupIngress:\n - PortRange: 80/80\n Priority: 1\n IpProtocol: tcp\n SourceCidrIp: 0.0.0.0/0\n NicType: intranet\n - PortRange: 443/443\n Priority: 1\n IpProtocol: tcp\n SourceCidrIp: 0.0.0.0/0\n NicType: intranet\n Tags:\n - Key: from\n Value: qianwenai\n\n RdsInstance:\n Type: ALIYUN::RDS::DBInstance\n Properties:\n Engine: MySQL\n EngineVersion: '8.0'\n DBInstanceClass:\n Ref: DbInstanceClass\n DBInstanceStorage:\n Ref: DbInstanceStorage\n DBInstanceStorageType: cloud_essd\n PayType: Postpaid\n DBInstanceDescription:\n Fn::Sub: qianwenai-${AppName}-rds\n VpcId:\n Ref: Vpc\n VSwitchId:\n Ref: VSwitch\n ZoneId:\n Ref: ZoneId\n SecurityIPList: 10.0.0.0/16\n DeletionProtection: false\n Tags:\n from: qianwenai\n\n RdsDatabase:\n Type: ALIYUN::RDS::Database\n Properties:\n DBInstanceId:\n Ref: RdsInstance\n DBName:\n Ref: DbName\n CharacterSetName: utf8mb4\n DependsOn: RdsInstance\n\n RdsAccount:\n Type: ALIYUN::RDS::Account\n Properties:\n DBInstanceId:\n Ref: RdsInstance\n AccountName:\n Ref: DbAccount\n AccountPassword:\n Ref: DbPassword\n AccountType: Normal\n DependsOn: RdsDatabase\n\n RdsAccountPrivilege:\n Type: ALIYUN::RDS::AccountPrivilege\n Properties:\n DBInstanceId:\n Ref: RdsInstance\n AccountName:\n Ref: DbAccount\n DBName:\n Ref: DbName\n AccountPrivilege: ReadWrite\n DependsOn: RdsAccount\n\n EcsInstance:\n Type: ALIYUN::ECS::InstanceGroup\n Properties:\n ImageId:\n Ref: ImageId\n InstanceType:\n Ref: InstanceType\n InstanceChargeType: PostPaid\n Password:\n Ref: Password\n SecurityGroupId:\n Ref: SecurityGroup\n VSwitchId:\n Ref: VSwitch\n VpcId:\n Ref: Vpc\n InstanceName:\n Fn::Sub: qianwenai-${AppName}-ecs-[1,2]\n HostName:\n Fn::Sub: qianwenai-${AppName}-ecs-[1,2]\n MaxAmount: 1\n MinAmount: 1\n SystemDiskCategory: cloud_essd\n SystemDiskSize:\n Ref: SystemDiskSize\n AllocatePublicIP: false\n UserData:\n Fn::Sub:\n - |\n #!/bin/bash\n set -euxo pipefail\n # 引导日志可能包含数据库连接信息,先建好并收紧权限再写入\n # (默认 umask 会产生 644,任何本机用户都能读)。\n install -m 600 /dev/null /var/log/qianwenai-bootstrap.log 2>/dev/null || \\\n { touch /var/log/qianwenai-bootstrap.log; chmod 600 /var/log/qianwenai-bootstrap.log; }\n exec >> /var/log/qianwenai-bootstrap.log 2>&1\n echo \"[$(date -u +%FT%TZ)] === qianwenai bootstrap (with RDS) start ===\"\n\n # 写入/加载密码期间关闭 xtrace,否则 -x 会把 DB_PASSWORD 明文打进日志。\n set +x\n mkdir -p /etc/qianwenai\n cat > /etc/qianwenai/db.env \u003c\u003cDBENV\n DATABASE_URL=\"mysql://${DbAccount}:${DbPassword}@${RdsAddr}:${RdsPort}/${DbName}\"\n DB_HOST=\"${RdsAddr}\"\n DB_PORT=\"${RdsPort}\"\n DB_NAME=\"${DbName}\"\n DB_USER=\"${DbAccount}\"\n DB_PASSWORD=\"${DbPassword}\"\n DBENV\n chmod 600 /etc/qianwenai/db.env\n\n set -a\n . /etc/qianwenai/db.env\n set +a\n set -x\n echo \"[bootstrap] /etc/qianwenai/db.env 已写入(内容已省略)\"\n\n # ↓↓↓ generate_template.py 注入 base64 编码的引导脚本(解码后 source 执行,继承 db.env) ↓↓↓\n __USERDATA_BODY__\n - RdsAddr:\n Fn::GetAtt: [RdsInstance, InnerConnectionString]\n RdsPort:\n Fn::GetAtt: [RdsInstance, InnerPort]\n Tags:\n - Key: from\n Value: qianwenai\n - Key: qianwenai-appName\n Value:\n Ref: AppName\n DependsOn: RdsAccountPrivilege\n\n Eip:\n Type: ALIYUN::VPC::EIP\n Properties:\n Name:\n Fn::Sub: qianwenai-${AppName}-eip\n InternetChargeType: PayByTraffic\n Bandwidth: 5\n Tags:\n - Key: from\n Value: qianwenai\n\n EipAssoc:\n Type: ALIYUN::VPC::EIPAssociation\n Properties:\n AllocationId:\n Ref: Eip\n InstanceId:\n Fn::Select:\n - 0\n - Fn::GetAtt:\n - EcsInstance\n - InstanceIds\n\nOutputs:\n PublicIp:\n Description: 公网访问 IP(静态 http://\u003cIP>/,应用 http://\u003cIP>/api/)\n Value:\n Fn::GetAtt:\n - Eip\n - EipAddress\n EcsInstanceIds:\n Description: ECS 实例 ID 列表\n Value:\n Fn::GetAtt:\n - EcsInstance\n - InstanceIds\n EcsPrivateIps:\n Value:\n Fn::GetAtt:\n - EcsInstance\n - PrivateIps\n SecurityGroupId:\n Description: ECS 安全组 ID(入方向规则检查 / 放行)\n Value:\n Fn::GetAtt:\n - SecurityGroup\n - SecurityGroupId\n EipAllocationId:\n Description: EIP 分配 ID(EIP 状态查询 / 重新绑定)\n Value:\n Fn::GetAtt:\n - Eip\n - AllocationId\n DbInstanceId:\n Description: RDS 实例 ID\n Value:\n Ref: RdsInstance\n DbConnectionAddress:\n Description: RDS 内网连接地址\n Value:\n Fn::GetAtt:\n - RdsInstance\n - InnerConnectionString\n DbPort:\n Description: RDS 内网端口\n Value:\n Fn::GetAtt:\n - RdsInstance\n - InnerPort\n DbAccount:\n Value:\n Ref: DbAccount\n StackName:\n Value:\n Ref: ALIYUN::StackName\n","content_type":"application/yaml; charset=utf-8","language":"yaml","size":7820,"content_sha256":"c29cd973eac416041ea50bc9879b3f3493355d13b72d9c578a0b6a55fae5c7f0"},{"filename":"templates/ros_single.yaml","content":"ROSTemplateFormatVersion: '2015-09-01'\nDescription: 'qianwenai single-host deployment: 1 ECS + EIP + VPC + SecurityGroup. Static hosting + app service co-located on one VM.'\n\nParameters:\n AppName:\n Type: String\n Description: 应用名(用于资源命名),仅小写字母数字和短横线\n Default: app\n AllowedPattern: '^[a-z][a-z0-9-]{0,30}

千问 AI 云部署 快速路径 1. 路由任务 — 匹配到 3 种模式之一:全栈部署 · 热更新 · 删除/清理。 2. 部署(默认) — 严格按步骤 1→14 顺序执行,不跳步/不乱序;门禁与可跳过项见 「执行顺序」。 3. 创建资源前确认费用 — 人民币(¥)展示小时单价,取得用户确认。 4. 记录状态 — 成功后写入 。 范围 | 范围内 | 范围外 | |--------|--------| | 本地项目/Git → 阿里云国内站 | 国际站 → 用 | | 全栈 ROS 编排、热更新、清理 | AWS/GCP/Azure/其他云 | | ECS + 可选 RDS + OSS + 公网 IP | K8s/Serverless/容器编排 | | OAuth/AK 认证(不收集凭证) | 域名/HTTPS(不涉及) | | 部署用户提供的代码/项目 | 审查或修改用户代码的业务逻辑、为代码正确性背书 | 关于用户代码 本 skill 负责把用户提供的代码/项目构建并部署上线,不审查、不修改其业务逻辑,也不保证代码本身正确。 代码的 bug、安全问题及部署上线后由代码引发的后果,由用户自行承担;如需改代码,由用户自行决定并执行。 假设 - CLI 3.x 已安装;无有效凭证时按 引导认证。 - 默认地域 。 --- 入口路由 | 信号 | 模式 | |------|------|…

\n InstanceType:\n Type: String\n Description: ECS 实例规格\n ImageId:\n Type: String\n Default: aliyun_3_x64_20G_alibase_20240528.vhd\n Description: 操作系统镜像。默认 Alibaba Cloud Linux 3 x86_64。\n Password:\n Type: String\n NoEcho: true\n Description: ECS 登录密码(8-30 位,含大小写字母+数字)\n MinLength: 8\n MaxLength: 30\n SystemDiskSize:\n Type: Number\n Default: 40\n MinValue: 20\n MaxValue: 500\n ZoneId:\n Type: String\n Description: 可用区 ID(步骤 6 选定的有货可用区)\n AppPort:\n Type: Number\n Default: 8080\n Description: 应用服务监听端口(被 Nginx 反代到 /api/)\n UserDataScript:\n Type: String\n Description: bootstrap 脚本(明文,ROS 会自动 base64 编码)\n Default: |\n #!/bin/bash\n echo \"no userdata provided\" > /var/log/qianwenai-bootstrap.log\n\nResources:\n Vpc:\n Type: ALIYUN::ECS::VPC\n Properties:\n VpcName:\n Fn::Sub: qianwenai-${AppName}-vpc\n CidrBlock: 10.0.0.0/16\n Tags:\n - Key: from\n Value: qianwenai\n - Key: qianwenai-appName\n Value:\n Ref: AppName\n\n VSwitch:\n Type: ALIYUN::ECS::VSwitch\n Properties:\n VpcId:\n Ref: Vpc\n ZoneId:\n Ref: ZoneId\n CidrBlock: 10.0.1.0/24\n VSwitchName:\n Fn::Sub: qianwenai-${AppName}-vsw\n Tags:\n - Key: from\n Value: qianwenai\n\n SecurityGroup:\n Type: ALIYUN::ECS::SecurityGroup\n Properties:\n SecurityGroupName:\n Fn::Sub: qianwenai-${AppName}-sg\n VpcId:\n Ref: Vpc\n SecurityGroupIngress:\n - PortRange: 80/80\n Priority: 1\n IpProtocol: tcp\n SourceCidrIp: 0.0.0.0/0\n NicType: intranet\n - PortRange: 443/443\n Priority: 1\n IpProtocol: tcp\n SourceCidrIp: 0.0.0.0/0\n NicType: intranet\n Tags:\n - Key: from\n Value: qianwenai\n\n EcsInstance:\n Type: ALIYUN::ECS::InstanceGroup\n Properties:\n ImageId:\n Ref: ImageId\n InstanceType:\n Ref: InstanceType\n InstanceChargeType: PostPaid\n Password:\n Ref: Password\n SecurityGroupId:\n Ref: SecurityGroup\n VSwitchId:\n Ref: VSwitch\n VpcId:\n Ref: Vpc\n InstanceName:\n Fn::Sub: qianwenai-${AppName}-ecs-[1,2]\n HostName:\n Fn::Sub: qianwenai-${AppName}-ecs-[1,2]\n MaxAmount: 1\n MinAmount: 1\n SystemDiskCategory: cloud_essd\n SystemDiskSize:\n Ref: SystemDiskSize\n AllocatePublicIP: false\n UserData:\n Ref: UserDataScript\n Tags:\n - Key: from\n Value: qianwenai\n - Key: qianwenai-appName\n Value:\n Ref: AppName\n\n Eip:\n Type: ALIYUN::VPC::EIP\n Properties:\n Name:\n Fn::Sub: qianwenai-${AppName}-eip\n InternetChargeType: PayByTraffic\n Bandwidth: 5\n Tags:\n - Key: from\n Value: qianwenai\n\n EipAssoc:\n Type: ALIYUN::VPC::EIPAssociation\n Properties:\n AllocationId:\n Ref: Eip\n InstanceId:\n Fn::Select:\n - 0\n - Fn::GetAtt:\n - EcsInstance\n - InstanceIds\n\nOutputs:\n PublicIp:\n Description: 公网访问 IP(静态 http://\u003cIP>/,应用 http://\u003cIP>/api/)\n Value:\n Fn::GetAtt:\n - Eip\n - EipAddress\n EcsInstanceIds:\n Description: ECS 实例 ID 列表\n Value:\n Fn::GetAtt:\n - EcsInstance\n - InstanceIds\n EcsPrivateIps:\n Description: ECS 内网 IP 列表\n Value:\n Fn::GetAtt:\n - EcsInstance\n - PrivateIps\n SecurityGroupId:\n Description: ECS 安全组 ID(入方向规则检查 / 放行)\n Value:\n Fn::GetAtt:\n - SecurityGroup\n - SecurityGroupId\n EipAllocationId:\n Description: EIP 分配 ID(EIP 状态查询 / 重新绑定)\n Value:\n Fn::GetAtt:\n - Eip\n - AllocationId\n StackName:\n Value:\n Ref: ALIYUN::StackName\n","content_type":"application/yaml; charset=utf-8","language":"yaml","size":4407,"content_sha256":"9c0a06c3e8317bfcd4ec8c6752cb1ffe6239875e88cc41c2e6417cfa2d4859fe"},{"filename":"templates/userdata/docker.sh","content":"#!/bin/bash\n# qianwenai · Docker 应用 bootstrap\n# 占位符:\n# __APP_ARTIFACT_URL__ 应用镜像 tar.gz(docker save 的产物)或 docker-compose.yml + 构建上下文 tar.gz 的 OSS 签名 URL\n# __APP_MODE__ docker-image | docker-compose\n# __APP_PORT__ 应用容器监听端口(被 Nginx 反代)\n# __APP_IMAGE_NAME__ docker-image 模式下 docker load 后的镜像名:tag(如 myapp:latest)\n# __APP_NAME__ 服务名(systemd unit / 容器名)\nset -euxo pipefail\n\nLOG=/var/log/qianwenai-bootstrap.log\nexec >> \"$LOG\" 2>&1\necho \"[$(date -u +%FT%TZ)] === qianwenai docker bootstrap start ===\"\n\n# 1. 安装 Docker\nif ! command -v docker >/dev/null 2>&1; then\n if command -v dnf >/dev/null 2>&1; then\n dnf install -y docker\n elif command -v yum >/dev/null 2>&1; then\n yum install -y docker\n elif command -v apt-get >/dev/null 2>&1; then\n apt-get update && apt-get install -y docker.io\n fi\nfi\nsystemctl enable docker\nsystemctl start docker\n\nAPP_URL=\"__APP_ARTIFACT_URL__\"\nAPP_MODE=\"__APP_MODE__\"\nAPP_PORT=\"__APP_PORT__\"\nIMAGE_NAME=\"__APP_IMAGE_NAME__\"\nAPP_NAME=\"__APP_NAME__\"\n\nmkdir -p /opt/qianwenai\ncd /opt/qianwenai\ncurl -fsSL \"$APP_URL\" -o app.tar.gz\n\n# 若 RDS bootstrap 写了 db.env,docker 启动时挂进容器\nDB_ENV_OPT=\"\"\n[ -f /etc/qianwenai/db.env ] && DB_ENV_OPT=\"--env-file /etc/qianwenai/db.env\"\n\nif [ \"$APP_MODE\" = \"docker-image\" ]; then\n # 解压并 docker load\n tar -xzf app.tar.gz\n # docker load 后确保镜像 tag 与 IMAGE_NAME 一致:产物 tar 里的 tag 未必等于 IMAGE_NAME,\n # 若不一致,unit 的 ExecStart 会按 IMAGE_NAME 找不到/跑错镜像。这里按加载结果重打 tag。\n LOAD_OUT=$(docker load -i image.tar)\n echo \"$LOAD_OUT\"\n LOADED_REF=$(echo \"$LOAD_OUT\" | sed -n 's/^Loaded image: //p' | head -1)\n [ -z \"$LOADED_REF\" ] && LOADED_REF=$(echo \"$LOAD_OUT\" | sed -n 's/^Loaded image ID: //p' | head -1)\n if [ -n \"$LOADED_REF\" ] && [ \"$LOADED_REF\" != \"${IMAGE_NAME}\" ]; then\n docker tag \"$LOADED_REF\" \"${IMAGE_NAME}\"\n fi\n # 写 systemd unit 持久托管\n cat > /etc/systemd/system/${APP_NAME}.service \u003c\u003cUNIT\n[Unit]\nDescription=${APP_NAME} app container\nAfter=docker.service\nRequires=docker.service\n\n[Service]\nRestart=always\nExecStartPre=-/usr/bin/docker rm -f ${APP_NAME}\nExecStart=/usr/bin/docker run --rm --name ${APP_NAME} -p ${APP_PORT}:${APP_PORT} ${DB_ENV_OPT} ${IMAGE_NAME}\nExecStop=/usr/bin/docker stop ${APP_NAME}\n\n[Install]\nWantedBy=multi-user.target\nUNIT\n systemctl daemon-reload\n systemctl enable ${APP_NAME}\n systemctl restart ${APP_NAME}\n\nelif [ \"$APP_MODE\" = \"docker-compose\" ]; then\n # 解压(包含 docker-compose.yml 和构建上下文 或 已 build 的镜像 tar)\n tar -xzf app.tar.gz\n # 安装 docker compose plugin(若未自带)\n if ! docker compose version >/dev/null 2>&1; then\n mkdir -p /usr/local/lib/docker/cli-plugins\n curl -fsSL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 \\\n -o /usr/local/lib/docker/cli-plugins/docker-compose\n chmod +x /usr/local/lib/docker/cli-plugins/docker-compose\n fi\n # compose 会自动加载同目录下的 .env;如有 RDS env 则导出到 .env。\n # db.env 权限为 0600(含数据库密码),必须用 install -m 600 保持权限,\n # 否则默认 cp 会落成 0644,使密钥对同机其他用户可读。\n if [ -f /etc/qianwenai/db.env ]; then\n install -m 600 /etc/qianwenai/db.env ./.env\n fi\n docker compose -f docker-compose.yml up -d\nfi\n\necho \"[$(date -u +%FT%TZ)] docker app up\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":3570,"content_sha256":"93d8e608c6d3a13d09f09e9008416bf6d1c937b223695002733030b1c3f4d78a"},{"filename":"templates/userdata/nginx_proxy.sh","content":"#!/bin/bash\n# qianwenai · Nginx 全量反代应用(适用于 Flask/Django/Express SSR 等服务端渲染应用)\n# 该片段会被 generate_template.py 注入到 ECS UserData 头部。\n# 占位符(generate_template.py 会替换):\n# __APP_PORT__ 应用服务监听端口(如 5000)\nset -euxo pipefail\n\nLOG=/var/log/qianwenai-bootstrap.log\nexec > >(tee -a \"$LOG\") 2>&1\necho \"[$(date -u +%FT%TZ)] === qianwenai nginx (proxy) bootstrap start ===\"\n\n# 1. 安装 Nginx\nif ! command -v nginx >/dev/null 2>&1; then\n if command -v dnf >/dev/null 2>&1; then dnf install -y nginx\n elif command -v yum >/dev/null 2>&1; then yum install -y nginx\n elif command -v apt-get >/dev/null 2>&1; then apt-get update && apt-get install -y nginx\n else echo \"no supported package manager\"; exit 1\n fi\nfi\n\n# 2. 写站点配置:所有请求反代到应用\ncat > /etc/nginx/conf.d/qianwenai.conf \u003c\u003cNGINX\nserver {\n listen 80 default_server;\n server_name _;\n\n location / {\n proxy_pass http://127.0.0.1:__APP_PORT__;\n proxy_set_header Host \\$host;\n proxy_set_header X-Real-IP \\$remote_addr;\n proxy_set_header X-Forwarded-For \\$proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto \\$scheme;\n proxy_read_timeout 60s;\n proxy_connect_timeout 10s;\n }\n\n location = /healthz { return 200 \"ok\\n\"; }\n}\nNGINX\n\n# 移除默认 server(避免冲突)\n[ -f /etc/nginx/conf.d/default.conf ] && mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak || true\n\nnginx -t\nsystemctl enable nginx\nsystemctl restart nginx\n\necho \"[$(date -u +%FT%TZ)] nginx (proxy) ready\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1639,"content_sha256":"f0260bd023c6e738583927379fa3610ba5e53d91df23a511fc85042f7306d77d"},{"filename":"templates/userdata/nginx_static_proxy.sh","content":"#!/bin/bash\n# qianwenai · Nginx 静态托管 + /api/ 反代应用\n# 该片段会被 generate_template.py 注入到 ECS UserData 头部。\n# 占位符(generate_template.py 会替换):\n# __STATIC_ARTIFACT_URL__ 静态 dist 压缩包的 OSS 签名 URL(http GET)\n# __APP_PORT__ 应用服务监听端口(如 8080)\nset -euxo pipefail\n\nLOG=/var/log/qianwenai-bootstrap.log\nexec > >(tee -a \"$LOG\") 2>&1\necho \"[$(date -u +%FT%TZ)] === qianwenai nginx bootstrap start ===\"\n\n# 1. 安装 Nginx\nif ! command -v nginx >/dev/null 2>&1; then\n if command -v dnf >/dev/null 2>&1; then dnf install -y nginx\n elif command -v yum >/dev/null 2>&1; then yum install -y nginx\n elif command -v apt-get >/dev/null 2>&1; then apt-get update && apt-get install -y nginx\n else echo \"no supported package manager\"; exit 1\n fi\nfi\n\n# 2. 拉取静态构建产物(若有)\n# 注意:STATIC_URL 由 generate_template.py 在打包前替换:有产物 → 真实签名 URL,无静态文件 → 空字符串\nSTATIC_URL='__STATIC_ARTIFACT_URL__'\nmkdir -p /var/www/static\nif [ -n \"$STATIC_URL\" ]; then\n curl -fsSL \"$STATIC_URL\" -o /tmp/static.tar.gz\n tar -xzf /tmp/static.tar.gz -C /var/www/static --strip-components=0\n rm -f /tmp/static.tar.gz\nelse\n cat > /var/www/static/index.html \u003c\u003c'HTML'\n\u003c!doctype html>\u003cmeta charset=utf-8>\u003ctitle>qianwenai\u003c/title>\n\u003ch1>ECS is up. Awaiting static artifact.\u003c/h1>\nHTML\nfi\n\n# 3. 写站点配置:80 端口 root 指向静态目录,/api/ 反代应用\ncat > /etc/nginx/conf.d/qianwenai.conf \u003c\u003cNGINX\nserver {\n listen 80 default_server;\n server_name _;\n root /var/www/static;\n index index.html;\n\n location / {\n try_files \\$uri \\$uri/ /index.html;\n }\n\n location /api/ {\n proxy_pass http://127.0.0.1:__APP_PORT__;\n proxy_set_header Host \\$host;\n proxy_set_header X-Real-IP \\$remote_addr;\n proxy_set_header X-Forwarded-For \\$proxy_add_x_forwarded_for;\n proxy_read_timeout 60s;\n }\n\n location = /healthz { return 200 \"ok\\n\"; }\n}\nNGINX\n\n# 移除默认 server(避免冲突)\n[ -f /etc/nginx/conf.d/default.conf ] && mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak || true\n\nnginx -t\nsystemctl enable nginx\nsystemctl restart nginx\n\necho \"[$(date -u +%FT%TZ)] nginx ready\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2293,"content_sha256":"0b6833516927029a9e9e0245b082aee426a15835403d677512535e0e2a874f39"},{"filename":"templates/userdata/nginx_static.sh","content":"#!/bin/bash\n# qianwenai · Nginx 纯静态托管(无应用反代)\n# 该片段会被 generate_template.py 注入到 ECS UserData 头部。\n# 占位符(generate_template.py 会替换):\n# __STATIC_ARTIFACT_URL__ 静态 dist 压缩包的 OSS 签名 URL(http GET)\nset -euxo pipefail\n\nLOG=/var/log/qianwenai-bootstrap.log\nexec > >(tee -a \"$LOG\") 2>&1\necho \"[$(date -u +%FT%TZ)] === qianwenai nginx (static) bootstrap start ===\"\n\n# 1. 安装 Nginx\nif ! command -v nginx >/dev/null 2>&1; then\n if command -v dnf >/dev/null 2>&1; then dnf install -y nginx\n elif command -v yum >/dev/null 2>&1; then yum install -y nginx\n elif command -v apt-get >/dev/null 2>&1; then apt-get update && apt-get install -y nginx\n else echo \"no supported package manager\"; exit 1\n fi\nfi\n\n# 2. 拉取静态构建产物(若有)\nSTATIC_URL='__STATIC_ARTIFACT_URL__'\nmkdir -p /var/www/static\nif [ -n \"$STATIC_URL\" ]; then\n curl -fsSL \"$STATIC_URL\" -o /tmp/static.tar.gz\n tar -xzf /tmp/static.tar.gz -C /var/www/static --strip-components=0\n rm -f /tmp/static.tar.gz\nelse\n cat > /var/www/static/index.html \u003c\u003c'HTML'\n\u003c!doctype html>\u003cmeta charset=utf-8>\u003ctitle>qianwenai\u003c/title>\n\u003ch1>ECS is up. Awaiting static artifact.\u003c/h1>\nHTML\nfi\n\n# 3. 写站点配置:纯静态托管,无应用反代\ncat > /etc/nginx/conf.d/qianwenai.conf \u003c\u003cNGINX\nserver {\n listen 80 default_server;\n server_name _;\n root /var/www/static;\n index index.html;\n\n location / {\n try_files \\$uri \\$uri/ /index.html;\n }\n\n location = /healthz { return 200 \"ok\\n\"; }\n}\nNGINX\n\n# 移除默认 server(避免冲突)\n[ -f /etc/nginx/conf.d/default.conf ] && mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak || true\n\nnginx -t\nsystemctl enable nginx\nsystemctl restart nginx\n\necho \"[$(date -u +%FT%TZ)] nginx (static) ready\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1825,"content_sha256":"2e537284d3150864739eceeeed94fcd43e9f97e814f11c6d570da35ca47710a7"},{"filename":"templates/userdata/systemd.sh","content":"#!/bin/bash\n# qianwenai · systemd 托管应用\n# 占位符:\n# __APP_ARTIFACT_URL__ 应用产物 tar.gz 的 OSS 签名 URL\n# __APP_RUNTIME__ none | java | node | python\n# __START_COMMAND__ 完整启动命令(相对 /opt/qianwenai),如\n# ./server / \"python3 app.py\" / \"sh -c 'java -jar /opt/qianwenai/*.jar'\" /\n# \"node server.js\" / \"gunicorn -b :8080 app:app\"\n# __APP_PORT__ 应用监听端口\n# __APP_NAME__ 服务名(systemd unit / 日志文件名)\nset -euxo pipefail\n\nLOG=/var/log/qianwenai-bootstrap.log\nexec >> \"$LOG\" 2>&1\necho \"[$(date -u +%FT%TZ)] === qianwenai systemd bootstrap start ===\"\n\nAPP_URL=\"__APP_ARTIFACT_URL__\"\nRUNTIME=\"__APP_RUNTIME__\"\nENTRY=\"__START_COMMAND__\"\nPORT=\"__APP_PORT__\"\nAPP_NAME=\"__APP_NAME__\"\n\n# 1. 安装运行时\ncase \"$RUNTIME\" in\n none)\n : # 无需安装运行时(静态链接二进制、或运行时已存在)\n ;;\n java)\n if ! command -v java >/dev/null 2>&1; then\n if command -v dnf >/dev/null 2>&1; then dnf install -y java-17-openjdk-headless\n else yum install -y java-17-openjdk-headless; fi\n fi\n ;;\n node)\n if ! command -v node >/dev/null 2>&1; then\n # 走发行版自带的、带 GPG 签名校验的包源安装 Node。\n # 顺序:① 直接 dnf install(Alibaba Cloud Linux 3 的 nodejs 20 是 alinux3-updates 里的独立包);\n # ② 独立包不存在时,若有 nodejs 模块流则启用后再装;③ 老系统退回 yum。\n if command -v dnf >/dev/null 2>&1; then\n if ! dnf install -y nodejs npm; then\n if dnf -q module list nodejs >/dev/null 2>&1; then\n dnf -y module reset nodejs || true\n # 优先 20,没有则退回该镜像可用的默认流\n dnf -y module enable nodejs:20 || dnf -y module enable nodejs || true\n dnf install -y nodejs npm\n fi\n fi\n else\n yum install -y nodejs npm\n fi\n fi\n if ! command -v yarn >/dev/null 2>&1; then\n npm install -g yarn --registry=https://registry.npmmirror.com\n fi\n ;;\n python)\n if ! command -v python3 >/dev/null 2>&1; then\n yum install -y python3 python3-pip\n fi\n ;;\n *)\n echo \"[warn] unknown runtime '$RUNTIME', skipping runtime install\"\n ;;\nesac\n\n# 2. 拉产物\nmkdir -p /opt/qianwenai\ncd /opt/qianwenai\ncurl -fsSL \"$APP_URL\" -o app.tar.gz\ntar -xzf app.tar.gz\nrm -f app.tar.gz\n\n# python: 安装依赖\nif [ \"$RUNTIME\" = \"python\" ] && [ -f requirements.txt ]; then\n python3 -m pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com -r requirements.txt\nfi\n# node: 安装依赖(产物已包含 package.json 时)\nif [ \"$RUNTIME\" = \"node\" ] && [ -f package.json ]; then\n yarn install --production --registry=https://registry.npmmirror.com\nfi\n\n# 3. 解析启动命令\n# ENTRY 即「完整启动命令」,是命令的唯一来源;脚本不按 runtime 注入任何解释器,\n# 只把首个 token(argv[0])解析成绝对路径——systemd ExecStart 要求 argv[0] 为绝对路径。\n# 无论 ./server / \"python3 run.py\" / \"java -jar \u003cname>.jar\" / \"gunicorn app:app\",\n# 都按 ENTRY 原样运行。\nset -- $ENTRY\nARGV0=\"$1\"; shift || true\ncase \"$ARGV0\" in\n /*)\n : ;; # 已是绝对路径,原样使用\n */*)\n # 含 / 的相对路径(./server、subdir/app)→ 拼绝对路径;不能走 command -v,它会原样返回相对路径\n ARGV0=\"/opt/qianwenai/${ARGV0#./}\"\n chmod +x \"$ARGV0\" 2>/dev/null || true\n ;;\n *)\n if command -v \"$ARGV0\" >/dev/null 2>&1; then\n ARGV0=\"$(command -v \"$ARGV0\")\" # PATH 上的解释器/工具(python3 / node / java / gunicorn …)\n else\n ARGV0=\"/opt/qianwenai/$ARGV0\" # 产物里的可执行文件(裸文件名,如 server)\n chmod +x \"$ARGV0\" 2>/dev/null || true\n fi ;;\nesac\nEXEC=\"$ARGV0 $*\"\n\n# 4. 写 systemd unit\ncat > /etc/systemd/system/${APP_NAME}.service \u003c\u003cUNIT\n[Unit]\nDescription=${APP_NAME} app\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nWorkingDirectory=/opt/qianwenai\nEnvironment=PORT=${PORT}\nEnvironmentFile=-/etc/qianwenai/db.env\nExecStart=${EXEC}\nRestart=always\nRestartSec=3\nStandardOutput=append:/var/log/${APP_NAME}.log\nStandardError=append:/var/log/${APP_NAME}.log\n\n[Install]\nWantedBy=multi-user.target\nUNIT\n\nsystemctl daemon-reload\nsystemctl enable ${APP_NAME}\nsystemctl restart ${APP_NAME}\n\necho \"[$(date -u +%FT%TZ)] systemd app up\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":4581,"content_sha256":"2ecf704c4389c0e90e33826950467bedbcd859bd407dd550f5f78434ce289acd"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"千问 AI 云部署","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"快速路径","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"路由任务","type":"text","marks":[{"type":"strong"}]},{"text":" — 匹配到 3 种模式之一:全栈部署 · 热更新 · 删除/清理。","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"部署(默认)","type":"text","marks":[{"type":"strong"}]},{"text":" — 严格按步骤 1→14 顺序执行,不跳步/不乱序;门禁与可跳过项见 ","type":"text"},{"text":"reference/rules/rule_interaction.md","type":"text","marks":[{"type":"code_inline"}]},{"text":"「执行顺序」。","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"创建资源前确认费用","type":"text","marks":[{"type":"strong"}]},{"text":" — 人民币(¥)展示小时单价,取得用户确认。","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"记录状态","type":"text","marks":[{"type":"strong"}]},{"text":" — 成功后写入 ","type":"text"},{"text":".qianwenai-deploy","type":"text","marks":[{"type":"code_inline"}]},{"text":"。","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"范围","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"范围内","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"范围外","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"本地项目/Git → 阿里云国内站","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"国际站 → 用 ","type":"text"},{"text":"qwencloud-deploy","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"全栈 ROS 编排、热更新、清理","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"AWS/GCP/Azure/其他云","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ECS + 可选 RDS + OSS + 公网 IP","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"K8s/Serverless/容器编排","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"OAuth/AK 认证(不收集凭证)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"域名/HTTPS(不涉及)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"部署用户提供的代码/项目","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"审查或修改用户代码的业务逻辑、为代码正确性背书","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"关于用户代码","type":"text"}]},{"type":"paragraph","content":[{"text":"本 skill 负责把用户提供的代码/项目构建并部署上线,不审查、不修改其业务逻辑,也不保证代码本身正确。","type":"text"}]},{"type":"paragraph","content":[{"text":"代码的 bug、安全问题及部署上线后由代码引发的后果,由用户自行承担;如需改代码,由用户自行决定并执行。","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"假设","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"aliyun","type":"text","marks":[{"type":"code_inline"}]},{"text":" CLI 3.x 已安装;无有效凭证时按 ","type":"text"},{"text":"reference/deploy/01_env_check.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" 引导认证。","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"默认地域 ","type":"text"},{"text":"cn-hangzhou","type":"text","marks":[{"type":"code_inline"}]},{"text":"。","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"入口路由","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"信号","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"模式","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"存在 ","type":"text"},{"text":".qianwenai-deploy","type":"text","marks":[{"type":"code_inline"}]},{"text":" + 用户说「更新」","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"热更新","type":"text","marks":[{"type":"strong"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"存在 ","type":"text"},{"text":".qianwenai-deploy","type":"text","marks":[{"type":"code_inline"}]},{"text":" + 「删除/清理/释放」","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"删除","type":"text","marks":[{"type":"strong"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Git URL 或本地项目(无已有部署)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"全栈部署","type":"text","marks":[{"type":"strong"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"触发时先展示欢迎话术(见 ","type":"text"},{"text":"reference/rules/rule_interaction.md","type":"text","marks":[{"type":"code_inline"}]},{"text":")。","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"全栈部署(步骤 1–14)","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"阶段 1 · 准备","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"步骤","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"动作","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"参考文档","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"1","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"环境检查","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/01_env_check.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"2","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Git clone(Git URL 时)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/02_git_clone.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"3","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"项目分析","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/03_analyze_project.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"阶段 2 · 资源规划","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"步骤","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"动作","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"参考文档","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"4","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"存量部署扫描","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/04_check_existing.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"5","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"数据库识别","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/05_database.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"6","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ECS 规格选择","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/06_instance_type.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"7","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"生成 ROS 模板","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/07_generate_template.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"8","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"库存检查","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/08_check_stock.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"9","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"模板验证 + 询价确认","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/09_estimate_cost.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"阶段 3 · 执行","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"步骤","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"动作","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"参考文档","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"10","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"上传产物 + 重新生成模板","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/10_upload_artifacts.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"11","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"创建栈","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/11_create_stack.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"12","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"等待终态 + 探活","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/12_wait_stack.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"13","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"记录状态","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/13_record_state.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"14","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"追加应用档案","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/14_app_timeline.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"热更新","type":"text"}]},{"type":"paragraph","content":[{"text":"触发","type":"text","marks":[{"type":"strong"}]},{"text":":存在 ","type":"text"},{"text":".qianwenai-deploy","type":"text","marks":[{"type":"code_inline"}]},{"text":" + 用户想更新代码。IP 不变。","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"步骤","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"动作","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"参考文档","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"U1","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"构建 + 上传新产物","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/10_upload_artifacts.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"U2","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"下发更新(Cloud Assistant)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/hotfix/update_app.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"U3","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"探活 + 更新状态","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/hotfix/update_app.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"U4","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"追加应用档案(","type":"text"},{"text":"event=hotfix","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reference/deploy/14_app_timeline.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"更新脚本模板见 ","type":"text"},{"text":"reference/hotfix/update_recipe.md","type":"text","marks":[{"type":"code_inline"}]},{"text":"。","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"删除 / 清理","type":"text"}]},{"type":"paragraph","content":[{"text":"触发","type":"text","marks":[{"type":"strong"}]},{"text":":用户说「删除」「清理」「释放资源」。","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"⚠️ 不可逆 — 二次确认。含 RDS 时警告数据丢失。","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"🚫 严禁手动逐个删资源,只用 ","type":"text"},{"text":"delete_stack.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":"。","type":"text"}]}]},{"type":"paragraph","content":[{"text":"详见 ","type":"text"},{"text":"reference/cleanup/delete_stack.md","type":"text","marks":[{"type":"code_inline"}]},{"text":"。","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"关键约束","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"约束","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"规则","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"币种","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"人民币(¥)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"认证","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"OAuth(推荐)或 AK/SK,不通过聊天收集凭证","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"模板上传","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"必须 ","type":"text"},{"text":"--TemplateURL","type":"text","marks":[{"type":"code_inline"}]},{"text":"(WAF 拦截 TemplateBody)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"栈名重试","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"复用,绝不重新生成","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"资源删除","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"始终通过 ","type":"text"},{"text":"delete_stack.sh","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"敏感信息","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"分析后检查硬编码密钥并警告","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"命令展示","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"不向用户展示底层命令","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"文件布局","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"scripts/\n generate_template.py upload_artifacts.py\n create_stack.sh record_state.py\n delete_stack.sh update_app.sh\n wait_and_probe.py append_timeline.py\nreference/\n deploy/\n 01_env_check.md ~ 14_app_timeline.md\n hotfix/\n update_app.md update_recipe.md\n cleanup/\n delete_stack.md\n rules/\n rule_interaction.md rule_error_handling.md ram_policies.md\ntemplates/\n ros_single[_rds].yaml\n userdata/{systemd,docker,nginx_proxy,nginx_static,nginx_static_proxy}.sh","type":"text"}]}]},"metadata":{"date":"2026-11-02","name":"qianwenai-deploy","skip":"当用户明确指定 Alibaba Cloud 国际站(alibabacloud.com)、AWS、GCP、Azure 或其它具体云平台时,不要使用本 Skill。","input":"本地项目目录、Git URL,或已有部署状态文件(.qianwenai-deploy)。 可选:用户对实例规格、地域、数据库的偏好。","author":"@skillopedia","output":"一个带公网 IP 的运行中云服务、部署状态文件(.qianwenai-deploy), 以及包含访问地址、费用汇总和后续指引的成功卡片。","source":{"stars":16,"repo_name":"qianwenai-deploy","origin_url":"https://github.com/QianWen-AI/qianwenai-deploy/blob/HEAD/skills/deploy/SKILL.md","repo_owner":"QianWen-AI","body_sha256":"3d1ccc9210204ffd9f78b55d125e9a81b1c15e54b3b692b043456f8c1f5a9320","cluster_key":"783efd3257c12a90b746c84886d505c390a7ef3546ddb56eb9450011844fde1f","clean_bundle":{"format":"clean-skill-bundle-v1","source":"QianWen-AI/qianwenai-deploy/skills/deploy/SKILL.md","text_bytes":175172,"source_commit":"5e476b3d085946f41014094e2e44e7409aa92644","skills_sh_rank":7505,"attachment_count":35,"text_attachments":35,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/deploy/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"2.2","category":"devops-infrastructure","category_label":"DevOps"},"exact_dupes_collapsed_into_this":0},"trigger":"当用户要求把项目部署上云、把应用上线、发布网站、生成访问地址、部署 Git 仓库, 或更新线上版本,且未指定具体云平台时使用;用户提到\"阿里云\"\"Aliyun\"或 \"aliyun.com\"时也使用。","version":"2.2","category":"devops-infrastructure","import_tag":"skills-sh-top20k-2026-11","description":"将本地项目或 Git 仓库一键部署、发布和更新至云端,并生成可访问的线上服务。 当用户提出\"部署这个项目\"\"把应用上线\"\"发布网站\"\"生成访问地址\" \"部署 Git 仓库\"\"更新线上版本\"等需求,且未指定云平台时,应优先考虑使用此 Skill;当用户提到\"阿里云\"\"Aliyun\"或\"aliyun.com\"时,应优先使用。 本 Skill 部署至阿里云国内站(aliyun.com),支持全栈部署、ROS 资源编排、 云资源自动创建、部署前询价确认、服务探活、部署状态记录和热更新。 如果用户明确指定 Alibaba Cloud 国际站(alibabacloud.com)或其他云平台, 则不要使用此 Skill。","prerequisites":["已安装并以 OAuth 模式配置国内站凭证的 aliyun CLI 3.x"]}},"renderedAt":1793671865233}

千问 AI 云部署 快速路径 1. 路由任务 — 匹配到 3 种模式之一:全栈部署 · 热更新 · 删除/清理。 2. 部署(默认) — 严格按步骤 1→14 顺序执行,不跳步/不乱序;门禁与可跳过项见 「执行顺序」。 3. 创建资源前确认费用 — 人民币(¥)展示小时单价,取得用户确认。 4. 记录状态 — 成功后写入 。 范围 | 范围内 | 范围外 | |--------|--------| | 本地项目/Git → 阿里云国内站 | 国际站 → 用 | | 全栈 ROS 编排、热更新、清理 | AWS/GCP/Azure/其他云 | | ECS + 可选 RDS + OSS + 公网 IP | K8s/Serverless/容器编排 | | OAuth/AK 认证(不收集凭证) | 域名/HTTPS(不涉及) | | 部署用户提供的代码/项目 | 审查或修改用户代码的业务逻辑、为代码正确性背书 | 关于用户代码 本 skill 负责把用户提供的代码/项目构建并部署上线,不审查、不修改其业务逻辑,也不保证代码本身正确。 代码的 bug、安全问题及部署上线后由代码引发的后果,由用户自行承担;如需改代码,由用户自行决定并执行。 假设 - CLI 3.x 已安装;无有效凭证时按 引导认证。 - 默认地域 。 --- 入口路由 | 信号 | 模式 | |------|------|…