Files
soroush.asadi 52be5be93f feat(node-agent): production ops kit — Windows service + WireGuard mesh
config:
- LoadEnvFile(): reads agent.env beside the exe (or $AGENT_ENV_FILE) before env,
  so the sc.exe service needs no per-service environment plumbing; real env wins

deploy/ (new):
- build-windows.ps1     cross-compile → dist\ + stage the deploy kit
- agent.env.example     fully documented config template
- install-service.ps1   register as auto-start Windows service (native sc.exe),
                        crash-restart 3×/5s, no NSSM dependency
- uninstall-service.ps1 stop + remove
- wireguard-node.conf.template + setup-wireguard.ps1  node dials out only, no
                        public IP / inbound rules; tunnel installed as boot service
- README.md             full control-plane + node walkthrough, ops table, troubleshooting

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 12:20:48 +03:30

89 lines
3.8 KiB
PowerShell

<#
.SYNOPSIS
Install WireGuard and bring up the FlatRender mesh tunnel as a persistent service.
.DESCRIPTION
- Verifies WireGuard is installed (downloads the MSI if missing and -Download is set).
- Installs the given .conf as a permanent WireGuard tunnel service (survives reboot).
- The tunnel auto-connects on boot, BEFORE the node-agent service starts, so the
agent can always reach the gateway over 10.66.0.0/24.
Run ELEVATED (Administrator).
.PARAMETER ConfigPath
Path to the filled-in WireGuard config (from wireguard-node.conf.template).
Default: wg-flatrender.conf beside this script.
.PARAMETER Download
If set and WireGuard is not installed, download + silently install the MSI.
.EXAMPLE
.\setup-wireguard.ps1 -ConfigPath .\wg-flatrender.conf
#>
param(
[string]$ConfigPath = (Join-Path $PSScriptRoot "wg-flatrender.conf"),
[switch]$Download
)
$ErrorActionPreference = "Stop"
$principal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Error "This script must be run as Administrator."
exit 1
}
# ── Ensure WireGuard is installed ─────────────────────────────────────────────
$wg = "C:\Program Files\WireGuard\wireguard.exe"
if (-not (Test-Path $wg)) {
if ($Download) {
Write-Host "WireGuard not found — downloading installer..."
$msi = Join-Path $env:TEMP "wireguard.msi"
Invoke-WebRequest -Uri "https://download.wireguard.com/windows-client/wireguard-installer.exe" -OutFile $msi
Write-Host "Installing WireGuard silently..."
Start-Process -FilePath $msi -ArgumentList "/S" -Wait
} else {
Write-Error "WireGuard is not installed. Install it from https://www.wireguard.com/install/ or re-run with -Download."
exit 1
}
}
# ── Validate config ───────────────────────────────────────────────────────────
if (-not (Test-Path $ConfigPath)) {
Write-Error "Config not found: $ConfigPath`nCopy wireguard-node.conf.template, fill the placeholders, save as wg-flatrender.conf."
exit 1
}
$ConfigPath = (Resolve-Path $ConfigPath).Path
if ((Get-Content $ConfigPath -Raw) -match '<[A-Z_]+>') {
Write-Error "Config still contains <PLACEHOLDERS>. Fill in all four values before installing."
exit 1
}
$tunnelName = [System.IO.Path]::GetFileNameWithoutExtension($ConfigPath)
# ── Remove existing tunnel of the same name ───────────────────────────────────
$svcName = "WireGuardTunnel`$$tunnelName"
if (Get-Service -Name $svcName -ErrorAction SilentlyContinue) {
Write-Host "Removing existing tunnel '$tunnelName'..."
& $wg /uninstalltunnelservice $tunnelName | Out-Null
Start-Sleep -Seconds 2
}
# ── Install the tunnel as a service ───────────────────────────────────────────
Write-Host "Installing WireGuard tunnel '$tunnelName' as a boot service..."
& $wg /installtunnelservice $ConfigPath
Start-Sleep -Seconds 3
$svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue
if ($svc -and $svc.Status -eq 'Running') {
Write-Host ""
Write-Host "✓ WireGuard tunnel '$tunnelName' is up." -ForegroundColor Green
Write-Host " Verify : & '$wg' show"
Write-Host " Ping CP: ping 10.66.0.1"
Write-Host ""
Write-Host " Next : install the node agent service (install-service.ps1) and point"
Write-Host " ORCHESTRATOR_URL in agent.env at the control plane's mesh IP."
} else {
Write-Warning "Tunnel service did not reach Running state. Check: & '$wg' show"
}