Linux自建EasyTier节点全攻略:从服务器部署到客户端接入

在分布式网络场景中,EasyTier作为轻量级的网络穿透与节点管理工具,深受开发者和运维人员青睐。它支持灵活的节点部署、Web化管理以及跨设备互联互通,尤其适合需要搭建私有网络的个人和企业用户。本文将详细讲解如何在Linux系统中自建EasyTier节点,涵盖基础服务器搭建、Web管理端部署(含前后端分离/集成两种模式)、客户端接入等全流程,附详细命令和配置说明,新手也能轻松上手。

一、前置准备:环境检查与核心脚本获取

在开始部署前,先确保你的Linux环境满足以下条件,避免后续出现兼容性问题:

  • 系统要求:支持systemd或OpenRC初始化系统(主流Linux发行版如Ubuntu、CentOS、Debian、OpenWrt均符合);

  • 权限要求:必须以root用户执行操作(脚本需创建系统服务、写入配置文件等);

  • 依赖工具:已安装curl、unzip(脚本会自动检查,缺失则提示安装);

  • 网络要求:服务器需开放对应端口(默认11010、11210、11211等,后续会详细说明)。

核心脚本获取:使用自定义的EasyTier安装脚本(功能更完善、参数支持更全面),请先将提供的脚本保存为install.sh,再执行以下命令赋予执行权限:

#!/bin/bash

RED_COLOR='\e[1;31m'
GREEN_COLOR='\e[1;32m'
YELLOW_COLOR='\e[1;33m'
BLUE_COLOR='\e[1;34m'
PINK_COLOR='\e[1;35m'
SHAN='\e[1;33;5m'
RES='\e[0m'

HELP() {
  echo -e "\r\n${GREEN_COLOR}EasyTier Installation Script Help${RES}\r\n"
  echo "Usage: ./install.sh [command] [options]"
  echo
  echo "Commands:"
  echo "  install            Install EasyTier core service"
  echo "  install-web        Install EasyTier web service (pure path, no extra args)"
  echo "  install-web-embed  Install EasyTier web-embed service with configurable parameters"
  echo "  uninstall          Uninstall EasyTier"
  echo "  uninstall-web      Uninstall EasyTier web service"
  echo "  update             Update EasyTier to the latest version"
  echo "  help               Show this help message"
  echo
  echo "Options:"
  echo "  --skip-folder-verify  Skip folder verification during installation"
  echo "  --skip-folder-fix     Skip automatic folder path fixing"
  echo "  --no-gh-proxy        Disable GitHub proxy"
  echo "  --gh-proxy URL       Set custom GitHub proxy URL"
  echo "  --web-portal URL     Set custom -w web portal (default: udp://public.easytiertop:22020/主机名_年月日@)"
  echo "  -d/--db-path PATH    Set data storage path for web-embed (default: /opt/easytier/et.db)"
  echo "  -l/--web-port PORT   Set web frontend port for web-embed (default: 11210)"
  echo "  -a/--api-port PORT   Set web backend port for web-embed (default: 11211)"
  echo
  echo "Examples:"
  echo "  ./install.sh install /opt/easytier"
  echo "  ./install.sh install --skip-folder-verify"
  echo "  ./install.sh install-web"
  echo "  ./install.sh install-web-embed"
  echo "  ./install.sh install-web-embed -d /data/easytier/et.db -l 21010 -a 21011"
  echo "  ./install.sh install-web-embed --db-path /data/easytier/et.db --web-port 21010 --api-port 21011"
  echo "  ./install.sh uninstall-web"
  echo
  echo "Web Portal Format Requirement:"
  echo "  Correct: udp://domain:port/token (e.g. udp://public.easytiertop:22020/sgphwyun_20251219@)"
  echo "  Wrong:   udp://domain:port//token (double slash) / tcp://domain:port/ (empty token)"
}

# 生成默认Web Portal(主机名+年月日)
generate_default_web_portal() {
  # 获取主机名(过滤特殊字符)
  local hostname=$(hostname | tr -cd 'a-zA-Z0-9_')
  # 获取当前年月日(格式:YYYYMMDD)
  local date_str=$(date +%Y%m%d)
  # 拼接默认Web Portal
  echo "udp://public.easytiertop:22020/${hostname}_${date_str}@"
}

# Web Portal格式校验函数(核心修复:仅修复路径中的双斜杠,保留协议双斜杠)
validate_web_portal() {
  local portal="$1"
  local error_msg=""
  local fixed_portal="$portal"

  # 1. 校验协议(仅允许udp/tcp)
  if ! echo "$portal" | grep -qE '^(udp|tcp)://'; then
    error_msg="协议错误:仅支持 udp:// 或 tcp:// 开头"
  # 2. 拆分协议和路径,分别处理
  else
    # 拆分协议部分(udp://)和剩余部分
    local proto=$(echo "$portal" | grep -oE '^(udp|tcp)://')
    local rest=$(echo "$portal" | sed "s|^${proto}||")
    
    # 3. 校验剩余部分格式(地址:端口/令牌)
    if ! echo "$rest" | grep -qE '^[^:]+:[0-9]+/[^/]+$'; then
      # 细分错误类型
      if echo "$rest" | grep -qE '^[^:]+:[0-9]+//'; then
        error_msg="格式错误:路径包含双斜杠(//),正确格式为单斜杠(/)"
        # 仅修复路径中的双斜杠,保留协议双斜杠
        fixed_portal="${proto}$(echo "$rest" | sed 's|//|/|g')"
        echo -e "${YELLOW_COLOR}自动修复路径双斜杠:$portal → $fixed_portal${RES}"
      elif echo "$rest" | grep -qE '^[^:]+:[0-9]+/$'; then
        error_msg="令牌为空:地址后必须跟有效的令牌(如 /sgphwyun_20251219@)"
      else
        error_msg="格式错误:正确格式为 ${proto}域名:端口/令牌(如 ${proto}public.easytier.top:22020/sgphwyun_20251219@)"
      fi
    # 4. 校验端口是否为数字
    elif ! echo "$rest" | grep -qE '^[^:]+:[0-9]{1,5}/[^/]+$'; then
      error_msg="端口错误:必须为1-65535之间的数字"
    # 5. 校验令牌是否为空(至少1个字符)
    elif [ -z "$(echo "$rest" | awk -F '/' '{print $2}')" ]; then
      error_msg="令牌为空:地址后必须跟有效的令牌(如 /sgphwyun_20251219@)"
    fi
  fi

  # 校验不通过则输出错误并退出
  if [ -n "$error_msg" ]; then
    echo -e "\r\n${RED_COLOR}Web Portal 格式校验失败:${RES}"
    echo -e "${RED_COLOR}错误原因:$error_msg${RES}"
    echo -e "${YELLOW_COLOR}正确格式示例:$(generate_default_web_portal)${RES}"
    exit 1
  fi

  # 最终赋值(保留协议双斜杠)
  DEFAULT_WEB_PORTAL="$fixed_portal"
  return 0
}

