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

83 lines
4.1 KiB
PowerShell

<#
.SYNOPSIS
Install the FlatRender Node Agent as a Windows service (native sc.exe — no NSSM).
.DESCRIPTION
Registers flatrender-node-agent.exe as an auto-start service that survives reboots
and auto-restarts on crash. Configuration is read from `agent.env` placed next to
the exe (see agent.env.example), so no per-service environment plumbing is needed.
Run from an ELEVATED PowerShell prompt (Administrator).
.PARAMETER ExePath
Path to flatrender-node-agent.exe. Defaults to the exe beside this script.
.PARAMETER ServiceName
Windows service name. Default: FlatRenderNodeAgent.
.EXAMPLE
.\install-service.ps1
.\install-service.ps1 -ExePath C:\flatrender\flatrender-node-agent.exe
#>
param(
[string]$ExePath = (Join-Path $PSScriptRoot "flatrender-node-agent.exe"),
[string]$ServiceName = "FlatRenderNodeAgent",
[string]$DisplayName = "FlatRender Node Agent"
)
$ErrorActionPreference = "Stop"
# ── Elevation check ───────────────────────────────────────────────────────────
$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. Right-click PowerShell → Run as administrator."
exit 1
}
# ── Validate exe + config ─────────────────────────────────────────────────────
if (-not (Test-Path $ExePath)) {
Write-Error "Executable not found: $ExePath`nBuild it first (see README) and copy it here."
exit 1
}
$ExePath = (Resolve-Path $ExePath).Path
$envFile = Join-Path (Split-Path $ExePath) "agent.env"
if (-not (Test-Path $envFile)) {
Write-Warning "No agent.env found next to the exe at: $envFile"
Write-Warning "Copy agent.env.example → agent.env and fill in NODE_ID / NODE_HMAC_SECRET before the service will work."
}
# ── Remove any existing instance ──────────────────────────────────────────────
$existing = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($existing) {
Write-Host "Service '$ServiceName' already exists — stopping and removing it first..."
if ($existing.Status -ne 'Stopped') { Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue }
& sc.exe delete $ServiceName | Out-Null
Start-Sleep -Seconds 2
}
# ── Create the service ────────────────────────────────────────────────────────
# binPath must quote the exe path (spaces). start=auto → launches at boot.
Write-Host "Creating service '$ServiceName'..."
& sc.exe create $ServiceName binPath= "`"$ExePath`"" start= auto DisplayName= "$DisplayName" | Out-Null
& sc.exe description $ServiceName "FlatRender render-node agent: claims and renders After Effects jobs." | Out-Null
# ── Crash recovery: restart after 5s, three times, reset window 1 day ─────────
& sc.exe failure $ServiceName reset= 86400 actions= restart/5000/restart/5000/restart/5000 | Out-Null
# ── Start it ──────────────────────────────────────────────────────────────────
Write-Host "Starting service..."
Start-Service -Name $ServiceName
Start-Sleep -Seconds 2
$svc = Get-Service -Name $ServiceName
Write-Host ""
Write-Host "✓ Installed and $($svc.Status)." -ForegroundColor Green
Write-Host " Service : $ServiceName"
Write-Host " Exe : $ExePath"
Write-Host " Config : $envFile"
Write-Host ""
Write-Host " Health : curl http://localhost:7777/health"
Write-Host " Logs : Get-WinEvent -ProviderName 'Service Control Manager' | Select-Object -First 5"
Write-Host " Stop : Stop-Service $ServiceName"
Write-Host " Remove : .\uninstall-service.ps1"