mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-02-27 20:53:01 +00:00
Rewrite install.sh to build from source instead of downloading release
The install script previously downloaded pre-built binaries from MHSanaei/3x-ui releases, which didn't include TrustTunnel support. Now it clones the fork, installs Go, and builds from source so all custom protocol changes are included in the installed binary. https://claude.ai/code/session_01RQBndg4ZPmYAToK4KKcBzp
This commit is contained in:
parent
0c866b476a
commit
836f65f192
1 changed files with 158 additions and 141 deletions
299
install.sh
299
install.sh
|
|
@ -76,33 +76,70 @@ is_port_in_use() {
|
|||
install_base() {
|
||||
case "${release}" in
|
||||
ubuntu | debian | armbian)
|
||||
apt-get update && apt-get install -y -q curl tar tzdata socat ca-certificates
|
||||
apt-get update && apt-get install -y -q curl tar tzdata socat ca-certificates git gcc make unzip
|
||||
;;
|
||||
fedora | amzn | virtuozzo | rhel | almalinux | rocky | ol)
|
||||
dnf -y update && dnf install -y -q curl tar tzdata socat ca-certificates
|
||||
dnf -y update && dnf install -y -q curl tar tzdata socat ca-certificates git gcc make unzip
|
||||
;;
|
||||
centos)
|
||||
if [[ "${VERSION_ID}" =~ ^7 ]]; then
|
||||
yum -y update && yum install -y curl tar tzdata socat ca-certificates
|
||||
yum -y update && yum install -y curl tar tzdata socat ca-certificates git gcc make unzip
|
||||
else
|
||||
dnf -y update && dnf install -y -q curl tar tzdata socat ca-certificates
|
||||
dnf -y update && dnf install -y -q curl tar tzdata socat ca-certificates git gcc make unzip
|
||||
fi
|
||||
;;
|
||||
arch | manjaro | parch)
|
||||
pacman -Syu && pacman -Syu --noconfirm curl tar tzdata socat ca-certificates
|
||||
pacman -Syu && pacman -Syu --noconfirm curl tar tzdata socat ca-certificates git gcc make unzip
|
||||
;;
|
||||
opensuse-tumbleweed | opensuse-leap)
|
||||
zypper refresh && zypper -q install -y curl tar timezone socat ca-certificates
|
||||
zypper refresh && zypper -q install -y curl tar timezone socat ca-certificates git gcc make unzip
|
||||
;;
|
||||
alpine)
|
||||
apk update && apk add curl tar tzdata socat ca-certificates
|
||||
apk update && apk add curl tar tzdata socat ca-certificates git gcc musl-dev make unzip
|
||||
;;
|
||||
*)
|
||||
apt-get update && apt-get install -y -q curl tar tzdata socat ca-certificates
|
||||
apt-get update && apt-get install -y -q curl tar tzdata socat ca-certificates git gcc make unzip
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Go version required for building
|
||||
GO_VERSION="1.22.5"
|
||||
|
||||
install_go() {
|
||||
if command -v go >/dev/null 2>&1; then
|
||||
local current_go=$(go version 2>/dev/null | grep -oP 'go\K[0-9]+\.[0-9]+')
|
||||
local required="1.22"
|
||||
if [[ "$(printf '%s\n' "$required" "$current_go" | sort -V | head -n1)" == "$required" ]]; then
|
||||
echo -e "${green}Go ${current_go} is already installed${plain}"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${green}Installing Go ${GO_VERSION}...${plain}"
|
||||
local go_arch
|
||||
case "$(uname -m)" in
|
||||
x86_64 | x64 | amd64) go_arch="amd64" ;;
|
||||
i*86 | x86) go_arch="386" ;;
|
||||
armv8* | armv8 | arm64 | aarch64) go_arch="arm64" ;;
|
||||
armv7* | armv7 | arm) go_arch="armv6l" ;;
|
||||
armv6* | armv6) go_arch="armv6l" ;;
|
||||
s390x) go_arch="s390x" ;;
|
||||
*) echo -e "${red}Unsupported architecture for Go${plain}"; exit 1 ;;
|
||||
esac
|
||||
|
||||
curl -4fLo /tmp/go.tar.gz "https://go.dev/dl/go${GO_VERSION}.linux-${go_arch}.tar.gz"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "${red}Failed to download Go${plain}"
|
||||
exit 1
|
||||
fi
|
||||
rm -rf /usr/local/go
|
||||
tar -C /usr/local -xzf /tmp/go.tar.gz
|
||||
rm -f /tmp/go.tar.gz
|
||||
export PATH="/usr/local/go/bin:$PATH"
|
||||
echo -e "${green}Go $(go version) installed successfully${plain}"
|
||||
}
|
||||
|
||||
gen_random_string() {
|
||||
local length="$1"
|
||||
local random_string=$(LC_ALL=C tr -dc 'a-zA-Z0-9' </dev/urandom | fold -w "$length" | head -n 1)
|
||||
|
|
@ -761,78 +798,108 @@ config_after_install() {
|
|||
}
|
||||
|
||||
install_x-ui() {
|
||||
cd ${xui_folder%/x-ui}/
|
||||
|
||||
# Download resources
|
||||
if [ $# == 0 ]; then
|
||||
tag_version=$(curl -Ls "https://api.github.com/repos/MHSanaei/3x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||
if [[ ! -n "$tag_version" ]]; then
|
||||
echo -e "${yellow}Trying to fetch version with IPv4...${plain}"
|
||||
tag_version=$(curl -4 -Ls "https://api.github.com/repos/MHSanaei/3x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||
if [[ ! -n "$tag_version" ]]; then
|
||||
echo -e "${red}Failed to fetch x-ui version, it may be due to GitHub API restrictions, please try it later${plain}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo -e "Got x-ui latest version: ${tag_version}, beginning the installation..."
|
||||
curl -4fLRo ${xui_folder}-linux-$(arch).tar.gz https://github.com/MHSanaei/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "${red}Downloading x-ui failed, please be sure that your server can access GitHub ${plain}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
tag_version=$1
|
||||
tag_version_numeric=${tag_version#v}
|
||||
min_version="2.3.5"
|
||||
|
||||
if [[ "$(printf '%s\n' "$min_version" "$tag_version_numeric" | sort -V | head -n1)" != "$min_version" ]]; then
|
||||
echo -e "${red}Please use a newer version (at least v2.3.5). Exiting installation.${plain}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
url="https://github.com/MHSanaei/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz"
|
||||
echo -e "Beginning to install x-ui $1"
|
||||
curl -4fLRo ${xui_folder}-linux-$(arch).tar.gz ${url}
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "${red}Download x-ui $1 failed, please check if the version exists ${plain}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
curl -4fLRo /usr/bin/x-ui-temp https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.sh
|
||||
# GitHub repo to build from
|
||||
local REPO_URL="https://github.com/yelloduxx/3x-ui.git"
|
||||
local BRANCH="claude/add-trusttunnel-protocol-vZFzn"
|
||||
local BUILD_DIR="/tmp/3x-ui-build"
|
||||
|
||||
# Install Go if needed
|
||||
install_go
|
||||
|
||||
# Clone and build from source
|
||||
echo -e "${green}Cloning repository...${plain}"
|
||||
rm -rf "${BUILD_DIR}"
|
||||
git clone --depth 1 --branch "${BRANCH}" "${REPO_URL}" "${BUILD_DIR}"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "${red}Failed to download x-ui.sh${plain}"
|
||||
echo -e "${red}Failed to clone repository${plain}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo -e "${green}Building x-ui from source...${plain}"
|
||||
cd "${BUILD_DIR}"
|
||||
export CGO_ENABLED=1
|
||||
export CGO_CFLAGS="-D_LARGEFILE64_SOURCE"
|
||||
export PATH="/usr/local/go/bin:$PATH"
|
||||
go build -ldflags "-w -s" -o build/x-ui main.go
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "${red}Build failed${plain}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${green}Build successful${plain}"
|
||||
|
||||
# Download Xray-core binary
|
||||
echo -e "${green}Downloading Xray-core...${plain}"
|
||||
local xray_arch
|
||||
case "$(uname -m)" in
|
||||
x86_64 | x64 | amd64) xray_arch="64" ;;
|
||||
i*86 | x86) xray_arch="32" ;;
|
||||
armv8* | armv8 | arm64 | aarch64) xray_arch="arm64-v8a" ;;
|
||||
armv7* | armv7 | arm) xray_arch="arm32-v7a" ;;
|
||||
armv6* | armv6) xray_arch="arm32-v6" ;;
|
||||
s390x) xray_arch="s390x" ;;
|
||||
*) echo -e "${red}Unsupported architecture for Xray${plain}"; exit 1 ;;
|
||||
esac
|
||||
|
||||
mkdir -p build/bin
|
||||
cd build/bin
|
||||
curl -sfLRO "https://github.com/XTLS/Xray-core/releases/download/v26.2.6/Xray-linux-${xray_arch}.zip"
|
||||
unzip -o "Xray-linux-${xray_arch}.zip"
|
||||
rm -f "Xray-linux-${xray_arch}.zip" geoip.dat geosite.dat
|
||||
mv xray "xray-linux-$(arch)"
|
||||
curl -sfLRO https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
|
||||
curl -sfLRO https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat
|
||||
curl -sfLRo geoip_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat
|
||||
curl -sfLRo geosite_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat
|
||||
curl -sfLRo geoip_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat
|
||||
curl -sfLRo geosite_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat
|
||||
cd "${BUILD_DIR}"
|
||||
|
||||
# Stop x-ui service and remove old resources
|
||||
if [[ -e ${xui_folder}/ ]]; then
|
||||
if [[ $release == "alpine" ]]; then
|
||||
rc-service x-ui stop
|
||||
rc-service x-ui stop 2>/dev/null
|
||||
else
|
||||
systemctl stop x-ui
|
||||
systemctl stop x-ui 2>/dev/null
|
||||
fi
|
||||
rm ${xui_folder}/ -rf
|
||||
fi
|
||||
|
||||
# Extract resources and set permissions
|
||||
tar zxvf x-ui-linux-$(arch).tar.gz
|
||||
rm x-ui-linux-$(arch).tar.gz -f
|
||||
|
||||
cd x-ui
|
||||
|
||||
# Install built files
|
||||
mkdir -p ${xui_folder}
|
||||
cp build/x-ui ${xui_folder}/
|
||||
cp -r build/bin ${xui_folder}/
|
||||
cp x-ui.sh ${xui_folder}/
|
||||
# Copy service files into install dir for later detection
|
||||
cp -f x-ui.service.debian ${xui_folder}/ 2>/dev/null
|
||||
cp -f x-ui.service.arch ${xui_folder}/ 2>/dev/null
|
||||
cp -f x-ui.service.rhel ${xui_folder}/ 2>/dev/null
|
||||
# Also copy as generic x-ui.service for fallback
|
||||
case "${release}" in
|
||||
ubuntu | debian | armbian) cp -f x-ui.service.debian ${xui_folder}/x-ui.service 2>/dev/null ;;
|
||||
arch | manjaro | parch) cp -f x-ui.service.arch ${xui_folder}/x-ui.service 2>/dev/null ;;
|
||||
*) cp -f x-ui.service.rhel ${xui_folder}/x-ui.service 2>/dev/null ;;
|
||||
esac
|
||||
|
||||
cd ${xui_folder}
|
||||
chmod +x x-ui
|
||||
chmod +x x-ui.sh
|
||||
|
||||
|
||||
# Check the system's architecture and rename the file accordingly
|
||||
if [[ $(arch) == "armv5" || $(arch) == "armv6" || $(arch) == "armv7" ]]; then
|
||||
mv bin/xray-linux-$(arch) bin/xray-linux-arm
|
||||
chmod +x bin/xray-linux-arm
|
||||
fi
|
||||
chmod +x x-ui bin/xray-linux-$(arch)
|
||||
|
||||
# Update x-ui cli and se set permission
|
||||
mv -f /usr/bin/x-ui-temp /usr/bin/x-ui
|
||||
chmod +x x-ui bin/xray-linux-$(arch) 2>/dev/null
|
||||
|
||||
# Install x-ui CLI wrapper
|
||||
cp -f "${xui_folder}/x-ui.sh" /usr/bin/x-ui
|
||||
chmod +x /usr/bin/x-ui
|
||||
mkdir -p /var/log/x-ui
|
||||
|
||||
# Cleanup build directory
|
||||
rm -rf "${BUILD_DIR}"
|
||||
|
||||
tag_version="source-build"
|
||||
config_after_install
|
||||
|
||||
# Etckeeper compatibility
|
||||
|
|
@ -848,96 +915,46 @@ install_x-ui() {
|
|||
echo -e "${green}Created /etc/.gitignore and added x-ui.db for etckeeper${plain}"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [[ $release == "alpine" ]]; then
|
||||
curl -4fLRo /etc/init.d/x-ui https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.rc
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "${red}Failed to download x-ui.rc${plain}"
|
||||
exit 1
|
||||
if [ -f "${xui_folder}/x-ui.service.debian" ]; then
|
||||
# Use a simple OpenRC init script
|
||||
cp -f "${xui_folder}/x-ui.service.debian" /etc/init.d/x-ui 2>/dev/null
|
||||
fi
|
||||
# Create OpenRC init script
|
||||
cat > /etc/init.d/x-ui <<'INITEOF'
|
||||
#!/sbin/openrc-run
|
||||
name="x-ui"
|
||||
description="3x-ui panel"
|
||||
command="/usr/local/x-ui/x-ui"
|
||||
command_background=true
|
||||
pidfile="/run/x-ui.pid"
|
||||
directory="/usr/local/x-ui"
|
||||
output_log="/var/log/x-ui/x-ui.log"
|
||||
error_log="/var/log/x-ui/x-ui.log"
|
||||
INITEOF
|
||||
chmod +x /etc/init.d/x-ui
|
||||
rc-update add x-ui
|
||||
rc-service x-ui start
|
||||
else
|
||||
# Install systemd service file
|
||||
service_installed=false
|
||||
|
||||
if [ -f "x-ui.service" ]; then
|
||||
echo -e "${green}Found x-ui.service in extracted files, installing...${plain}"
|
||||
cp -f x-ui.service ${xui_service}/ >/dev/null 2>&1
|
||||
if [[ $? -eq 0 ]]; then
|
||||
service_installed=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$service_installed" = false ]; then
|
||||
case "${release}" in
|
||||
ubuntu | debian | armbian)
|
||||
if [ -f "x-ui.service.debian" ]; then
|
||||
echo -e "${green}Found x-ui.service.debian in extracted files, installing...${plain}"
|
||||
cp -f x-ui.service.debian ${xui_service}/x-ui.service >/dev/null 2>&1
|
||||
if [[ $? -eq 0 ]]; then
|
||||
service_installed=true
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
arch | manjaro | parch)
|
||||
if [ -f "x-ui.service.arch" ]; then
|
||||
echo -e "${green}Found x-ui.service.arch in extracted files, installing...${plain}"
|
||||
cp -f x-ui.service.arch ${xui_service}/x-ui.service >/dev/null 2>&1
|
||||
if [[ $? -eq 0 ]]; then
|
||||
service_installed=true
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if [ -f "x-ui.service.rhel" ]; then
|
||||
echo -e "${green}Found x-ui.service.rhel in extracted files, installing...${plain}"
|
||||
cp -f x-ui.service.rhel ${xui_service}/x-ui.service >/dev/null 2>&1
|
||||
if [[ $? -eq 0 ]]; then
|
||||
service_installed=true
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# If service file not found in tar.gz, download from GitHub
|
||||
if [ "$service_installed" = false ]; then
|
||||
echo -e "${yellow}Service files not found in tar.gz, downloading from GitHub...${plain}"
|
||||
case "${release}" in
|
||||
ubuntu | debian | armbian)
|
||||
curl -4fLRo ${xui_service}/x-ui.service https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.service.debian >/dev/null 2>&1
|
||||
;;
|
||||
arch | manjaro | parch)
|
||||
curl -4fLRo ${xui_service}/x-ui.service https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.service.arch >/dev/null 2>&1
|
||||
;;
|
||||
*)
|
||||
curl -4fLRo ${xui_service}/x-ui.service https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.service.rhel >/dev/null 2>&1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "${red}Failed to install x-ui.service from GitHub${plain}"
|
||||
exit 1
|
||||
fi
|
||||
service_installed=true
|
||||
fi
|
||||
|
||||
if [ "$service_installed" = true ]; then
|
||||
echo -e "${green}Setting up systemd unit...${plain}"
|
||||
chown root:root ${xui_service}/x-ui.service >/dev/null 2>&1
|
||||
chmod 644 ${xui_service}/x-ui.service >/dev/null 2>&1
|
||||
systemctl daemon-reload
|
||||
systemctl enable x-ui
|
||||
systemctl start x-ui
|
||||
if [ -f "${xui_folder}/x-ui.service" ]; then
|
||||
echo -e "${green}Installing systemd service file...${plain}"
|
||||
cp -f "${xui_folder}/x-ui.service" ${xui_service}/x-ui.service
|
||||
else
|
||||
echo -e "${red}Failed to install x-ui.service file${plain}"
|
||||
echo -e "${red}Service file not found${plain}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${green}Setting up systemd unit...${plain}"
|
||||
chown root:root ${xui_service}/x-ui.service >/dev/null 2>&1
|
||||
chmod 644 ${xui_service}/x-ui.service >/dev/null 2>&1
|
||||
systemctl daemon-reload
|
||||
systemctl enable x-ui
|
||||
systemctl start x-ui
|
||||
fi
|
||||
|
||||
echo -e "${green}x-ui ${tag_version}${plain} installation finished, it is running now..."
|
||||
|
||||
echo -e "${green}x-ui (built from source)${plain} installation finished, it is running now..."
|
||||
echo -e ""
|
||||
echo -e "┌───────────────────────────────────────────────────────┐
|
||||
│ ${blue}x-ui control menu usages (subcommands):${plain} │
|
||||
|
|
@ -961,4 +978,4 @@ install_x-ui() {
|
|||
|
||||
echo -e "${green}Running...${plain}"
|
||||
install_base
|
||||
install_x-ui $1
|
||||
install_x-ui
|
||||
|
|
|
|||
Loading…
Reference in a new issue