3x-ui/docs/install-logic.md
root f5862abc2e feat: add CodeMirror YAML editor for Clash template and fix settings save button bug
- Replace plain textarea with CodeMirror editor (YAML syntax highlighting, line numbers, auto-indent) for Clash subscription template
- Fix confAlerts crash when subClashURI/subURI/subJsonURI is null/undefined (prevented save button from enabling)
- Add yaml.js CodeMirror mode asset
- Include docs and .gitignore cleanup
2026-04-24 16:15:22 +08:00

15 KiB
Raw Blame History

install.sh 逻辑文档

概述

install.sh 是 3x-ui 面板的安装脚本,负责在 Linux 服务器上完成以下工作:

  1. 安装系统依赖包
  2. 下载并解压 3x-ui 发行版
  3. 配置 systemd / OpenRC 服务
  4. 生成随机凭据用户名、密码、端口、Web 路径)
  5. 配置 SSL 证书Let's Encrypt 域名证书、IP 证书、或自定义证书)
  6. 显示安装结果和访问信息

全局配置

颜色变量

变量 用途
red \033[0;31m 红色文本
green \033[0;32m 绿色文本
blue \033[0;34m 蓝色文本
yellow \033[0;33m 黄色文本
plain \033[0m 重置颜色

路径变量

变量 默认值 说明
xui_folder /usr/local/x-ui x-ui 安装目录
xui_service /etc/systemd/system systemd 服务文件目录

可通过环境变量 XUI_MAIN_FOLDERXUI_SERVICE 覆盖。


入口流程

install.sh 被执行
  ├─ 检查 root 权限
  ├─ 检测操作系统发行版
  ├─ 检测 CPU 架构
  ├─ install_base()          ← 安装系统依赖
  └─ install_x-ui($1)        ← 主安装逻辑($1 为可选的版本号)

函数详解

1. root 权限检查(第 14-15 行)

检查 $EUID 是否为 0。非 root 用户直接退出并提示使用 root 权限。

2. 操作系统检测(第 17-28 行)

读取 /etc/os-release/usr/lib/os-release,将 $ID 赋值给 release 变量。

支持的发行版:

包管理器 发行版
apt ubuntu, debian, armbian
dnf fedora, amzn, virtuozzo, rhel, almalinux, rocky, ol
yum centos 7
pacman arch, manjaro, parch
zypper opensuse-tumbleweed, opensuse-leap
apk alpine

3. arch() — CPU 架构检测(第 30-41 行)

通过 uname -m 映射到标准架构标识:

uname -m 输出 返回值
x86_64, x64, amd64 amd64
i*86, x86 386
armv8*, arm64, aarch64 arm64
armv7*, arm armv7
armv6* armv6
armv5* armv5
s390x s390x
其他 退出报错

4. IP/域名验证函数(第 46-57 行)

函数 逻辑
is_ipv4() 正则匹配 数字.数字.数字.数字 格式
is_ipv6() 检查字符串是否包含 :
is_ip() 调用 is_ipv4is_ipv6
is_domain() 正则匹配标准域名格式(含国际化域名 xn-- 支持)

5. is_port_in_use() — 端口占用检测(第 60-74 行)

按优先级尝试三种方式:

  1. ss -ltn — 检查监听端口
  2. netstat -lnt — 回退方案
  3. lsof -nP -iTCP:端口 -sTCP:LISTEN — 最后手段

任一命中即返回 0端口被占用

6. install_base() — 安装基础依赖(第 76-104 行)

根据 $release 使用对应的包管理器安装以下公共依赖:

curl, tar, tzdata, socat, ca-certificates, openssl

额外安装 cron(用于 acme.sh 自动续期,仅 apt 系列)。

  • CentOS 7 使用 yum,其他版本使用 dnf
  • 未识别的发行版默认回退到 apt-get

7. gen_random_string(length) — 随机字符串生成(第 106-111 行)

openssl rand -base64(length*2) → 过滤 a-zA-Z0-9 → 截取前 length 个字符

用于生成用户名、密码、Web 路径等随机值。

8. install_acme() — 安装 acme.sh第 113-124 行)

curl -s https://get.acme.sh | sh

安装到 ~/.acme.sh/ 目录。失败返回 1。


SSL 证书管理

9. setup_ssl_certificate(domain, server_ip, port, webBasePath) — 域名 SSL第 126-191 行)

用途:为域名签发 Let's Encrypt 证书。

流程

检查 acme.sh 是否已安装
  ├─ 未安装 → 调用 install_acme()
  └─ 已安装 → 继续

创建证书目录:/root/cert/${domain}/

签发证书:
  acme.sh --set-default-ca --server letsencrypt
  acme.sh --issue -d ${domain} --listen-v6 --standalone --httpport 80
  ↳ 失败 → 清理并返回 1

安装证书:
  acme.sh --installcert
    --key-file     /root/cert/${domain}/privkey.pem
    --fullchain-file /root/cert/${domain}/fullchain.pem
    --reloadcmd    "systemctl restart x-ui"

启用自动续期acme.sh --upgrade --auto-upgrade

设置文件权限:
  privkey.pem  → 600仅所有者可读
  fullchain.pem → 644

配置面板证书路径:
  x-ui cert -webCert fullchain.pem -webCertKey privkey.pem

前提条件80 端口必须可从外网访问。

10. setup_ip_certificate(ipv4, ipv6) — IP 证书(第 195-343 行)

用途:为 IP 地址签发 Let's Encrypt 短期证书(约 6 天有效期)。

流程

检查 acme.sh
验证 IPv4 地址格式

创建证书目录:/root/cert/ip/

选择 HTTP-01 监听端口:
  └─ 默认 80用户可自定义
  └─ 循环检测端口占用,被占用则提示换端口

签发证书:
  acme.sh --issue
    -d ${ipv4} [-d ${ipv6}]
    --standalone
    --server letsencrypt
    --certificate-profile shortlived
    --days 6
    --httpport ${WebPort}

安装证书:
  acme.sh --installcert
    --key-file     /root/cert/ip/privkey.pem
    --fullchain-file /root/cert/ip/fullchain.pem
    --reloadcmd    "systemctl restart x-ui || rc-service x-ui restart"
  ↳ 通过检查文件是否存在(而非退出码)判断成功

启用自动续期
设置文件权限
配置面板证书路径

关键特性

  • 使用 --certificate-profile shortlived 配置文件,证书有效期约 6 天
  • acme.sh cron 任务会在到期前自动续期
  • 不依赖退出码判断安装成功(因为 reloadcmd 失败会导致非零退出)
  • 支持 IPv4 + IPv6 双栈

11. ssl_cert_issue() — 手动 SSL 证书签发(第 346-509 行)

用途:交互式域名证书签发,提供更多自定义选项。

流程

读取当前面板的 webBasePath 和 port

检查 acme.sh不存在则安装

获取并验证用户输入的域名:
  └─ 循环直到输入有效域名
  └─ 检查是否已存在该域名的证书

创建证书目录:/root/cert/${domain}/

选择端口(默认 80

临时停止面板(释放端口)

签发证书:
  acme.sh --issue -d ${domain} --listen-v6 --standalone --httpport ${WebPort}

设置 reloadcmd证书续期后执行的命令
  ├─ 默认systemctl restart x-ui || rc-service x-ui restart
  ├─ 选项 1systemctl reload nginx ; systemctl restart x-ui
  ├─ 选项 2自定义命令
  └─ 选项 0保持默认

安装证书并启用自动续期

启动面板

询问是否将证书应用到面板:
  └─ 是 → x-ui cert -webCert ... -webCertKey ...
  └─ 否 → 跳过

特点

  • 签发前会停止面板以释放端口
  • 支持自定义 reloadcmd例如先 reload nginx 再重启 x-ui
  • 签发失败会自动重新启动面板

12. prompt_and_setup_ssl(panel_port, web_base_path, server_ip) — SSL 选择菜单(第 513-638 行)

用途:安装时的统一 SSL 配置入口,提供三种选择。

菜单

1. Let's Encrypt 域名证书90 天有效期,自动续期)
   └─ 调用 ssl_cert_issue()
   └─ 从 acme.sh 列表提取域名作为 SSL_HOST

2. Let's Encrypt IP 证书6 天有效期,自动续期)  ← 默认选项
   └─ 可选输入 IPv6 地址
   └─ 停止面板释放 80 端口
   └─ 调用 setup_ip_certificate(server_ip, ipv6)
   └─ SSL_HOST = server_ip

3. 自定义 SSL 证书(指定已有文件路径)
   └─ 输入域名
   └─ 循环验证证书文件(存在、可读、非空)
   └─ 循环验证私钥文件(存在、可读、非空)
   └─ x-ui cert -webCert ... -webCertKey ...
   └─ 提示用户自行管理续期

全局变量:设置 SSL_HOST 供后续显示访问地址使用。


安装后配置

13. config_after_install() — 安装后配置(第 640-760 行)

用途首次安装后的凭据生成、端口设置、Web 路径生成、SSL 配置。

流程图

读取当前面板设置:
  - hasDefaultCredential是否为默认凭据
  - webBasePath
  - port
  - cert证书路径

获取服务器公网 IP
  └─ 依次尝试 6 个 API
     1. api4.ipify.org
     2. ipv4.icanhazip.com
     3. v4.api.ipinfo.io/ip
     4. ipv4.myexternalip.com/raw
     5. 4.ident.me
     6. check-host.net/ip

判断 webBasePath 是否足够长≥4 字符):

  ┌─ webBasePath 过短
  │
  │  ├─ hasDefaultCredential == true首次安装
  │  │   ├─ 生成随机 webBasePath18 位)
  │  │   ├─ 生成随机用户名10 位)
  │  │   ├─ 生成随机密码10 位)
  │  │   ├─ 询问是否自定义端口
  │  │   │   ├─ 是 → 用户输入端口
  │  │   │   └─ 否 → 随机生成 1024-62000 范围端口
  │  │   ├─ 应用设置x-ui setting -username ... -password ... -port ... -webBasePath ...
  │  │   ├─ prompt_and_setup_ssl()  ← 必需
  │  │   └─ 显示完整凭据和访问地址
  │  │
  │  └─ hasDefaultCredential != true非首次安装
  │      ├─ 生成新 webBasePath
  │      ├─ 检查是否有证书:
  │      │   ├─ 无 → prompt_and_setup_ssl()(推荐)
  │      │   └─ 有 → 显示 HTTP 访问地址
  │      └─ 结束
  │
  └─ webBasePath 正常≥4 字符)
  
     ├─ hasDefaultCredential == true
     │   ├─ 生成随机用户名和密码
     │   ├─ 应用新凭据
     │   └─ 显示凭据
     │
     └─ hasDefaultCredential != true
         └─ 提示凭据已正确设置

     再次检查证书:
     ├─ 无证书 → prompt_and_setup_ssl()(推荐)
     └─ 有证书 → 跳过

