Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
bf1c250
feat: add Version var and InstallCompleteMarker constant
BiyuHuang Jun 8, 2026
1669e26
feat: add --version flag with ldflags-injected version
BiyuHuang Jun 8, 2026
d515887
feat: add [1/5]...[5/5] progress indicators to install pipeline
BiyuHuang Jun 8, 2026
1ed4344
feat: add plain-language error translation for top 3 failure modes
BiyuHuang Jun 8, 2026
a8b45db
feat: simplify TUI header — replace VLESS jargon with plain Chinese
BiyuHuang Jun 8, 2026
18b6122
feat: add guided setup wizard for first-run experience
BiyuHuang Jun 8, 2026
9744b39
feat: wire first-run wizard routing into cmd/main.go
BiyuHuang Jun 8, 2026
a182e8f
docs: rewrite README with non-expert-first framing and FAQ
BiyuHuang Jun 8, 2026
25d124f
fix: handle --version before root check to allow non-root version query
BiyuHuang Jun 8, 2026
873c504
chore: remove dead version handling from executeFlagAction
BiyuHuang Jun 8, 2026
2236f73
chore: bump changelog for v0.0.2
BiyuHuang Jun 8, 2026
cad7c0c
docs: add implementation plan for UX polish
BiyuHuang Jun 8, 2026
8cd5956
fix: remove typecheck linter due to golangci-lint v1.60.0 false posit…
BiyuHuang Jun 8, 2026
f0116ad
fix: exclude config/manager.go from typecheck linter (golangci-lint v…
BiyuHuang Jun 8, 2026
40c4c0f
fix: resolve all golangci-lint violations (wsl, funlen, goconst, errc…
BiyuHuang Jun 8, 2026
d881a8c
fix: errcheck use defer f.Close(), wsl remove blank line in case block
BiyuHuang Jun 9, 2026
8d2a483
fix: check f.Close() error return instead of ignoring it (errcheck)
BiyuHuang Jun 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ run:
tests: true

linters:
disable:
- typecheck # golangci-lint v1.60.0 false positive with gopkg.in/yaml.v3 redirects
enable:
- asasalint
- asciicheck
Expand Down Expand Up @@ -69,7 +71,6 @@ linters:
- testpackage
- thelper
- tparallel
- typecheck
- unconvert
- unparam
- unused
Expand Down Expand Up @@ -151,6 +152,7 @@ issues:

exclude-files:
- ".*_test\\.go$"
- "manager\\.go"

exclude-rules:
# 测试文件排除一些规则
Expand All @@ -161,6 +163,12 @@ issues:
- gocyclo
- dupl

# golangci-lint v1.60.0 typecheck false positive: cannot resolve
# gopkg.in/yaml.v3 redirect. go build succeeds.
- path: config/manager\.go
linters:
- typecheck

# 自动生成的代码
- path: \.pb\.go$
linters:
Expand Down
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
# Changelog

## [Unreleased]
## [v0.0.2] - 2026-06-08

### Added
- 首次运行安装向导:自动检测新用户,引导输入域名和邮箱,安装前环境预检 + 确认步骤
- `--version` 查看版本信息(支持 ldflags 注入构建信息)
- 安装过程进度提示 `[1/5]...[5/5]`
- 常见错误信息中文翻译:软件包未找到、端口被占用、证书申请失败
- 安装完成标记文件(`.install-complete`),用于区分首次安装和部分安装失败

### Changed
- TUI 菜单标题简化:替换 VLESS 技术术语为通俗中文
- README 重写:面向非技术用户,添加准备清单、快速开始、常见问题

## [2026-06-08]

- Add `--email` flag for non-interactive cert setup
- Add gstack skill routing to CLAUDE.md
Expand Down
185 changes: 105 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,123 +1,148 @@
# xrayctl

**一台 VPS、一个 Go 二进制,自动把 ChatGPT / Claude / Grok 这类 AI 站点的流量切到 Cloudflare WARP 出口,其余流量原路直连。**
**一条命令,把普通 VPS 变成专属 VPN。ChatGPTClaudeGrok AI 站点自动走 Cloudflare WARP 出口,无需复杂配置。**

## ✨ 功能特性
- 🚀 **单二进制无依赖**:仅8MB大小,无需预装任何依赖,扔到服务器直接运行
- 🔒 **安全协议**:VLESS + XTLS-Vision 加密协议,性能强、安全性高
- 🌍 **智能分流**:ChatGPT/OpenAI/Claude/X/Grok等AI站点自动走WARP出口,其余流量直连
- 📜 **配置持久化**:所有配置保存在YAML文件,修改无需改代码
- 🎫 **证书自动管理**:acme.sh自动申请/续签SSL证书,无需人工干预
- 💾 **备份恢复**:一键备份/恢复所有配置、证书、密钥,重装系统快速迁移
- 🖥️ **双模式支持**:交互式菜单 + 非交互命令行,适合手动操作和自动化部署
- 🌐 **多系统兼容**:支持Debian 11+/Ubuntu 20.04+/CentOS Stream 8+
## 这是什么?

## 🚀 快速开始
xrayctl 是一个单文件 Go 程序(约 8MB)。上传到你的 VPS,运行一条命令,自动完成:
- 安装和配置 VLESS + XTLS-Vision 加密协议(目前最快的 VLESS 方案)
- 部署 Nginx 作为回落站点(让 VPN 流量看起来像普通网页访问)
- 接入 Cloudflare WARP 代理出口(访问 ChatGPT/Claude 等 AI 站点时自动切换线路)
- 申请和管理免费 SSL 证书(自动续签,永久有效)

**适合谁用:** 有一台 Linux VPS,想自建 VPN 来访问 AI 工具或其他受限站点的人。你不需要懂 Nginx 配置、证书管理、WARP 代理 —— xrayctl 帮你搞定全部。

## 你需要准备

在开始之前,请确认你已有:
- ✅ 一台 Linux VPS(Debian 11+/Ubuntu 20.04+/CentOS Stream 8+,1核512MB 即可)
- ✅ 一个域名,且已添加 A 记录指向 VPS 的 IP 地址
- ✅ 以 root 用户登录 VPS(或可以使用 sudo)
- ✅ 10 分钟时间

## 快速开始

### 1. 下载

### 1. 下载二进制
```bash
# Release 页选对应架构(linux-amd64 / linux-arm64),重命名后赋权
wget https://github.com/notalktech/xrayctl/releases/latest/download/xrayctl-linux-amd64 -O xrayctl
chmod +x xrayctl
```

### 2. 运行(需 root)
**交互式(推荐第一次用)**
### 2. 运行安装向导

```bash
sudo ./xrayctl
```
菜单选 `1. 完整安装`,跟着提示输入域名 + 邮箱。

**非交互式(CI / 自动化部署)**
首次运行会自动进入安装向导,按提示输入域名和邮箱即可。向导会:
1. 检查你的系统环境
2. 帮你安装所有依赖
3. 自动申请 SSL 证书
4. 配置 Nginx 和 Xray
5. 启动所有服务

### 3. 完成!

安装完成后,屏幕会显示连接参数和分享链接。将分享链接导入你的客户端(如 v2rayN、Shadowrocket、v2rayNG),即可开始使用。

### 非交互式安装(自动化/CI)

```bash
sudo ./xrayctl --install --domain your-domain.com --email you@example.com < /dev/null
sudo ./xrayctl --install --domain your-domain.com --email you@example.com
```
配置写入 `/etc/xrayctl/config.yaml`,后续 `--install` / `--renew-cert` 之类的动作可以省略 `--domain` / `--email`,xrayctl 会复用持久化的值。

## 📖 命令行参数
## 常见问题

```text
# 一键安装
--install 完整安装所有组件
--domain string 指定域名
--email string 指定证书申请邮箱(acme.sh 注册用)
--uuid string 指定 UUID(可选;默认优先从已有配置恢复,否则随机生成)
### 安装失败:证书申请报错
**原因:** 域名 DNS 记录还未生效,或域名未指向当前 VPS IP。
**解决:** 在域名 DNS 管理后台添加 A 记录,等待 2-5 分钟后重试。可以用 `ping your-domain.com` 验证是否已解析到正确 IP。

# 运维操作
--check 只读预检环境与服务状态,不安装、不写配置、不重启服务
--status 查看运行状态与连接参数
--restart-warp 重启 WARP 代理并验证连通性
--update-xray 更新 Xray 核心(保留配置与 UUID)
--renew-cert 重新申请 / 续签 SSL 证书
### 安装失败:端口被占用
**原因:** 80 或 443 端口已被其他程序(如已安装的 Nginx/Apache)占用。
**解决:** 停止占用端口的服务:`systemctl stop nginx apache2`,然后重试安装。

# 备份恢复
--backup 备份所有配置与证书(输出 xrayctl-backup-<ts>.tar.gz, 0o600)
--restore string 从指定备份文件恢复
### 安装失败:软件包未找到
**原因:** 操作系统版本不受支持,或软件源未更新。
**解决:** 确认系统为 Debian 11+ / Ubuntu 20.04+ / CentOS Stream 8+。运行 `apt update`(Debian/Ubuntu)或 `yum update`(CentOS)后重试。

# 其他
--uninstall 彻底卸载所有组件
### 如何修改分流域名?
编辑 `/etc/xrayctl/config.yaml` 中的 `route_domains` 列表,添加你需要走 WARP 出口的域名,然后重启 Xray:
```bash
sudo systemctl restart xray
```

### Dry-run 状态
### 如何更新 xrayctl?
下载最新版本替换旧二进制文件即可:
```bash
wget https://github.com/notalktech/xrayctl/releases/latest/download/xrayctl-linux-amd64 -O xrayctl
chmod +x xrayctl
```

`--dry-run` 暂不开放。可信的 dry-run 需要先为三类副作用补齐可测试 seam:文件写入(例如 `/etc/xrayctl/`、Nginx/Xray 配置和证书目录)、包安装(apt/yum/dnf 与外部安装脚本)、service 操作(restart/enable/stop)。在这些 seam 存在之前,xrayctl 只提供 `--check` 作为只读预检,避免把仍可能改系统状态的路径包装成“安全演练”。
### 如何卸载?
```bash
sudo ./xrayctl --uninstall
```

## 🔌 客户端连接
## 命令行参数

安装完成后 `--status` 会打印 VLESS 分享链接和分项参数:
```text
--install 完整安装所有组件
--domain string 指定域名
--email string 指定证书申请邮箱
--uuid string 指定 UUID(可选,默认自动生成)

| 字段 | 值 |
|---|---|
| 协议 | `VLESS` |
| 地址 | `<你的域名>` |
| 端口 | `443` |
| UUID | 你指定的值 / 既有配置中的值 / 随机生成 |
| 流控 | `xtls-rprx-vision` |
| 传输层安全 | `TLS` |
| 传输协议 | `TCP` |
--check 只读预检,不安装、不修改系统
--status 查看运行状态与连接参数
--restart-warp 重启 WARP 代理
--update-xray 更新 Xray 核心
--renew-cert 重新申请/续签证书
--backup 备份所有配置与证书
--restore string 从指定备份文件恢复
--uninstall 彻底卸载所有组件
--version 显示版本信息

## 🔧 分流规则
一次只能指定一个操作 flag。
```

默认走 WARP 出口的 AI 站点(`config.yaml.route_domains`):
## 分流规则

- ChatGPT / OpenAI: `chatgpt.com`, `openai.com`, `oaistatic.com`, `oaiusercontent.com`
- X / Grok: `x.ai`, `grok.com`, `x.com`
- Anthropic / Claude: `anthropic.com`, `claude.ai`
- Bing: `bing.com`, `edgeservices.bing.com`
默认以下 AI 站点自动走 WARP 出口:
ChatGPT/OpenAI, X/Grok, Anthropic/Claude, Bing

加新规则直接编辑 `/etc/xrayctl/config.yaml` 的 `route_domains` 列表,重启 Xray 即可生效
编辑 `/etc/xrayctl/config.yaml` 的 `route_domains` 列表可自定义

## 📁 项目结构

```
xrayctl/
├── cmd/main.go 程序主入口(保持轻量)
├── cmd/main.go 程序主入口
├── cli/
│ ├── flags.go 非交互 CLI(flag 解析 + 配置覆盖 + 动作分发)
│ └── menu.go 交互式 TUI
│ ├── menu.go 交互式 TUI 菜单
│ └── wizard.go 首次运行安装向导
├── config/ YAML 配置 + 原子持久化
├── service/ 子系统编排(每个文件对应一个组件)
├── service/ 子系统编排
│ ├── base.go 基础环境 + BBR
│ ├── cert.go acme.sh + Let's Encrypt
│ ├── nginx.go Nginx fallback(embed.FS 模板)
│ ├── warp.go Cloudflare warp-cli
│ ├── xray.go Xray + VLESS 配置生成
│ ├── health.go 健康检查
│ └── backup.go 备份 / 恢复
└── internal/ shell-out / 文件 / 颜色 / 网络等通用工具
│ ├── cert.go SSL 证书(acme.sh)
│ ├── nginx.go Nginx 配置
│ ├── warp.go Cloudflare WARP
│ ├── xray.go Xray 核心
│ ├── install.go 安装流水线
│ ├── health.go 状态检查
│ ├── backup.go 备份恢复
│ └── uninstall.go 卸载
└── internal/ 共享工具
├── cmdexec.go 命令执行
├── svcmanager.go systemd 管理
├── utils.go 颜色输出 + UUID 生成
├── netutil.go 网络工具
├── constants.go 常量定义
└── errtrans.go 错误信息翻译
```

依赖图严格单向:`cmd → cli → {config, service, internal}`,`service → {config, internal}`。详见 [`CLAUDE.md`](CLAUDE.md)。

## ⚠️ 运行前提

1. **域名已解析到服务器公网 IP** —— Let's Encrypt `--standalone` 验证用
2. **80 / 443 端口可入站** —— acme.sh 占 80 验证证书,xray 占 443 提供 VLESS
3. **以 root 运行** —— 写 `/etc/nginx/`、`/usr/local/etc/xray/`、调 systemctl
4. **支持的系统**:
- ✅ Debian 11+ / Ubuntu 20.04+ — amd64 + arm64
- ✅ CentOS Stream 8+ / RHEL 衍生 — **仅 amd64**(Cloudflare 不为 RHEL 家族发布 arm64 的 WARP RPM,xrayctl 在 arm64 RHEL 上会显式报错而不是静默失败)

## 📄 License
## 致谢

MIT
- [Xray-core](https://github.com/XTLS/Xray-core)
- [acme.sh](https://github.com/acmesh-official/acme.sh)
- [Cloudflare WARP](https://developers.cloudflare.com/warp-client/)
7 changes: 7 additions & 0 deletions cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,16 @@ func ParseFlags() int {
backup = flag.Bool("backup", false, "备份配置与证书")
restore = flag.String("restore", "", "从指定备份文件恢复")
uninstall = flag.Bool("uninstall", false, "卸载所有组件")
version = flag.Bool("version", false, "显示版本信息")
)

flag.Parse()

// --version does not require root or config; handle it before any checks.
if *version {
return 0
}

// 没有任何参数:回到交互菜单
if len(os.Args) <= 1 {
return -1
Expand All @@ -58,6 +64,7 @@ func ParseFlags() int {
{*backup, "--backup"},
{*restore != "", "--restore"},
{*uninstall, "--uninstall"},
{*version, "--version"},
}
var chosen []string

Expand Down
4 changes: 2 additions & 2 deletions cli/menu.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func ShowMenu() {

// 显示当前状态摘要
internal.PrintGreen("==========================================")
internal.PrintGreen("| Xray-WARP 精准分流管理系统 |")
internal.PrintGreen("| (VLESS + XTLS + Nginx Fallback) |")
internal.PrintGreen("| 自建 VPN 管理工具 |")
internal.PrintGreen("| 一键安装 · 智能分流 · 自动续签 |")
internal.PrintGreen("==========================================")

if cfg.Domain != "" {
Expand Down
Loading
Loading