mirror of https://github.com/go-gost/gost.git
239 lines
8.0 KiB
PowerShell
239 lines
8.0 KiB
PowerShell
#Requires -RunAsAdministrator
|
|
<#
|
|
.SYNOPSIS
|
|
Builds gost from source and installs it as a Windows service.
|
|
|
|
.DESCRIPTION
|
|
Runs "go build" against the local source tree, copies the resulting binary
|
|
to a target directory, and registers it as a Windows service using the
|
|
native Windows Service Control Manager. gost is built with go-svc and
|
|
runs as a proper Windows service without any wrapper.
|
|
|
|
.PARAMETER InstallDir
|
|
Directory where gost.exe and gost.yml are placed.
|
|
Default: C:\Program Files\gost
|
|
|
|
.PARAMETER ConfigFile
|
|
Path to an existing gost config file to use. If omitted and no config
|
|
exists in InstallDir, a minimal placeholder is created.
|
|
|
|
.PARAMETER ServiceName
|
|
Windows service name. Default: gost
|
|
|
|
.PARAMETER DisplayName
|
|
Windows service display name. Default: GOST Tunnel
|
|
|
|
.PARAMETER ExtraArgs
|
|
Additional arguments passed to gost.exe, e.g. "-L :8080 -D".
|
|
The -C flag pointing to the config file is always added automatically.
|
|
|
|
.PARAMETER StartupType
|
|
Service start type: Automatic, Manual, or Disabled. Default: Automatic
|
|
|
|
.PARAMETER Start
|
|
Start the service immediately after installation.
|
|
|
|
.EXAMPLE
|
|
# Build, install with defaults, and start immediately
|
|
.\install-service.ps1 -Start
|
|
|
|
.EXAMPLE
|
|
# Install with a custom config
|
|
.\install-service.ps1 -ConfigFile C:\etc\gost.yml -Start
|
|
|
|
.EXAMPLE
|
|
# Install with inline service definition (no config file)
|
|
.\install-service.ps1 -ExtraArgs "-L socks5://:1080 -L http://:8080" -Start
|
|
#>
|
|
|
|
[CmdletBinding(SupportsShouldProcess)]
|
|
param(
|
|
[string]$InstallDir = "C:\Program Files\gost",
|
|
[string]$ConfigFile = "",
|
|
[string]$ServiceName = "gost",
|
|
[string]$DisplayName = "GOST Tunnel",
|
|
[string]$ExtraArgs = "",
|
|
[ValidateSet("Automatic","Manual","Disabled")]
|
|
[string]$StartupType = "Automatic",
|
|
[switch]$Start
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
# Directory containing this script == repo root
|
|
$RepoRoot = $PSScriptRoot
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
function Write-Step([string]$msg) { Write-Host "`n==> $msg" -ForegroundColor Cyan }
|
|
function Write-Ok([string]$msg) { Write-Host " OK $msg" -ForegroundColor Green }
|
|
function Write-Warn([string]$msg) { Write-Host " WARN $msg" -ForegroundColor Yellow }
|
|
|
|
function Build-Binary([string]$destDir) {
|
|
if (-not (Get-Command go -ErrorAction SilentlyContinue)) {
|
|
throw "go not found in PATH. Please install Go from https://go.dev/dl/"
|
|
}
|
|
|
|
Write-Step "Building gost from source ($RepoRoot)..."
|
|
|
|
if (-not (Test-Path $destDir)) {
|
|
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
|
|
}
|
|
|
|
$exeDest = Join-Path $destDir "gost.exe"
|
|
|
|
# Embed version: prefer git tag, fall back to version.go
|
|
$ldflags = "-s -w"
|
|
$version = $null
|
|
if (Get-Command git -ErrorAction SilentlyContinue) {
|
|
$version = git -C $RepoRoot describe --tags --abbrev=0 2>$null
|
|
}
|
|
if (-not $version) {
|
|
$verFile = Join-Path $RepoRoot "cmd\gost\version.go"
|
|
if (Test-Path $verFile) {
|
|
$match = Select-String -Path $verFile -Pattern 'version\s*=\s*"([^"]+)"'
|
|
if ($match) { $version = $match.Matches[0].Groups[1].Value }
|
|
}
|
|
}
|
|
if ($version) { $ldflags = "-s -w -X 'main.version=$version'" }
|
|
|
|
$goArgs = @("build", "-ldflags", $ldflags, "-o", $exeDest, "./cmd/gost")
|
|
Write-Host " go $($goArgs -join ' ')" -ForegroundColor DarkGray
|
|
|
|
& go @goArgs 2>&1 | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
|
|
if ($LASTEXITCODE -ne 0) { throw "go build failed (exit $LASTEXITCODE)" }
|
|
|
|
Write-Ok "Built: $exeDest"
|
|
return $exeDest
|
|
}
|
|
|
|
function Ensure-Config([string]$installDir, [string]$userConfig) {
|
|
$dest = Join-Path $installDir "gost.yml"
|
|
|
|
if ($userConfig -ne "") {
|
|
if (-not (Test-Path $userConfig)) {
|
|
throw "Config file not found: $userConfig"
|
|
}
|
|
$resolvedSrc = (Resolve-Path $userConfig).Path
|
|
$resolvedDest = if (Test-Path $dest) { (Resolve-Path $dest).Path } else { "" }
|
|
if ($resolvedSrc -ne $resolvedDest) {
|
|
Copy-Item $userConfig $dest -Force
|
|
Write-Ok "Config copied from $userConfig"
|
|
}
|
|
return $dest
|
|
}
|
|
|
|
if (Test-Path $dest) {
|
|
Write-Ok "Using existing config: $dest"
|
|
return $dest
|
|
}
|
|
|
|
# Create a minimal placeholder config
|
|
$placeholder = @"
|
|
# gost configuration file
|
|
# Documentation: https://gost.run/
|
|
#
|
|
# Example: HTTP proxy on port 8080
|
|
# services:
|
|
# - name: http-proxy
|
|
# addr: ":8080"
|
|
# handler:
|
|
# type: http
|
|
# listener:
|
|
# type: tcp
|
|
|
|
log:
|
|
level: info
|
|
format: json
|
|
"@
|
|
Set-Content -Path $dest -Value $placeholder -Encoding UTF8
|
|
Write-Warn "A placeholder config was created at $dest"
|
|
Write-Warn "Edit it before starting the service, or pass -ExtraArgs with -L/-F flags."
|
|
return $dest
|
|
}
|
|
|
|
function Register-GostService([string]$exePath, [string]$cfgPath, [string]$extraArgs) {
|
|
$binPath = "`"$exePath`" -C `"$cfgPath`""
|
|
if ($extraArgs -ne "") { $binPath += " $extraArgs" }
|
|
|
|
$existing = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
|
|
if ($existing) {
|
|
Write-Step "Service '$ServiceName' already exists — updating..."
|
|
if ($existing.Status -eq "Running") {
|
|
Write-Step "Stopping existing service..."
|
|
Stop-Service -Name $ServiceName -Force
|
|
$existing.WaitForStatus("Stopped", [TimeSpan]::FromSeconds(30))
|
|
}
|
|
sc.exe config $ServiceName binPath= $binPath | Out-Null
|
|
$startValue = switch ($StartupType) {
|
|
"Automatic" { "auto" }
|
|
"Manual" { "demand" }
|
|
"Disabled" { "disabled" }
|
|
}
|
|
sc.exe config $ServiceName start= $startValue | Out-Null
|
|
Write-Ok "Service updated."
|
|
} else {
|
|
Write-Step "Registering service '$ServiceName'..."
|
|
$startValue = switch ($StartupType) {
|
|
"Automatic" { "auto" }
|
|
"Manual" { "demand" }
|
|
"Disabled" { "disabled" }
|
|
}
|
|
sc.exe create $ServiceName `
|
|
binPath= $binPath `
|
|
DisplayName= $DisplayName `
|
|
start= $startValue | Out-Null
|
|
|
|
# Restart on failure: 5 s / 10 s / 30 s, reset counter after 1 day
|
|
sc.exe failure $ServiceName reset= 86400 actions= restart/5000/restart/10000/restart/30000 | Out-Null
|
|
Write-Ok "Service registered."
|
|
}
|
|
|
|
sc.exe description $ServiceName "GOST (GO Simple Tunnel) - secure tunnel service" | Out-Null
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Main
|
|
# ---------------------------------------------------------------------------
|
|
|
|
Write-Host ""
|
|
Write-Host " gost Windows Service Installer (build from source)" -ForegroundColor White
|
|
Write-Host " ===================================================" -ForegroundColor White
|
|
Write-Host " Repo : $RepoRoot"
|
|
Write-Host " Install dir: $InstallDir"
|
|
Write-Host " Service : $ServiceName ($StartupType)"
|
|
Write-Host ""
|
|
|
|
# 1. Build binary from source
|
|
$exePath = Build-Binary $InstallDir
|
|
|
|
# 2. Ensure config exists
|
|
$cfgPath = Ensure-Config $InstallDir $ConfigFile
|
|
|
|
# 3. Register Windows service
|
|
Register-GostService $exePath $cfgPath $ExtraArgs
|
|
|
|
# 4. Optionally start
|
|
if ($Start) {
|
|
Write-Step "Starting service '$ServiceName'..."
|
|
Start-Service -Name $ServiceName
|
|
$svc = Get-Service -Name $ServiceName
|
|
$svc.WaitForStatus("Running", [TimeSpan]::FromSeconds(15))
|
|
Write-Ok "Service is running."
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host " Done!" -ForegroundColor Green
|
|
Write-Host ""
|
|
Write-Host " Useful commands:" -ForegroundColor White
|
|
Write-Host " Start : Start-Service $ServiceName"
|
|
Write-Host " Stop : Stop-Service $ServiceName"
|
|
Write-Host " Status : Get-Service $ServiceName"
|
|
Write-Host " Logs : Get-EventLog -LogName Application -Source $ServiceName -Newest 20"
|
|
Write-Host " Uninstall: sc.exe delete $ServiceName"
|
|
Write-Host ""
|