最后执行x-ui migrate数据库迁移

主安装逻辑

14. install_x-ui(version) — 主安装函数(第 762-958 行)

参数$1 可选,指定安装版本号(如 v2.3.5)。

流程

cd /usr/local/

┌─ 无版本参数(安装最新版)
│   ├─ 从 GitHub API 获取最新版本号
│   │   └─ IPv4 失败时重试 curl -4
│   └─ 下载x-ui-linux-${arch}.tar.gz
│
└─ 有版本参数
    ├─ 验证版本号 ≥ v2.3.5
    └─ 下载指定版本

同时下载 x-ui.sh 到 /usr/bin/x-ui-temp

停止已有 x-ui 服务并删除旧安装目录

解压 tar.gz设置执行权限

ARM 架构特殊处理:
  armv5/armv6/armv7 → 重命名为 xray-linux-arm

安装 x-ui.sh 到 /usr/bin/x-ui
创建日志目录 /var/log/x-ui/

调用 config_after_install()  ← 生成凭据 + SSL

etckeeper 兼容:
  └─ 如果 /etc/.git 存在,将 x-ui.db 加入 .gitignore

┌─ Alpine Linux
│   ├─ 下载 OpenRC 脚本 x-ui.rc → /etc/init.d/x-ui
│   ├─ rc-update add x-ui启用开机自启
│   └─ rc-service x-ui start
│
└─ 其他系统systemd
    ├─ 优先使用 tar.gz 中的服务文件
    │   ├─ x-ui.service          ← 通用
    │   ├─ x-ui.service.debian   ← Ubuntu/Debian
    │   ├─ x-ui.service.arch     ← Arch/Manjaro
    │   └─ x-ui.service.rhel     ← 其他CentOS/Fedora 等)
    │
    ├─ 如果 tar.gz 中没有,从 GitHub 下载对应文件
    │
    └─ 配置服务:
        chown root:root x-ui.service
        chmod 644 x-ui.service
        systemctl daemon-reload
        systemctl enable x-ui
        systemctl start x-ui

