# proxy_init **Repository Path**: self_5/proxy_init ## Basic Information - **Project Name**: proxy_init - **Description**: 使用aliyun服务器,自动部署不同区域的sing-box服务 - **Primary Language**: Python - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-05-05 - **Last Updated**: 2026-05-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # proxy_init > 阿里云轻量应用服务器(SWAS)代理服务器快速初始化工具 一键完成从 **购买服务器 → 配置代理 → 生成订阅链接** 的全流程自动化,无需手动登录控制台。 支持**断点续跑**(幂等性),任意步骤失败后修复问题重跑,自动跳过已完成步骤。 --- ## 目录 - [功能概览](#功能概览) - [支持的代理协议](#支持的代理协议) - [前置要求](#前置要求) - [快速开始](#快速开始) - [配置说明](#配置说明) - [运行](#运行) - [teardown:退订与清理](#teardown退订与清理) - [工作流程详解](#工作流程详解) - [可选功能](#可选功能) - [常见问题](#常见问题) - [目录结构](#目录结构) --- ## 功能概览 | 步骤 | 操作 | 是否幂等 | |------|------|---------| | Step 1 | 创建阿里云指定区域的 SWAS 轻量服务器 | ✅ | | Step 1b | 通过 API 重置 root 密码,重启实例 | ✅ | | Step 2 | 开放防火墙端口(TCP + UDP) | ✅ | | Step 3 | 更新 Cloudflare DNS A 记录 | ✅ | | Step 4 | 渲染并上传 sing-box `config.json` | ✅ | | Step 5 | 渲染并执行服务器初始化脚本 `init.sh` | ✅ | | Step 6+7 | 生成 v2ray 订阅文件(Base64)并上传 | ✅ | **特性亮点:** - 🔁 **断点续跑**:状态持久化到 `.proxy_init_state.json`,重跑自动跳过已完成步骤 - ⚙️ **配置与代码分离**:所有参数通过 `config.yaml` 管理,敏感凭证通过 `.env` 注入 - 🧩 **可选模块**:WARP 出口、上游 SOCKS5 代理、源服务器同步均可独立开关 - 📄 **模板驱动**:sing-box 配置、订阅链接、初始化脚本均使用 Jinja2 模板,修改无需改代码 - 🗑️ **一键清理**:`teardown` 子命令退订实例并删除 DNS 解析 --- ## 支持的代理协议 服务器初始化后,以下协议开箱即用: | 协议 | 端口 | 传输层 | |------|------|--------| | Mixed(HTTP + SOCKS5) | 4000 | TCP | | Naive(HTTPS) | 4001 | TLS | | VMess | 4002 | WebSocket + TLS | | VLESS | 4003 | WebSocket + TLS | | Hysteria2 | 4004 | UDP(QUIC) | | Trojan | 4005 | TLS | | TUIC v5 | 4006 | UDP(QUIC) | | VLESS + XTLS-Reality | 4007 | TCP(无需域名证书)| --- ## 前置要求 ### 账号与权限 | 平台 | 需要的权限 | |------|-----------| | 阿里云 | RAM 子账号,需要 SWAS 全权限 + BSS 退款权限 | | Cloudflare | API Token,权限:`Zone → DNS → Edit` | ### 本地环境 - **Python 3.11+** - **[uv](https://docs.astral.sh/uv/)** 包管理器 ```bash # 安装 uv(macOS / Linux) curl -LsSf https://astral.sh/uv/install.sh | sh # 或 Homebrew brew install uv ``` --- ## 快速开始 ### 1. 克隆仓库 ```bash git clone cd proxy_init ``` ### 2. 安装依赖 ```bash uv sync ``` ### 3. 配置凭证 ```bash cp .env.example .env ``` 编辑 `.env`,填写真实值: ```dotenv # 阿里云访问凭证 ALIYUN_ACCESS_KEY_ID=your_access_key_id ALIYUN_ACCESS_KEY_SECRET=your_access_key_secret # Cloudflare 访问凭证(需要 Zone/DNS/Edit 权限) CF_API_TOKEN=your_cloudflare_api_token CF_ZONE_ID=your_cloudflare_zone_id CF_ACCOUNT_ID=your_cloudflare_account_id # 服务器 SSH 登录密码(API 重置后的登录密码) # 要求:8~30 位,同时含大小写字母和数字 SERVER_SSH_PASSWORD=Your$tr0ngP@ssword ``` ### 4. 修改配置 编辑 `config.yaml`(重点字段): ```yaml aliyun: region: "ap-northeast-1" # 目标区域(见下方区域列表) server: image_id: "..." # 系统镜像 ID(在控制台创建实例页面查询) plan_id: "..." # 套餐 ID cloudflare: domains: - name: "jp-vm1.example.com" # 你的完整域名(需已在 Cloudflare 托管) singbox: proxy_username: "your_username" # 代理用户名 proxy_password: "your_password" # 代理密码 uuid: "your-uuid-here" # 建议用 uuidgen 生成 server_init: hostname: "jp-vm1" # 服务器主机名 cert_domain: "jp-vm1.example.com" # SSL 证书域名(与 cloudflare.domains[0] 一致) acme_email: "you@example.com" # Let's Encrypt 注册邮箱 subscribe: node_prefix: "jp-ali" # 订阅节点名称前缀 ``` ### 5. 运行 ```bash uv run python main.py init ``` 全流程约 **5~10 分钟**(主要耗时为证书申请和软件安装)。 --- ## 配置说明 ### 阿里云常用区域 | 区域 ID | 地理位置 | |---------|---------| | `ap-southeast-1` | 新加坡 | | `ap-northeast-1` | 日本(东京) | | `cn-hongkong` | 中国香港 | | `ap-southeast-5` | 印度尼西亚(雅加达) | | `us-west-1` | 美国(硅谷) | | `eu-central-1` | 德国(法兰克福) | ### 完整配置参考(config.yaml) ```yaml aliyun: region: "ap-northeast-1" server: image_id: "e9363571cf2444aba422b17470285465" # Ubuntu 22.04 plan_id: "swas.s.c2m05s20b1.linux" period: 1 # 购买时长(月) charge_type: "PrePaid" # PrePaid(包年包月)| PostPaid(按量) auto_renew: false firewall_ports: - "4000/4006" # sing-box 入站端口范围(含 Mixed/Naive/VMess/VLESS/Hysteria2/Trojan/TUIC) - "4007" # VLESS-Reality - "80" - "443" cloudflare: ttl: 60 domains: - name: "jp-vm1.example.com" proxied: false # 代理协议不建议开启 Cloudflare 代理 singbox: proxy_username: "your_username" proxy_password: "your_password" uuid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" reality: server_name: "www.microsoft.com" private_key: "your_reality_private_key" public_key: "your_reality_public_key" warp: enabled: true # false → 不生成 WARP 出口(见「可选功能」) private_key: "your_warp_private_key" address: - "172.16.0.2/32" - "2606:4700:110:85fa:xxxx:xxxx:xxxx:xxxx/128" upstream_socks: enabled: true # false → 不生成上游 SOCKS5 出口(见「可选功能」) server: "another-server.example.com" port: 4000 server_init: hostname: "jp-vm1" ssh_user: "root" ssh_port: 22 sync_from_source: false # true → 从已有服务器 rsync 配置文件 source_server_ip: "" # sync_from_source=true 时填写源服务器 IP swap_size_mb: 512 acme_email: "you@example.com" cert_domain: "jp-vm1.example.com" subscribe: filename: "sub.txt" remote_dir: "/usr/local/openresty/nginx/html/sub" node_prefix: "jp-ali" state: file: ".proxy_init_state.json" retry: instance_start_timeout: 300 # 等待实例 Running 的超时(秒) instance_poll_interval: 15 ssh_connect_timeout: 120 # SSH 首次连接重试总时长(秒) ssh_connect_interval: 10 ``` > **Reality 密钥对生成**: > ```bash > sing-box generate reality-keypair > ``` --- ## 运行 ### 基本命令 ```bash # 全流程初始化 uv run python main.py init # 详细日志(便于调试) uv run python main.py init -v # 预览模式:仅渲染模板,不调用任何 API uv run python main.py init --dry-run # 使用自定义配置文件 uv run python main.py -c my_config.yaml init # 清除状态重新开始(⚠️ 危险:若实例已创建,可能产生重复计费) uv run python main.py init --reset-state ``` ### 断点续跑 脚本任意步骤失败后,修复问题直接重跑即可,已完成的步骤会自动跳过: ``` 2026-05-05 13:30:52 INFO [Step 1] SKIP — instance already created: c574f5af (47.74.32.136) 2026-05-05 13:30:52 INFO [Step 1b] SKIP — password already reset. 2026-05-05 13:30:52 INFO [Step 2] SKIP — ports already opened. ... 2026-05-05 13:30:54 INFO [Step 5] Running server initialisation … ``` 状态记录在 `.proxy_init_state.json`(已加入 `.gitignore`)。 --- ## teardown:退订与清理 ```bash # 退订实例 + 删除 Cloudflare DNS 解析(完整清理) uv run python main.py teardown --instance-id # 只删除 DNS 解析,不退订实例 uv run python main.py teardown --instance-id --skip-refund # 只退订实例,不删除 DNS uv run python main.py teardown --instance-id --skip-dns ``` > **实例 ID** 可在阿里云控制台或 `.proxy_init_state.json` 中查看。 --- ## 工作流程详解 ``` ┌──────────────────────────────────────────────────────────┐ │ proxy_init pipeline │ └──────────────────────────────────────────────────────────┘ Step 1 ──► 创建 SWAS 实例(CreateInstancesRequest) 等待状态变为 Running(轮询 ListInstancesRequest) 获取公网 IP(ListInstancesRequest) Step 1b ──► API 重置 root 密码(UpdateInstanceAttributeRequest) 重启实例(RebootInstanceRequest) 等待再次 Running Step 2 ──► 开放防火墙端口(CreateFirewallRulesRequest,TCP+UDP) Step 3 ──► Cloudflare DNS upsert A 记录(cf.dns.records API) Step 4 ──► Jinja2 渲染 config.json.j2 SSH 密码登录 → 上传到 /etc/sing-box/config.json Step 5 ──► Jinja2 渲染 init.sh.j2 SSH 上传到 /tmp/proxy_init.sh → bash 执行(约 3~5 分钟) │ ├─ 卸载阿里云监控/安全/云助手控件 ├─ 优化 journal 日志、创建 Swap ├─ 安装 sing-box(官方 deb 仓库) ├─ 安装 OpenResty(nginx 高性能版) └─ 安装 acme.sh,申请 Let's Encrypt 证书(Cloudflare DNS-01) Step 6+7 ──► Jinja2 渲染 subscribe.txt.j2(7 协议链接 → Base64) SSH 上传订阅文件到 nginx 静态目录 完成后,订阅链接:https:///sub/sub.txt ``` --- ## 可选功能 ### WARP 出口(全局流量走 Cloudflare WARP) 在 `config.yaml` 中配置: ```yaml singbox: warp: enabled: true # ← 改为 false 则不生成 endpoints 段 private_key: "..." address: - "172.16.0.2/32" - "2606:4700:xxxx/128" ``` > WARP 私钥获取:使用 [warp-reg](https://github.com/badafans/warp-reg) 或任意 WARP 客户端注册账号。 ### 上游 SOCKS5 代理(AI 域名走另一台服务器) ```yaml singbox: upstream_socks: enabled: true # ← 改为 false 则不路由 AI 域名 server: "us-server.example.com" port: 4000 ``` 启用后,以下域名自动路由到上游代理:`openai`、`chatgpt`、`gemini`、`claude`、`anthropic`、`groq` 等。 ### 从源服务器同步配置(不手动配置 nginx) 如果你已有一台配置好的服务器,可开启同步,将 nginx 配置和静态文件 rsync 到新服务器: ```yaml server_init: sync_from_source: true source_server_ip: "1.2.3.4" # 已有服务器的 IP ``` --- ## 常见问题 ### Q: Step 5 执行 init.sh 报错 exit 1 或 exit 2? 查看完整输出日志定位具体失败步骤。常见原因: | 现象 | 原因 | 解决方案 | |------|------|---------| | `acme.sh --issue` 失败 | DNS 未传播 / CF Token 权限不足 | 检查 `.env` 中 `CF_API_TOKEN` 和 `CF_ZONE_ID` | | SSH 连接超时 | 实例刚启动,SSH 服务未就绪 | 脚本会自动重试,等待即可(最多 120 秒)| | `sing-box` 启动失败 | `config.json` 证书路径不存在 | 确保 Step 5 中证书申请成功 | ### Q: 如何重新执行某个步骤? 直接编辑 `.proxy_init_state.json`,将对应步骤改为 `false`,重新运行即可: ```json { "instance_id": "c574f5afcc4d484a82ba1be03519360b", "instance_ip": "47.74.32.136", "password_reset": true, "ports_opened": true, "dns_updated": true, "config_synced": true, "server_initialized": false, ← 改为 false,重新执行 Step 5 "subscribe_uploaded": false } ``` ### Q: 实例 image_id / plan_id 如何查询? 在阿里云控制台 → **轻量应用服务器** → 创建实例页面选好配置后,从 URL 或 API 获取。 也可通过 SWAS API `DescribeInstanceImages` 和 `DescribeInstancePlans` 查询(需要指定 region)。 ### Q: Cloudflare Token 需要哪些权限? 最小权限:`Zone → DNS → Edit`(仅允许修改 DNS 记录)。 不需要 `Zone Settings Edit` 或 `Zone Write`。 ### Q: 订阅文件访问 403? 检查 OpenResty nginx 配置中 `/sub/` 目录是否有正确的 `root` 路径和读取权限。 如果 `sync_from_source: false`,需要手动配置 nginx.conf。 --- ## 目录结构 ``` proxy_init/ ├── main.py # 主入口(子命令:init / teardown) ├── config.yaml # 主配置文件 ├── pyproject.toml # uv 项目配置与依赖 ├── .env.example # 环境变量模板 ├── .proxy_init_state.json # 断点续跑状态(自动生成,勿手动删除) │ ├── src/ │ ├── config.py # AppConfig dataclasses + YAML/ENV 加载 │ ├── state.py # StateManager(JSON 持久化,幂等核心) │ ├── aliyun.py # AliyunSwasManager(SWAS + BSS API) │ ├── cloudflare_mgr.py # CloudflareManager(DNS upsert / delete) │ ├── template_engine.py # TemplateEngine(Jinja2 渲染) │ └── ssh_client.py # SSHClient(密码认证,连接重试,exec,SFTP) │ ├── templates/ │ ├── config.json.j2 # sing-box 代理配置模板 │ ├── subscribe.txt.j2 # v2ray 订阅链接模板(7 协议) │ └── init.sh.j2 # 服务器初始化脚本模板 │ └── prompts/ # 开发文档 ├── proxy_init_project_prompt.md # LLM 上下文提示词 └── workthrough.md # 功能分析文档 ``` --- ## License MIT