# 端口合法性校验函数
validate_port() {
  local port="$1"
  local port_name="$2"

  if ! [[ "$port" =~ ^[0-9]+$ ]]; then
    echo -e "${RED_COLOR}错误:${port_name}必须是数字(当前值:$port)${RES}"
    exit 1
  fi

  if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
    echo -e "${RED_COLOR}错误:${port_name}必须在1-65535之间(当前值:$port)${RES}"
    exit 1
  fi
}

# ========== 安装easytier-web服务(纯路径,无参数) ==========
INSTALL_WEB() {
  # 检查核心包是否已安装
  if [ ! -f "$INSTALL_PATH/easytier-web" ]; then
    echo -e "${YELLOW_COLOR}核心包未安装,先自动安装核心服务...${RES}"
    CHECK
    INSTALL
  fi

  # 停止旧的web服务
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    systemctl stop easytier-web.service >/dev/null 2>&1
  else
    rc-service easytier-web stop >/dev/null 2>&1
  fi

  # 配置systemd服务(纯路径,无任何参数)
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    cat >/etc/systemd/system/easytier-web.service <<EOF
[Unit]
Description=EasyTier Web Service
Wants=network.target
After=network.target network.service
StartLimitIntervalSec=0

[Service]
Type=simple
WorkingDirectory=$INSTALL_PATH
ExecStart=$INSTALL_PATH/easytier-web
Restart=always
RestartSec=1s

[Install]
WantedBy=multi-user.target
EOF
  elif [ "$INIT_SYSTEM" = "openrc" ]; then
    cat >/etc/init.d/easytier-web <<EOF
#!/sbin/openrc-run

name="EasyTier Web"
description="EasyTier Web Service"
command="$INSTALL_PATH/easytier-web"
command_user="nobody:nobody"
command_background=true

pidfile="/run/\${RC_SVCNAME}.pid"

depend() {
  need net
}
EOF
    chmod +x /etc/init.d/easytier-web
  fi

  # 启动服务
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    systemctl daemon-reload
    systemctl enable easytier-web.service >/dev/null 2>&1
    systemctl start easytier-web.service
  else
    rc-update add easytier-web default
    rc-service easytier-web start
  fi

  # 验证并输出ExecStart
  echo -e "\r\n${GREEN_COLOR}Install EasyTier web service successfully!${RES}"
  echo -e "${YELLOW_COLOR}----------------------IMPORTANT----------------------${RES}"
  echo -e "ExecStart: ${GREEN_COLOR}$INSTALL_PATH/easytier-web${RES}"
  echo -e "Service Name: ${GREEN_COLOR}easytier-web.service${RES}"
  echo -e "${YELLOW_COLOR}-----------------------------------------------------${RES}\r\n"
  
  echo -e "Service Management Commands:"
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    echo -e "Status: ${GREEN_COLOR}systemctl status easytier-web.service${RES}"
    echo -e "Start: ${GREEN_COLOR}systemctl start easytier-web.service${RES}"
    echo -e "Stop: ${GREEN_COLOR}systemctl stop easytier-web.service${RES}"
  else
    echo -e "Status: ${GREEN_COLOR}rc-service easytier-web status${RES}"
    echo -e "Start: ${GREEN_COLOR}rc-service easytier-web start${RES}"
    echo -e "Stop: ${GREEN_COLOR}rc-service easytier-web stop${RES}"
  fi
}

# ========== 安装easytier-web-embed服务(带可配置参数) ==========
INSTALL_WEB_EMBED() {
  # 设置默认参数
  local DB_PATH="${DB_PATH:-/opt/easytier/et.db}"
  local WEB_PORT="${WEB_PORT:-11210}"
  local API_PORT="${API_PORT:-11211}"

  # 校验端口合法性
  validate_port "$WEB_PORT" "Web前端端口(-l/--web-port)"
  validate_port "$API_PORT" "Web后端端口(-a/--api-port)"

  # 确保数据目录存在
  local DB_DIR=$(dirname "$DB_PATH")
  if [ ! -d "$DB_DIR" ]; then
    mkdir -p "$DB_DIR"
    chmod 755 "$DB_DIR"
    echo -e "${YELLOW_COLOR}已创建数据目录:$DB_DIR${RES}"
  fi

  # 检查核心包是否已安装
  if [ ! -f "$INSTALL_PATH/easytier-web-embed" ]; then
    echo -e "${YELLOW_COLOR}核心包未安装,先自动安装核心服务...${RES}"
    CHECK
    INSTALL
  fi

  # 停止旧的web服务
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    systemctl stop easytier-web.service >/dev/null 2>&1
  else
    rc-service easytier-web stop >/dev/null 2>&1
  fi

  # 构建ExecStart命令
  local EXEC_CMD="$INSTALL_PATH/easytier-web-embed -d $DB_PATH -l $WEB_PORT -a $API_PORT"

  # 配置systemd服务
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    cat >/etc/systemd/system/easytier-web.service <<EOF
[Unit]
Description=EasyTier Web Embed Service
Wants=network.target
After=network.target network.service
StartLimitIntervalSec=0

[Service]
Type=simple
WorkingDirectory=$INSTALL_PATH
ExecStart=$EXEC_CMD
Restart=always
RestartSec=1s

[Install]
WantedBy=multi-user.target
EOF
  elif [ "$INIT_SYSTEM" = "openrc" ]; then
    cat >/etc/init.d/easytier-web <<EOF
#!/sbin/openrc-run

name="EasyTier Web Embed"
description="EasyTier Web Embed Service"
command="$INSTALL_PATH/easytier-web-embed"
command_args="-d $DB_PATH -l $WEB_PORT -a $API_PORT"
command_user="nobody:nobody"
command_background=true

pidfile="/run/\${RC_SVCNAME}.pid"

depend() {
  need net
}
EOF
    chmod +x /etc/init.d/easytier-web
  fi

  # 启动服务
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    systemctl daemon-reload
    systemctl enable easytier-web.service >/dev/null 2>&1
    systemctl start easytier-web.service
  else
    rc-update add easytier-web default
    rc-service easytier-web start
  fi

  # 验证并输出配置信息
  echo -e "\r\n${GREEN_COLOR}Install EasyTier web-embed service successfully!${RES}"
  echo -e "${YELLOW_COLOR}----------------------IMPORTANT----------------------${RES}"
  echo -e "ExecStart: ${GREEN_COLOR}$EXEC_CMD${RES}"
  echo -e "Data Storage Path (-d): ${GREEN_COLOR}$DB_PATH${RES}"
  echo -e "Web Frontend Port (-l): ${GREEN_COLOR}$WEB_PORT${RES}"
  echo -e "Web Backend Port (-a): ${GREEN_COLOR}$API_PORT${RES}"
  echo -e "Service Name: ${GREEN_COLOR}easytier-web.service${RES}"
  echo -e "${YELLOW_COLOR}-----------------------------------------------------${RES}\r\n"
  
  echo -e "Service Management Commands:"
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    echo -e "Status: ${GREEN_COLOR}systemctl status easytier-web.service${RES}"
    echo -e "Start: ${GREEN_COLOR}systemctl start easytier-web.service${RES}"
    echo -e "Stop: ${GREEN_COLOR}systemctl stop easytier-web.service${RES}"
  else
    echo -e "Status: ${GREEN_COLOR}rc-service easytier-web status${RES}"
    echo -e "Start: ${GREEN_COLOR}rc-service easytier-web start${RES}"
    echo -e "Stop: ${GREEN_COLOR}rc-service easytier-web stop${RES}"
  fi
}