显示安装完成信息和子命令用法

子命令列表(安装完成后显示):

命令 功能
x-ui 打开管理菜单
x-ui start 启动面板
x-ui stop 停止面板
x-ui restart 重启面板
x-ui status 查看状态
x-ui settings 查看当前设置
x-ui enable 设置开机自启
x-ui disable 取消开机自启
x-ui log 查看日志
x-ui banlog 查看 Fail2ban 日志
x-ui update 更新
x-ui legacy 安装旧版本
x-ui install 安装
x-ui uninstall 卸载

调用关系总结

install.sh
  │
  ├─ install_base()
  │     └─ 根据发行版安装 curl, tar, tzdata, socat, ca-certificates, openssl
  │
  └─ install_x-ui($1)
        ├─ 下载 x-ui 发行版和 x-ui.sh
        ├─ 解压、设置权限
        ├─ config_after_install()
        │     ├─ gen_random_string() × 3用户名/密码/Web路径
        │     ├─ 获取公网 IP
        │     ├─ prompt_and_setup_ssl()
        │     │     ├─ [选项1] ssl_cert_issue()
        │     │     │     ├─ install_acme()
        │     │     │     └─ acme.sh 签发/安装/续期域名证书
        │     │     ├─ [选项2] setup_ip_certificate()
        │     │     │     ├─ install_acme()
        │     │     │     └─ acme.sh 签发/安装/续期 IP 短期证书
        │     │     └─ [选项3] 用户提供自定义证书路径
        │     └─ x-ui migrate
        └─ 配置系统服务systemd 或 OpenRC

关键设计决策

  1. 强制 SSL:首次安装时必须配置 SSL 证书(三种方式选一),确保面板通过 HTTPS 访问。

  2. 随机化安全用户名、密码、端口、Web 路径全部随机生成,避免使用默认凭据。

  3. 多 OS 兼容:通过 case 语句适配 7 大包管理器体系Alpine 使用 OpenRC其余使用 systemd。

  4. IP 证书支持:利用 Let's Encrypt 的 shortlived profile为无域名场景提供 SSL 支持6 天有效期,自动续期)。

  5. 优雅降级

    • GitHub API 失败时用 curl -4 重试
    • ss 不可用时回退到 netstat,再回退到 lsof
    • tar.gz 中无服务文件时从 GitHub 下载
    • acme.sh reloadcmd 失败不阻止证书安装
  6. etckeeper 兼容:自动将数据库文件加入 /etc/.gitignore,避免 etckeeper 追踪频繁变化的数据库。