diff --git a/README.md b/README.md index 8b6cd7ce..78cda862 100644 --- a/README.md +++ b/README.md @@ -48,32 +48,37 @@ Choose the installation method that best suits your needs: +Linux (Recommended): ```bash -# 1. Download pre-built binary (Recommended, All platforms supported) -# Visit https://github.com/EasyTier/EasyTier/releases +curl -fsSL "https://github.com/EasyTier/EasyTier/blob/main/script/install.sh?raw=true" | sudo bash -s install +``` -# 2. Install via cargo (Latest development version) -cargo install --git https://github.com/EasyTier/EasyTier.git easytier - -# 3. Install via Docker -# See https://easytier.cn/en/guide/installation.html#installation-methods - -# 4. Linux Quick Install -wget -O- https://raw.githubusercontent.com/EasyTier/EasyTier/main/script/install.sh | sudo bash -s install - -# 5. MacOS via Homebrew +Homebrew (MacOS/Linux): +```bash brew tap brewforge/chinese brew install --cask easytier-gui - -# 6. OpenWrt Luci Web UI -# Visit https://github.com/EasyTier/luci-app-easytier - -# 7. (Optional) Install shell completions: -easytier-core --gen-autocomplete fish > ~/.config/fish/completions/easytier-core.fish -easytier-cli gen-autocomplete fish > ~/.config/fish/completions/easytier-cli.fish - ``` +Windows (Recommended, run with administrator privileges): +```powershell +irm "https://github.com/EasyTier/EasyTier/blob/main/script/install.ps1?raw=true" | iex +``` + +Install via cargo (Latest development version): +```bash +cargo install --git https://github.com/EasyTier/EasyTier.git easytier +``` + +[Install pre-built binary](https://github.com/EasyTier/EasyTier/releases) (Recommended, All platforms supported) + +[Install via Docker](https://easytier.cn/en/guide/installation.html#installation-methods) + +[Install OpenWrt ipk package](https://github.com/EasyTier/luci-app-easytier) + +Additional steps: + +[One-Click Register Service](https://easytier.cn/en/guide/network/oneclick-install-as-service.html) (Automatically start when the system boots and run in the background) + ### 🚀 Basic Usage #### Quick Networking with Shared Nodes diff --git a/README_CN.md b/README_CN.md index b90560a1..2e9d31fa 100644 --- a/README_CN.md +++ b/README_CN.md @@ -48,33 +48,37 @@ 选择最适合您需求的安装方式: +Linux(推荐): ```bash -# 1. 下载预编译二进制文件(推荐,支持所有平台) -# 访问 https://github.com/EasyTier/EasyTier/releases +curl -fsSL "https://github.com/EasyTier/EasyTier/blob/main/script/install.sh?raw=true" | sudo bash -s install +``` -# 2. 通过 cargo 安装(最新开发版本) -cargo install --git https://github.com/EasyTier/EasyTier.git easytier - -# 3. 通过 Docker 安装 -# 参见 https://easytier.cn/guide/installation.html#%E5%AE%89%E8%A3%85%E6%96%B9%E5%BC%8F - -# 4. Linux 快速安装 -wget -O- https://raw.githubusercontent.com/EasyTier/EasyTier/main/script/install.sh | sudo bash -s install - -# 5. MacOS 通过 Homebrew 安装 +Homebrew(MacOS/Linux): +```bash brew tap brewforge/chinese brew install --cask easytier-gui - -# 6. OpenWrt Luci Web 界面 -# 访问 https://github.com/EasyTier/luci-app-easytier - -# 7.(可选)安装 Shell 补全功能: -# Fish 补全 -easytier-core --gen-autocomplete fish > ~/.config/fish/completions/easytier-core.fish -easytier-cli gen-autocomplete fish > ~/.config/fish/completions/easytier-cli.fish - ``` +Windows(推荐,请以管理员权限运行): +```powershell +irm "https://github.com/EasyTier/EasyTier/blob/main/script/install.ps1?raw=true" | iex +``` + +通过 cargo 安装(最新开发版本): +```bash +cargo install --git https://github.com/EasyTier/EasyTier.git easytier +``` + +[下载预编译文件](https://github.com/EasyTier/EasyTier/releases)(推荐,支持所有平台) + +[通过 Docker 安装](https://easytier.cn/guide/installation.html#%E5%AE%89%E8%A3%85%E6%96%B9%E5%BC%8F) + +[安装 OpenWrt ipk 软件包](https://github.com/EasyTier/luci-app-easytier) + +附加步骤: + +[一键注册系统服务](https://easytier.cn/guide/network/oneclick-install-as-service.html)(系统启动时自动后台运行) + ### 🚀 基本用法 #### 使用共享节点快速组网 diff --git a/script/install.ps1 b/script/install.ps1 new file mode 100644 index 00000000..9a5891fc --- /dev/null +++ b/script/install.ps1 @@ -0,0 +1,234 @@ +<# +.SYNOPSIS + EasyTier Windows Installer + +.DESCRIPTION + Download EasyTier from GitHub Release and install it. + Copies binaries to the install directory and updates the system PATH. + +.PARAMETER Version + Target version: "latest", "stable", or a specific tag like "v2.5.0". + Default: "latest" + +.PARAMETER InstallDir + Directory to install EasyTier binaries. + Default: "$env:ProgramFiles\EasyTier" + +.EXAMPLE + .\install.ps1 + .\install.ps1 -Version v2.5.0 + .\install.ps1 -InstallDir "C:\EasyTier" + +.NOTES + Administrator privileges are required. + After installation, run: easytier-cli service install + to register EasyTier as a system service. +#> +param( + [Parameter(Position = 0)] + [ValidatePattern('^(stable|latest|v?\d+\.\d+\.\d+(-[^\s]+)?)$')] + [string]$Version = 'latest', + + [Parameter(Position = 1)] + [string]$InstallDir = "$env:ProgramFiles\EasyTier" +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$ProgressPreference = 'SilentlyContinue' + +# Force TLS 1.2+ for GitHub API and download requests +[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 + +# --------------------------------------------------------------------------- +# Constants +# --------------------------------------------------------------------------- +$GITHUB_REPO = 'EasyTier/EasyTier' +$GITHUB_API = "https://api.github.com/repos/$GITHUB_REPO" +$GITHUB_RELEASE_URL = "https://github.com/$GITHUB_REPO/releases" + +# --------------------------------------------------------------------------- +# Administrator check +# --------------------------------------------------------------------------- +$currentPrincipal = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() +if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + Write-Error 'Please run this script as Administrator.' + exit 1 +} + +# --------------------------------------------------------------------------- +# Architecture detection +# --------------------------------------------------------------------------- +# Check PROCESSOR_ARCHITEW6432 first to correctly identify 64-bit OS when +# running under 32-bit PowerShell (WoW64), where PROCESSOR_ARCHITECTURE +# reports 'x86' even on a 64-bit machine. +$cpuArch = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } +switch ($cpuArch) { + 'AMD64' { $arch = 'x86_64' } + 'ARM64' { $arch = 'arm64' } + 'x86' { $arch = 'i686' } + default { + Write-Error "Unsupported processor architecture: $cpuArch" + exit 1 + } +} +$assetBaseName = "easytier-windows-$arch" + +Write-Host '' +Write-Host ' ===============================================' -ForegroundColor Cyan +Write-Host ' EasyTier Windows Installer ' -ForegroundColor Cyan +Write-Host ' ===============================================' -ForegroundColor Cyan +Write-Host '' +Write-Host " Architecture : $arch" -ForegroundColor White +Write-Host '' + +# --------------------------------------------------------------------------- +# Step 1 - Resolve release version +# --------------------------------------------------------------------------- +Write-Host '[1/5] Querying GitHub Release info...' -ForegroundColor Yellow + +try { + if ($Version -eq 'latest' -or $Version -eq 'stable') { + $releaseInfo = Invoke-RestMethod ` + -Uri "$GITHUB_API/releases/latest" ` + -Headers @{ 'User-Agent' = 'EasyTier-Installer/1.0' } ` + -ErrorAction Stop + } + else { + $tag = if ($Version -notmatch '^v') { "v$Version" } else { $Version } + $releaseInfo = Invoke-RestMethod ` + -Uri "$GITHUB_API/releases/tags/$tag" ` + -Headers @{ 'User-Agent' = 'EasyTier-Installer/1.0' } ` + -ErrorAction Stop + } +} +catch { + Write-Error "Failed to fetch release info from GitHub: $_`nPlease check your network or visit $GITHUB_RELEASE_URL to download manually." + exit 1 +} + +$releaseVersion = $releaseInfo.tag_name +$assetZipName = "$assetBaseName-$releaseVersion.zip" + +Write-Host " Version : $releaseVersion" -ForegroundColor Green + +# --------------------------------------------------------------------------- +# Step 2 - Find download URL +# --------------------------------------------------------------------------- +Write-Host '' +Write-Host '[2/5] Resolving download URL...' -ForegroundColor Yellow +$asset = $releaseInfo.assets | + Where-Object { $_.name -eq $assetZipName } | + Select-Object -First 1 + +if (-not $asset) { + $availableAssets = ($releaseInfo.assets | Select-Object -ExpandProperty name) -join ', ' + Write-Error "Asset '$assetZipName' not found in release $releaseVersion.`nAvailable: $availableAssets`nVisit $GITHUB_RELEASE_URL to download manually." + exit 1 +} + +$downloadUrl = $asset.browser_download_url +Write-Host " URL : $downloadUrl" -ForegroundColor DarkGray + +# --------------------------------------------------------------------------- +# Step 3 - Download ZIP +# --------------------------------------------------------------------------- +Write-Host '' +Write-Host "[3/5] Downloading $assetZipName ..." -ForegroundColor Yellow + +$tempDir = Join-Path $env:TEMP "easytier-install-$(Get-Random)" +$zipPath = Join-Path $tempDir $assetZipName + +New-Item -ItemType Directory -Force -Path $tempDir | Out-Null + +try { + Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath -ErrorAction Stop + $sizeMB = [math]::Round((Get-Item $zipPath).Length / 1MB, 2) + Write-Host " Download complete ($sizeMB MB)" -ForegroundColor Green +} +catch { + Write-Error "Download failed: $_" + Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue + exit 1 +} + +# --------------------------------------------------------------------------- +# Step 4 - Extract & copy to install directory +# --------------------------------------------------------------------------- +Write-Host '' +Write-Host '[4/5] Extracting and copying files...' -ForegroundColor Yellow + +$extractDir = Join-Path $tempDir 'extracted' +New-Item -ItemType Directory -Force -Path $extractDir | Out-Null + +try { + Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force -ErrorAction Stop +} +catch { + Write-Error "Extraction failed: $_" + Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue + exit 1 +} + +# ZIP may contain a sub-directory; find exe files recursively and flatten +$exeFiles = Get-ChildItem -Path $extractDir -Filter '*.exe' -Recurse +if (-not $exeFiles) { + Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue + Write-Error 'No .exe files found after extraction. The ZIP may be malformed.' + exit 1 +} + +$binSourceDir = $exeFiles[0].DirectoryName + +try { + New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null + Get-ChildItem -Path $binSourceDir | Copy-Item -Destination $InstallDir -Force +} +catch { + Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue + Write-Error "Failed to copy files to install directory: $_" + exit 1 +} + +Write-Host " Installed to: $InstallDir" -ForegroundColor Green + +# --------------------------------------------------------------------------- +# Step 5 - Update system PATH +# --------------------------------------------------------------------------- +Write-Host '' +Write-Host '[5/5] Updating system PATH...' -ForegroundColor Yellow + +$systemPath = [Environment]::GetEnvironmentVariable('PATH', 'Machine') +# Split on ';' and normalize (trim trailing backslash, case-insensitive) for an exact match +$pathEntries = $systemPath -split ';' | ForEach-Object { $_.TrimEnd('\') } +$normalizedInstallDir = $InstallDir.TrimEnd('\') +if ($pathEntries -inotcontains $normalizedInstallDir) { + [Environment]::SetEnvironmentVariable('PATH', "$systemPath;$InstallDir", 'Machine') + $env:PATH = "$env:PATH;$InstallDir" + Write-Host " Added $InstallDir to system PATH" -ForegroundColor Green +} +else { + Write-Host " $InstallDir is already in PATH, skipping" -ForegroundColor DarkGray +} + +# --------------------------------------------------------------------------- +# Cleanup +# --------------------------------------------------------------------------- +try { + Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue +} +catch { + Write-Warning "Could not remove temp dir $tempDir : $_" +} + +# --------------------------------------------------------------------------- +# Done +# --------------------------------------------------------------------------- +Write-Host '' +Write-Host " [OK] EasyTier $releaseVersion installation complete!" -ForegroundColor Green +Write-Host '' +Write-Host " Install dir : $InstallDir" -ForegroundColor White +Write-Host ' User guide : https://easytier.cn/en/guide/network/decentralized-networking.html' -ForegroundColor DarkGray +Write-Host '' +Write-Host ' NOTE: If PATH was just updated, please restart your terminal.' -ForegroundColor DarkYellow +Write-Host ''