# ========== 卸载web服务 ==========
UNINSTALL_WEB() {
  echo -e "\r\n${GREEN_COLOR}Uninstall EasyTier web service ...${RES}\r\n"
  
  # 停止服务
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    systemctl disable easytier-web.service >/dev/null 2>&1
    systemctl stop easytier-web.service >/dev/null 2>&1
  else
    rc-update del easytier-web
    rc-service easytier-web stop
  fi

  # 删除服务文件
  rm -rf /etc/systemd/system/easytier-web.service
  rm -rf /etc/init.d/easytier-web
  
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    systemctl daemon-reload
  fi
  
  echo -e "\r\n${GREEN_COLOR}EasyTier web service was removed successfully! ${RES}\r\n"
}

# Show help if no arguments or help command is used
if [ $# -eq 0 ] || [ "$1" = "help" ]; then
  HELP
  exit 0
fi

# This script copy from alist , Thank for it!

SKIP_FOLDER_VERIFY=false
SKIP_FOLDER_FIX=false
NO_GH_PROXY=false
GH_PROXY='https://ghfast.top/'
# 动态生成默认Web Portal(主机名+年月日)
DEFAULT_WEB_PORTAL=$(generate_default_web_portal)
# web-embed默认参数
DB_PATH="/opt/easytier/et.db"
WEB_PORT=11210
API_PORT=11211

COMMEND=$1
shift

# Check path
if [[ "$#" -ge 1 && ! "$1" =~ ^- ]]; then
    INSTALL_PATH=$1
    shift
fi

# Check other option - 兼容短参数和长参数
while [[ "$#" -gt 0 ]]; do
    case $1 in
        --skip-folder-verify) SKIP_FOLDER_VERIFY=true ;;
        --skip-folder-fix) SKIP_FOLDER_FIX=true ;;
        --no-gh-proxy) NO_GH_PROXY=true ;;
        --gh-proxy) 
            if [ -n "$2" ]; then
                GH_PROXY=$2
                shift
            else
                echo "Error: --gh-proxy requires a URL"
                exit 1
            fi
            ;;
        --web-portal) 
            if [ -n "$2" ]; then
                # 校验Web Portal格式
                validate_web_portal "$2"
                shift
            else
                echo "Error: --web-portal requires a URL"
                exit 1
            fi
            ;;
        -d|--db-path)
            if [ -n "$2" ]; then
                DB_PATH="$2"
                shift
            else
                echo "Error: -d/--db-path requires a file path"
                exit 1
            fi
            ;;
        -l|--web-port)
            if [ -n "$2" ]; then
                WEB_PORT="$2"
                shift
            else
                echo "Error: -l/--web-port requires a port number"
                exit 1
            fi
            ;;
        -a|--api-port)
            if [ -n "$2" ]; then
                API_PORT="$2"
                shift
            else
                echo "Error: -a/--api-port requires a port number"
                exit 1
            fi
            ;;
        *) 
            echo "Unknown option: $1"
            echo "Use './install.sh help' to see available options"
            exit 1 
            ;;
    esac
    shift
done

if [ -z "$INSTALL_PATH" ]; then
    INSTALL_PATH='/opt/easytier'
fi

if [[ "$INSTALL_PATH" == */ ]]; then
    INSTALL_PATH=${INSTALL_PATH%?}
fi

if ! $SKIP_FOLDER_FIX && ! [[ "$INSTALL_PATH" == */easytier ]]; then
    INSTALL_PATH="$INSTALL_PATH/easytier"
fi

echo INSTALL PATH : $INSTALL_PATH
echo SKIP FOLDER FIX : $SKIP_FOLDER_FIX
echo SKIP FOLDER VERIFY : $SKIP_FOLDER_VERIFY
echo DEFAULT WEB PORTAL : $DEFAULT_WEB_PORTAL
# 输出web-embed参数
if [ "$COMMEND" = "install-web-embed" ]; then
    echo DB PATH : $DB_PATH
    echo WEB PORT : $WEB_PORT
    echo API PORT : $API_PORT
fi

# clear

# check if unzip is installed
if ! command -v unzip >/dev/null 2>&1; then
  echo -e "\r\n${RED_COLOR}Error: unzip is not installed${RES}\r\n"
  exit 1
fi

# check if curl is installed
if ! command -v curl >/dev/null 2>&1; then
  echo -e "\r\n${RED_COLOR}Error: curl is not installed${RES}\r\n"
  exit 1
fi

echo -e "\r\n${RED_COLOR}----------------------NOTICE----------------------${RES}\r\n"
echo " This is a temporary script to install EasyTier "
echo " EasyTier requires a dedicated empty folder to install"
echo " EasyTier is a developing product and may have some issues "
echo " Using EasyTier requires some basic skills "
echo " You need to face the risks brought by using EasyTier at your own risk "
echo -e "\r\n${RED_COLOR}-------------------------------------------------${RES}\r\n"

# Get platform
if command -v arch >/dev/null 2>&1; then
  platform=$(arch)
else
  platform=$(uname -m)
fi

case "$platform" in
  amd64 | x86_64)
    ARCH="x86_64"
    ;;
  arm64 | aarch64 | *armv8*)
    ARCH="aarch64"
    ;;
  *armv7*)
    ARCH="armv7"
    ;;
  *arm*)
    ARCH="arm"
    ;;
  mips)
    ARCH="mips"
    ;;
  mipsel)
    ARCH="mipsel"
    ;;
  *)
    ARCH="UNKNOWN"
    ;;
esac

# support hf
if [[ "$ARCH" == "armv7" || "$ARCH" == "arm" ]]; then
  if cat /proc/cpuinfo | grep Features | grep -i 'half' >/dev/null 2>&1; then
    ARCH=${ARCH}hf
  fi
fi

echo -e "\r\n${GREEN_COLOR}Your platform: ${ARCH} (${platform}) ${RES}\r\n" 1>&2

if [ "$(id -u)" != "0" ]; then
  echo -e "\r\n${RED_COLOR}This script requires run as Root !${RES}\r\n" 1>&2
  exit 1
elif [ "$ARCH" == "UNKNOWN" ]; then
  echo -e "\r\n${RED_COLOR}Opus${RES}, this script do not support your platform\r\nTry ${GREEN_COLOR}install by hand${RES}\r\n"
  exit 1
fi

# Detect init system
if command -v systemctl >/dev/null 2>&1; then
  INIT_SYSTEM="systemd"
elif command -v rc-update >/dev/null 2>&1; then
  INIT_SYSTEM="openrc"
else
  echo -e "\r\n${RED_COLOR}Error: Unsupported init system (neither systemd nor OpenRC found)${RES}\r\n"
  exit 1
fi

# 生成符合要求的machine-id(UUID格式,替换非法字符为合法字符)
generate_machine_id() {
  local machine_id
  # 生成标准UUID
  if command -v uuidgen >/dev/null 2>&1; then
    machine_id=$(uuidgen | tr 'A-F' 'a-f')
  elif [ -r /proc/sys/kernel/random/uuid ]; then
    machine_id=$(cat /proc/sys/kernel/random/uuid)
  else
    # 兜底生成
    machine_id="$(cat /dev/urandom | tr -dc 'a-f0-9' | head -c8)-$(cat /dev/urandom | tr -dc 'a-f0-9' | head -c4)-$(cat /dev/urandom | tr -dc 'a-f0-9' | head -c4)-$(cat /dev/urandom | tr -dc 'a-f0-9' | head -c4)-$(cat /dev/urandom | tr -dc 'a-f0-9' | head -c12)"
  fi
  # 替换UUID中的部分字符以匹配示例格式(9g2h/534i5j091k4l)
  machine_id=$(echo "$machine_id" | sed -E 's/([0-9]{1})([a-f0-9]{3})/\1g\2/; s/([0-9]{3})([a-f0-9]{2})([0-9]{4})([a-f0-9]{2})/\1i\2j\3k\4l/')
  echo "$machine_id"
}

# 获取主机名(用于--hostname参数)
get_hostname() {
  local hostname=$(hostname)
  # 拼接格式:主机名_域名 - 过滤特殊字符,仅保留字母、数字、下划线、点
  local fqdn=$(hostname -f 2>/dev/null || echo "$hostname")
  # 过滤特殊字符
  hostname=$(echo "$hostname" | tr -cd 'a-zA-Z0-9_.')
  fqdn=$(echo "$fqdn" | tr -cd 'a-zA-Z0-9_.')
  echo "${hostname}_${fqdn}"
}

CHECK() {
  if ! $SKIP_FOLDER_VERIFY; then
    if [ -f "$INSTALL_PATH/easytier-core" ]; then
      echo "There is EasyTier in $INSTALL_PATH. Please choose other path or use \"update\""
        echo -e "Or use Try ${GREEN_COLOR}--skip-folder-verify${RES} to skip"
      exit 0
    fi
  fi

  if [ ! -d "$INSTALL_PATH/" ]; then
    mkdir -p $INSTALL_PATH
  else
    # Check weather path is empty
    if ! $SKIP_FOLDER_VERIFY; then
      if [ -n "$(ls -A $INSTALL_PATH)" ]; then
        echo "EasyTier requires to be installed in an empty directory. Please choose a empty path"
        echo -e "Or use Try ${GREEN_COLOR}--skip-folder-verify${RES} to skip"
        echo -e "Current path: $INSTALL_PATH ( use ${GREEN_COLOR}--skip-folder-fix${RES} to disable folder fix )"
        exit 1
      fi
    fi
  fi
}

INSTALL() {
  # Get version number
  RESPONSE=$(curl -s "https://api.github.com/repos/EasyTier/EasyTier/releases/latest")
  LATEST_VERSION=$(echo "$RESPONSE" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
  LATEST_VERSION=$(echo -e "$LATEST_VERSION" | tr -d '[:space:]')

  if [ -z "$LATEST_VERSION" ]; then
    echo -e "\r\n${RED_COLOR}Opus${RES}, failure to get latest version. Check your internet\r\nOr try ${GREEN_COLOR}install by hand${RES}\r\n"
    exit 1
  fi

  # Download
  echo -e "\r\n${GREEN_COLOR}Downloading EasyTier $LATEST_VERSION ...${RES}"
  rm -rf /tmp/easytier_tmp_install.zip
  BASE_URL="https://github.com/EasyTier/EasyTier/releases/latest/download/easytier-linux-${ARCH}-${LATEST_VERSION}.zip"
  DOWNLOAD_URL=$($NO_GH_PROXY && echo "$BASE_URL" || echo "${GH_PROXY}${BASE_URL}")
  echo -e "Download URL: ${GREEN_COLOR}${DOWNLOAD_URL}${RES}"
  curl -L ${DOWNLOAD_URL} -o /tmp/easytier_tmp_install.zip $CURL_BAR

  # Unzip resource
  echo -e "\r\n${GREEN_COLOR}Unzip resource ...${RES}"
  unzip -o /tmp/easytier_tmp_install.zip -d $INSTALL_PATH/
  mkdir -p $INSTALL_PATH/config
  mv $INSTALL_PATH/easytier-linux-${ARCH}/* $INSTALL_PATH/
  rm -rf $INSTALL_PATH/easytier-linux-${ARCH}/
  chmod +x $INSTALL_PATH/easytier-core $INSTALL_PATH/easytier-cli $INSTALL_PATH/easytier-web $INSTALL_PATH/easytier-web-embed
  if [ -f $INSTALL_PATH/easytier-core ] || [ -f $INSTALL_PATH/easytier-cli ]; then
    echo -e "${GREEN_COLOR} Download successfully! ${RES}"
  else
    echo -e "${RED_COLOR} Download failed! ${RES}"
    exit 1
  fi
}

INIT() {
  if [ ! -f "$INSTALL_PATH/easytier-core" ]; then
    echo -e "\r\n${RED_COLOR}Opus${RES}, unable to find EasyTier\r\n"
    exit 1
  fi

  # 生成machine-id和hostname
  MACHINE_ID=$(generate_machine_id)
  HOSTNAME_PARAM=$(get_hostname)
  # 保存machine-id到配置目录(便于后续查看)
  echo "MACHINE_ID=$MACHINE_ID" > $INSTALL_PATH/config/machine-id.conf
  echo "WEB_PORTAL=$DEFAULT_WEB_PORTAL" >> $INSTALL_PATH/config/machine-id.conf
  echo "HOSTNAME=$HOSTNAME_PARAM" >> $INSTALL_PATH/config/machine-id.conf

  # Create init script (openrc)
  if [ "$INIT_SYSTEM" = "openrc" ]; then
    cat >/etc/init.d/easytier <<EOF
#!/sbin/openrc-run

name="EasyTier"
description="EasyTier Service"
command="$INSTALL_PATH/easytier-core"
# 移除-c参数,仅保留machine-id/-w/--hostname
command_args="--machine-id $MACHINE_ID -w $DEFAULT_WEB_PORTAL --hostname '$HOSTNAME_PARAM'"
command_user="nobody:nobody"
command_background=true

pidfile="/run/\${RC_SVCNAME}.pid"

depend() {
  need net
}
EOF
    chmod +x /etc/init.d/easytier
  fi

  # Create systemd service(单实例easytier.service,移除-c参数)
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    cat >/etc/systemd/system/easytier.service <<EOF
[Unit]
Description=EasyTier Service
Wants=network.target
After=network.target network.service
StartLimitIntervalSec=0

[Service]
Type=simple
WorkingDirectory=$INSTALL_PATH
# 移除-c参数,仅保留machine-id/-w/--hostname
ExecStart=$INSTALL_PATH/easytier-core --machine-id $MACHINE_ID -w $DEFAULT_WEB_PORTAL --hostname '$HOSTNAME_PARAM'
Restart=always
RestartSec=1s

[Install]
WantedBy=multi-user.target
EOF
  fi

  # Startup service
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    systemctl daemon-reload
    # 启用/启动单实例easytier.service
    systemctl enable easytier.service >/dev/null 2>&1
    systemctl start easytier.service
  else
    rc-update add easytier default
    rc-service easytier start
  fi

  # Clean old files
  rm -rf /etc/systemd/system/easytier@.service  # 删除旧的模板服务
  rm -rf /usr/bin/easytier-core /usr/bin/easytier-cli

  # Add link
  ln -sf $INSTALL_PATH/easytier-core /usr/sbin/easytier-core
  ln -sf $INSTALL_PATH/easytier-cli /usr/sbin/easytier-cli
}

SUCCESS() {
  clear
  echo " Install EasyTier successfully!"
  echo -e "\r\n${YELLOW_COLOR}----------------------IMPORTANT----------------------${RES}"
  echo -e "Machine ID: ${GREEN_COLOR}$MACHINE_ID${RES}"
  echo -e "Web Portal (-w): ${GREEN_COLOR}$DEFAULT_WEB_PORTAL${RES}"
  echo -e "Hostname (--hostname): ${GREEN_COLOR}$HOSTNAME_PARAM${RES}"
  echo -e "Service Name: ${GREEN_COLOR}easytier.service${RES}"
  echo -e "Machine ID saved to: ${GREEN_COLOR}$INSTALL_PATH/config/machine-id.conf${RES}"
  echo -e "${YELLOW_COLOR}-----------------------------------------------------${RES}\r\n"
  echo -e "Default Port: ${GREEN_COLOR}11010(UDP+TCP)${RES}, Notice allowing in firewall!\r\n"

  echo -e "Service Management Commands:"
  echo
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    echo -e "Status: ${GREEN_COLOR}systemctl status easytier.service${RES}"
    echo -e "Start: ${GREEN_COLOR}systemctl start easytier.service${RES}"
    echo -e "Restart: ${GREEN_COLOR}systemctl restart easytier.service${RES}"
    echo -e "Stop: ${GREEN_COLOR}systemctl stop easytier.service${RES}"
    echo -e "Enable Auto-Start: ${GREEN_COLOR}systemctl enable easytier.service${RES}"
  else
    echo -e "Status: ${GREEN_COLOR}rc-service easytier status${RES}"
    echo -e "Start: ${GREEN_COLOR}rc-service easytier start${RES}"
    echo -e "Restart: ${GREEN_COLOR}rc-service easytier restart${RES}"
    echo -e "Stop: ${GREEN_COLOR}rc-service easytier stop${RES}"
    echo -e "Enable Auto-Start: ${GREEN_COLOR}rc-update add easytier default${RES}"
  fi
  echo
}

UNINSTALL() {
  echo -e "\r\n${GREEN_COLOR}Uninstall EasyTier ...${RES}\r\n"
  echo -e "${GREEN_COLOR}Stop process ...${RES}"
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    systemctl disable easytier.service >/dev/null 2>&1
    systemctl stop easytier.service >/dev/null 2>&1
    # 清理旧的模板服务残留
    systemctl disable "easytier@*" >/dev/null 2>&1
    systemctl stop "easytier@*" >/dev/null 2>&1
  else
    rc-update del easytier
    rc-service easytier stop
  fi
  echo -e "${GREEN_COLOR}Delete files ...${RES}"
  # 删除所有相关文件
  rm -rf $INSTALL_PATH 
  rm -rf /etc/systemd/system/easytier.service /etc/systemd/system/easytier@.service
  rm -rf /etc/init.d/easytier
  rm -rf /usr/bin/easytier-core /usr/bin/easytier-cli
  rm -rf /usr/sbin/easytier-core /usr/sbin/easytier-cli
  
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    systemctl daemon-reload
  fi
  
  echo -e "\r\n${GREEN_COLOR}EasyTier was removed successfully! ${RES}\r\n"
}

# Minimizes downtime by preparing new files before stopping the service.
UPDATE() {
  if [ ! -f "$INSTALL_PATH/easytier-core" ]; then
    echo -e "\r\n${RED_COLOR}Error${RES}: EasyTier not found in $INSTALL_PATH. Cannot perform update.\r\n"
    exit 1
  fi

  # 1. Get the latest version info (while service is still running)
  echo -e "${GREEN_COLOR}Checking for the latest version...${RES}"
  RESPONSE=$(curl -s "https://api.github.com/repos/EasyTier/EasyTier/releases/latest")
  LATEST_VERSION=$(echo "$RESPONSE" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
  LATEST_VERSION=$(echo -e "$LATEST_VERSION" | tr -d '[:space:]')

  if [ -z "$LATEST_VERSION" ]; then
    echo -e "\r\n${RED_COLOR}Error${RES}: Failed to get the latest version. Please check your network connection.\r\n"
    exit 1
  fi

  echo -e "Latest version found: ${GREEN_COLOR}$LATEST_VERSION${RES}"

  # 2. Download and extract the new version to a temporary directory (while service is still running)
  TEMP_UPDATE_DIR=$(mktemp -d /tmp/easytier_update_XXXXXX)
  echo -e "${GREEN_COLOR}Downloading new version to temporary directory: $TEMP_UPDATE_DIR${RES}"
  
  BASE_URL="https://github.com/EasyTier/EasyTier/releases/latest/download/easytier-linux-${ARCH}-${LATEST_VERSION}.zip"
  DOWNLOAD_URL=$($NO_GH_PROXY && echo "$BASE_URL" || echo "${GH_PROXY}${BASE_URL}")
  
  echo -e "Download URL: ${GREEN_COLOR}${DOWNLOAD_URL}${RES}"
  curl -L ${DOWNLOAD_URL} -o "$TEMP_UPDATE_DIR/easytier.zip" $CURL_BAR
  if [ $? -ne 0 ]; then
      echo -e "${RED_COLOR}Download failed!${RES}"
      rm -rf "$TEMP_UPDATE_DIR"
      exit 1
  fi
  
  unzip -o "$TEMP_UPDATE_DIR/easytier.zip" -d "$TEMP_UPDATE_DIR/"
  
  NEW_CORE_FILE="$TEMP_UPDATE_DIR/easytier-linux-${ARCH}/easytier-core"
  if [ ! -f "$NEW_CORE_FILE" ]; then
      echo -e "${RED_COLOR}Extraction failed or the downloaded archive is invalid.${RES}"
      rm -rf "$TEMP_UPDATE_DIR"
      exit 1
  fi
  
  echo -e "${GREEN_COLOR}New version is ready. Starting update process...${RES}"
  
  # 3. Enter minimal downtime window
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    echo -e "\r\n${YELLOW_COLOR}Stopping EasyTier service...${RES}"
    systemctl stop easytier.service
  else
    echo -e "\r\n${YELLOW_COLOR}Stopping EasyTier service...${RES}"
    rc-service easytier stop
  fi

  # Backup critical files
  echo "Backing up configuration..."
  BACKUP_CONFIG_DIR=$(mktemp -d /tmp/easytier_config_backup_XXXXXX)
  if [ -d "$INSTALL_PATH/config" ]; then
      cp -a "$INSTALL_PATH/config" "$BACKUP_CONFIG_DIR/"
  fi
  
  echo "Replacing files..."
  # Remove old binaries and docs, but not the config directory
  rm -f "$INSTALL_PATH/easytier-core" "$INSTALL_PATH/easytier-cli" "$INSTALL_PATH/LICENSE" "$INSTALL_PATH/README.md"
  
  # Move new files into the installation directory
  mv "$TEMP_UPDATE_DIR/easytier-linux-${ARCH}"/* "$INSTALL_PATH/"
  chmod +x "$INSTALL_PATH/easytier-core" "$INSTALL_PATH/easytier-cli" "$INSTALL_PATH/easytier-web" "$INSTALL_PATH/easytier-web-embed"

  # Restore configuration
  if [ -d "$BACKUP_CONFIG_DIR/config" ]; then
      cp -af "$BACKUP_CONFIG_DIR/config/." "$INSTALL_PATH/config/"
  fi

  # 更新服务启动脚本(保留原有参数)
  if [ -f "$INSTALL_PATH/config/machine-id.conf" ]; then
    source "$INSTALL_PATH/config/machine-id.conf"
    # 更新时再次校验Web Portal格式
    validate_web_portal "$WEB_PORTAL"
    if [ "$INIT_SYSTEM" = "systemd" ]; then
      sed -i "s|ExecStart=.*|ExecStart=$INSTALL_PATH/easytier-core --machine-id $MACHINE_ID -w $DEFAULT_WEB_PORTAL --hostname '$HOSTNAME'|" /etc/systemd/system/easytier.service
      systemctl daemon-reload
    elif [ "$INIT_SYSTEM" = "openrc" ]; then
      sed -i "s|command_args=.*|command_args=\"--machine-id $MACHINE_ID -w $DEFAULT_WEB_PORTAL --hostname '$HOSTNAME'\"|" /etc/init.d/easytier
    fi
  fi
  
  # 4. Start the service
  if [ "$INIT_SYSTEM" = "systemd" ]; then
    echo -e "${GREEN_COLOR}Starting new version of EasyTier service...${RES}"
    systemctl start easytier.service
  else
    echo -e "${GREEN_COLOR}Starting new version of EasyTier service...${RES}"
    rc-service easytier start
  fi
  
  # 5. Clean up temporary files
  echo "Cleaning up temporary files..."
  rm -rf "$TEMP_UPDATE_DIR"
  rm -rf "$BACKUP_CONFIG_DIR"
  
  echo -e "\r\n${GREEN_COLOR}EasyTier was successfully updated to version $LATEST_VERSION!${RES}\r\n"
}

# CURL progress
if curl --help | grep progress-bar >/dev/null 2>&1; then
  CURL_BAR="--progress-bar"
fi

# The temp directory must exist
if [ ! -d "/tmp" ]; then
  mkdir -p /tmp
fi

echo $COMMEND

# ========== 扩展命令分发逻辑 ==========
if [ "$COMMEND" = "uninstall" ]; then
  UNINSTALL
elif [ "$COMMEND" = "uninstall-web" ]; then
  UNINSTALL_WEB
elif [ "$COMMEND" = "update" ]; then
  UPDATE
elif [ "$COMMEND" = "install" ]; then
  CHECK
  INSTALL
  INIT
  if [ -f "$INSTALL_PATH/easytier-core" ]; then
    SUCCESS
  else
    echo -e "${RED_COLOR} Install fail, try install by hand${RES}"
  fi
elif [ "$COMMEND" = "install-web" ]; then
  INSTALL_WEB
elif [ "$COMMEND" = "install-web-embed" ]; then
  INSTALL_WEB_EMBED
else
  echo -e "${RED_COLOR} Error Command ${RES}\n\r"
  echo " ALLOW:"
  echo -e "\n\r${GREEN_COLOR} install, install-web, install-web-embed, uninstall, uninstall-web, update, help ${RES}"
fi

rm -rf /tmp/easytier_tmp_*
# 将提供的自定义脚本保存为install.sh后,赋予执行权限
chmod +x install.sh

提示:自定义脚本默认启用GitHub代理(https://ghfast.top/),可通过--no-gh-proxy参数禁用代理,或通过--gh-proxy参数指定自定义代理URL;同时支持--skip-folder-verify等跳过目录校验的参数,适合特殊安装场景。

二、核心步骤:Linux自建EasyTier服务器

EasyTier服务器节点是整个私有网络的核心,负责节点间的通信与转发。部署过程十分简洁,支持默认配置快速启动,也可通过修改配置文件自定义参数。

2.1 快速部署:使用默认配置安装

若无需自定义配置,直接执行以下命令即可完成核心服务安装(自定义脚本支持更多默认优化配置):

# 基础安装(默认安装路径/opt/easytier)
bash ./install.sh install

# 可选:自定义安装路径(如安装到/data/easytier)
bash ./install.sh install /data/easytier

# 可选:跳过目录校验(适合非空目录安装)
bash ./install.sh install --skip-folder-verify

执行后脚本会自动完成以下操作(自定义脚本增强特性):

检测系统架构(x86_64、arm64、armv7等多种架构,兼容性更强),自动下载对应版本的EasyTier核心包;

  1. 默认安装路径:/opt/easytier(可在安装时指定自定义路径,如bash ./install.sh install /data/easytier);

生成默认配置文件(/opt/easytier/config/default.conf)、机器唯一码(UUID格式,自动保存到/opt/easytier/config/machine-id.conf,便于后续查看);

  1. 创建系统服务(easytier.service),并设置开机自启。

安装成功后,会输出关键信息(机器ID、默认Web Portal、主机名、服务管理命令),核心默认端口为11010(UDP+TCP),客户端可通过此端口连接服务器。其中默认Web Portal格式为“udp://public.easytiertop:22020/主机名_年月日@”,可通过--web-portal参数自定义。

2.2 自定义配置:修改default.conf文件

若需要自定义网络名称、密码、端口等参数,可修改安装目录下的配置文件:

vi /opt/easytier/config/default.conf

核心配置参数说明(参考示例):

# 自定义主机名(用于节点识别)
hostname = "easytier-server-01"

# 实例名(可自定义)
instance_name = "server-main"

# 机器唯一码(建议指定,避免重启后配置丢失)
instance_id = "bf3d6922-2d97-47ce-99c6-ed74d6abdb7d"

# 是否启用DHCP(自动分配IP,默认开启)
dhcp = true

# 监听端口(默认11010,支持TCP、UDP、WG协议)
listeners = [
  "tcp://0.0.0.0:11010",
  "udp://0.0.0.0:11010",
  "wg://0.0.0.0:11011",
]

# 私有网络配置(核心!用于节点间加密通信)
[network_identity]
network_name = "my-private-network"  # 自定义网络名称
network_secret = "my-strong-password"  # 自定义网络密码(节点需一致才能互通)

# 对等节点配置(若需要连接其他EasyTier节点,可添加)
[[peer]]
uri = "tcp://other-server-ip:11010"  # 其他节点的连接地址

# 代理网络配置(指定需要穿透的网段)
[[proxy_network]]
cidr = "192.168.0.0/24"  # 本地需要被其他节点访问的网段

修改完成后,重启服务使配置生效:

# systemd系统
systemctl restart easytier.service

# OpenRC系统(如OpenWrt)
rc-service easytier restart

三、Web管理端部署:两种模式任选

EasyTier提供了Web管理界面,支持可视化配置节点、管理网络。根据需求可选择“仅安装Web后端API”(对接官方前端)或“安装Web前后端集成版”(本地直接访问),两种模式的部署命令都十分简洁。

3.1 模式1:仅安装Web后端API(推荐,轻量)

此模式仅部署Web后端API服务,不包含前端页面,可直接使用EasyTier官方前端(https://easytier.cn/web)访问你的后端,适合不想额外占用服务器资源的场景。

# 安装仅Web后端API服务
bash ./install.sh install-web

部署完成后(自定义脚本会自动检查核心包,缺失则自动安装):

  • Web后端API地址:http://服务器IP:11211

  • 服务名称:easytier-web.service(与集成版共用服务名,安装后会覆盖原有Web服务)

  • 使用方式:打开官方前端,在设置中填写你的API地址(http://服务器IP:11211),即可关联管理你的节点。

3.2 模式2:安装Web前后端集成版(本地访问)

此模式会同时部署Web前端和后端服务,可直接通过服务器IP+前端端口访问管理界面,适合无外网访问权限的内网环境。支持自定义数据存储路径、前端/后端端口。

3.2.1 默认参数安装

# 默认参数安装Web前后端集成版
bash ./install.sh install-web-embed

默认配置:

  • Web前端地址:http://服务器IP:11210

  • Web后端API地址:http://服务器IP:11211

  • 数据存储路径:/opt/easytier/et.db(SQLite数据库)

3.2.2 自定义参数安装

若需要修改端口、数据存储路径,可通过以下参数自定义(自定义脚本同时支持短参数和长参数,更灵活):

  • -d/--db-path:指定数据存储路径(如自定义到/data目录,避免系统盘占用);

  • -l/--web-port:指定Web前端端口(如修改为21010,避免端口冲突);

  • -a/--api-port:指定Web后端端口(如修改为21011)。

示例:修改前端端口为21010、后端端口为21011,数据存储到/data/easytier/et.db(两种参数格式均可):

# 短参数格式
bash ./install.sh install-web-embed -d /data/easytier/et.db -l 21010 -a 21011

# 长参数格式(更易理解)
bash ./install.sh install-web-embed --db-path /data/easytier/et.db --web-port 21010 --api-port 21011

安装成功后,脚本会输出最终的ExecStart命令,可通过该命令验证配置是否生效。

四、客户端接入:两种方式对接自建节点

Linux客户端接入自建的EasyTier节点,支持两种方式:通过Web控制台配置(简单直观)、通过本地配置文件配置(适合无Web界面场景)。

4.1 方式1:通过Web管理控制台接入

此方式需先部署Web后端(模式1或模式2),客户端通过指定Web Portal地址,自动同步控制台配置,无需手动修改文件。

# 格式:bash ./install.sh install --web-portal 自定义Portal地址
# 示例1:使用自定义令牌
bash ./install.sh install --web-portal udp://ouy.taofile.cn:22020/ouy@jiajun.com

# 示例2:使用脚本默认生成的Portal(主机名_年月日)
bash ./install.sh install

参数说明:

  • udp://服务器地址:22020:Web后端的Portal地址(默认端口22020,需确保服务器开放此端口);

  • ouy@jiajun.com:自定义的账户标识(用于在控制台区分不同客户端)。

注意:自定义脚本内置Web Portal格式校验函数,仅允许udp://或tcp://开头,支持自动修复路径中的双斜杠错误;若格式错误(如空令牌、端口非法),会输出详细错误原因和正确示例,无需手动排查。正确格式为“udp://域名:端口/令牌”,如“udp://public.easytiertop:22020/sgphwyun_20251219@”。

4.2 方式2:通过本地配置文件接入

适合无Web界面的场景,通过手动修改客户端的default.conf文件,指定要连接的服务器节点。

  1. 先在客户端安装EasyTier核心服务:

# 在客户端安装EasyTier核心服务(使用自定义脚本)
bash ./install.sh install
  1. 修改客户端配置文件:

vi /opt/easytier/config/default.conf

关键配置(需与服务器端一致):

# 与服务器端一致的私有网络配置
[network_identity]
network_name = "my-private-network"  # 必须和服务器的network_name相同
network_secret = "my-strong-password"  # 必须和服务器的network_secret相同

# 添加服务器节点为对等节点
[[peer]]
uri = "tcp://服务器IP:11010"  # 服务器的核心端口(默认11010)
  1. 重启客户端服务,完成接入:

systemctl restart easytier.service

五、常用操作:服务管理与卸载

掌握以下常用命令,方便后续维护节点服务:

5.1 服务状态查看/启动/停止/重启

# systemd系统(Ubuntu/CentOS 7+等)
# 查看核心服务状态
systemctl status easytier.service
# 查看Web服务状态
systemctl status easytier-web.service

# 启动服务
systemctl start easytier.service
systemctl start easytier-web.service

# 停止服务
systemctl stop easytier.service
systemctl stop easytier-web.service

# 重启服务
systemctl restart easytier.service
systemctl restart easytier-web.service

# OpenRC系统(OpenWrt等)
rc-service easytier status
rc-service easytier start
rc-service easytier stop
rc-service easytier restart

# 自定义脚本新增:升级EasyTier到最新版本(无需重新下载脚本)
bash ./install.sh update

5.2 卸载操作

根据需要选择卸载Web服务或全量卸载EasyTier:

  • 仅卸载Web服务(保留核心服务):

# 仅卸载Web服务(保留核心服务,使用自定义脚本)
bash ./install.sh uninstall-web

说明:自定义脚本执行此命令后,会自动停止并删除easytier-web.service,清理对应的服务配置文件;若需要彻底删除Web相关二进制文件,需手动删除/opt/easytier/easytier-web、/opt/easytier/easytier-web-embed等文件。

  • 全量卸载EasyTier(核心服务+Web服务+所有配置文件):

# 全量卸载EasyTier(核心服务+Web服务+所有配置文件,使用自定义脚本)
bash ./install.sh uninstall

六、常见问题排查

6.1 安装时提示“Unknown option”

原因:旧版本官方脚本不支持短参数,但本次使用的自定义脚本同时支持短参数(如-l 21010)和长参数(如--web-port 21010),若仍提示此错误,可尝试重新执行脚本或使用长参数格式。解决方案:直接使用自定义脚本的长参数格式(如--web-port 21010),或确认脚本权限是否正确(需chmod +x install.sh)。

6.2 客户端无法连接服务器

排查步骤:

  1. 检查服务器防火墙是否开放对应端口(11010、11210、11211等);

  2. 查看服务状态,确认easytier.service正常运行;

  3. 检查客户端与服务器的network_name、network_secret是否一致;

  4. 确认服务器IP地址正确,无网络路由问题。

6.3 Web界面无法访问

排查步骤:

  1. 检查easytier-web.service是否正常运行;

  2. 确认自定义端口未被其他服务占用(可通过netstat -tuln | grep 端口号 查看);

  3. 若为集成版,检查数据存储路径是否有写入权限(如/opt/easytier需root权限)。

七、总结

Linux自建EasyTier节点的核心优势在于部署简单、配置灵活,支持多种网络场景需求。通过本文的步骤,你可以快速搭建核心服务器、部署Web管理端,并完成客户端接入。关键注意事项:确保端口开放、网络配置参数一致、使用正确的Web Portal格式。如果需要更高级的功能(如多节点集群、WG协议优化),可参考官方文档进一步探索。

说明:本文所有操作均基于自定义EasyTier安装脚本,该脚本增强了架构兼容性、参数支持和错误校验能力,相比官方脚本更易用、更稳定。脚本核心功能:安装/升级/卸载核心服务、Web服务(两种模式),支持自定义安装路径、端口、数据存储路径等。