lightman-agent 1.0.17 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent.config.json +22 -23
- package/agent.config.template.json +30 -31
- package/bin/cms-agent.js +291 -291
- package/package.json +1 -1
- package/public/assets/index-CcBNCz6h.css +1 -1
- package/public/assets/index-D9QHMG8k.js +1 -1
- package/public/assets/index-H-8HDl46.js +1 -1
- package/public/assets/index-YodeiCia.css +1 -1
- package/public/assets/index-legacy-DWtNM8y7.js +41 -41
- package/public/assets/polyfills-legacy-DyVYWHbW.js +4 -4
- package/scripts/guardian.ps1 +50 -124
- package/scripts/install-windows.ps1 +27 -90
- package/scripts/lightman-agent.logrotate +12 -12
- package/scripts/lightman-agent.service +38 -38
- package/scripts/reinstall-windows.ps1 +26 -26
- package/scripts/restore-desktop.ps1 +32 -32
- package/scripts/setup.ps1 +17 -22
- package/scripts/sync-display.mjs +20 -20
- package/scripts/uninstall-windows.ps1 +54 -54
- package/src/commands/display.ts +177 -177
- package/src/commands/kiosk.ts +113 -113
- package/src/commands/maintenance.ts +106 -106
- package/src/commands/network.ts +129 -129
- package/src/commands/power.ts +163 -163
- package/src/commands/rpi.ts +45 -45
- package/src/commands/screenshot.ts +166 -166
- package/src/commands/serial.ts +17 -17
- package/src/commands/update.ts +124 -124
- package/src/index.ts +173 -90
- package/src/lib/config.ts +2 -3
- package/src/lib/identity.ts +40 -40
- package/src/lib/logger.ts +137 -137
- package/src/lib/platform.ts +10 -10
- package/src/lib/rpi.ts +180 -180
- package/src/lib/screenMap.ts +135 -0
- package/src/lib/screens.ts +128 -128
- package/src/lib/types.ts +176 -177
- package/src/services/commands.ts +107 -107
- package/src/services/health.ts +161 -161
- package/src/services/localEvents.ts +60 -60
- package/src/services/logForwarder.ts +72 -72
- package/src/services/multiScreenKiosk.ts +116 -83
- package/src/services/oscBridge.ts +186 -186
- package/src/services/powerScheduler.ts +260 -260
- package/src/services/provisioning.ts +120 -122
- package/src/services/serialBridge.ts +230 -230
- package/src/services/serviceLauncher.ts +183 -183
- package/src/services/staticServer.ts +226 -226
- package/src/services/updater.ts +249 -249
- package/src/services/watchdog.ts +310 -310
- package/src/services/websocket.ts +152 -152
- package/tsconfig.json +28 -28
package/scripts/guardian.ps1
CHANGED
|
@@ -2,88 +2,30 @@
|
|
|
2
2
|
# Runs every 5 minutes via Task Scheduler.
|
|
3
3
|
# Restarts the NSSM service if it's down. Checks Chrome kiosk health.
|
|
4
4
|
|
|
5
|
-
$LogDir = "C:\ProgramData\Lightman\logs"
|
|
6
|
-
$LogFile = Join-Path $LogDir "guardian.log"
|
|
7
|
-
$ServiceName = "LightmanAgent"
|
|
8
|
-
$NssmExe = "C:\ProgramData\Lightman\nssm\nssm.exe"
|
|
9
|
-
|
|
10
|
-
$
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Force -Path $LogDir | Out-Null }
|
|
5
|
+
$LogDir = "C:\ProgramData\Lightman\logs"
|
|
6
|
+
$LogFile = Join-Path $LogDir "guardian.log"
|
|
7
|
+
$ServiceName = "LightmanAgent"
|
|
8
|
+
$NssmExe = "C:\ProgramData\Lightman\nssm\nssm.exe"
|
|
9
|
+
|
|
10
|
+
function Write-GuardianLog($msg) {
|
|
11
|
+
$ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
12
|
+
try {
|
|
13
|
+
if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Force -Path $LogDir | Out-Null }
|
|
16
14
|
Add-Content -Path $LogFile -Value "[$ts] $msg" -ErrorAction SilentlyContinue
|
|
17
15
|
if ((Get-Item $LogFile -ErrorAction SilentlyContinue).Length -gt 1MB) {
|
|
18
16
|
$rotated = "$LogFile.old"
|
|
19
17
|
if (Test-Path $rotated) { Remove-Item $rotated -Force }
|
|
20
18
|
Rename-Item $LogFile $rotated -Force
|
|
21
19
|
}
|
|
22
|
-
} catch { }
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
32
|
-
})
|
|
33
|
-
} catch {
|
|
34
|
-
@()
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function Stop-LightmanNodeProcesses {
|
|
39
|
-
$procs = Get-LightmanNodeProcesses
|
|
40
|
-
if (-not $procs -or $procs.Count -eq 0) {
|
|
41
|
-
Write-GuardianLog "No LIGHTMAN-owned node.exe process found"
|
|
42
|
-
return
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
foreach ($proc in $procs) {
|
|
46
|
-
try {
|
|
47
|
-
Stop-Process -Id $proc.ProcessId -Force -ErrorAction Stop
|
|
48
|
-
Write-GuardianLog "Stopped LIGHTMAN node.exe PID $($proc.ProcessId)"
|
|
49
|
-
} catch {
|
|
50
|
-
Write-GuardianLog "Failed to stop LIGHTMAN node.exe PID $($proc.ProcessId): $_"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function Get-LightmanShellMode {
|
|
56
|
-
$configPath = Join-Path $InstallDir "agent.config.json"
|
|
57
|
-
try {
|
|
58
|
-
if (-not (Test-Path $configPath)) { return $false }
|
|
59
|
-
$config = Get-Content $configPath -Raw | ConvertFrom-Json
|
|
60
|
-
return [bool]($config.kiosk.shellMode)
|
|
61
|
-
} catch {
|
|
62
|
-
return $false
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function Get-LightmanChromeProcesses {
|
|
67
|
-
try {
|
|
68
|
-
@(Get-CimInstance Win32_Process -Filter "Name = 'chrome.exe'" -ErrorAction SilentlyContinue | Where-Object {
|
|
69
|
-
$_.CommandLine -and (
|
|
70
|
-
$_.CommandLine -like "*$ChromeDataDir*" -or
|
|
71
|
-
$_.CommandLine -like "*chrome-kiosk*"
|
|
72
|
-
)
|
|
73
|
-
})
|
|
74
|
-
} catch {
|
|
75
|
-
@()
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
$shellMode = Get-LightmanShellMode
|
|
81
|
-
|
|
82
|
-
# 1. Check LIGHTMAN service
|
|
83
|
-
$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
84
|
-
if (-not $svc) {
|
|
85
|
-
$svc = Get-Service -DisplayName "LIGHTMAN*" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
86
|
-
}
|
|
20
|
+
} catch { }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
# 1. Check LIGHTMAN service
|
|
25
|
+
$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
26
|
+
if (-not $svc) {
|
|
27
|
+
$svc = Get-Service -DisplayName "LIGHTMAN*" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
28
|
+
}
|
|
87
29
|
|
|
88
30
|
if (-not $svc) {
|
|
89
31
|
Write-GuardianLog "CRITICAL: Service not found!"
|
|
@@ -99,51 +41,35 @@ try {
|
|
|
99
41
|
} else {
|
|
100
42
|
Start-Service -Name $svc.Name -ErrorAction SilentlyContinue
|
|
101
43
|
}
|
|
102
|
-
Start-Sleep -Seconds 5
|
|
103
|
-
$svc.Refresh()
|
|
104
|
-
Write-GuardianLog "After restart: $($svc.Status)"
|
|
105
|
-
}
|
|
106
|
-
elseif ($svc.Status -in @('StartPending', 'StopPending')) {
|
|
107
|
-
Write-GuardianLog "Service
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if ($
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
Write-GuardianLog "LIGHTMAN kiosk Chrome not running, but shell mode is enabled. Shell will relaunch it."
|
|
135
|
-
} else {
|
|
136
|
-
$vbsPath = Join-Path $InstallDir "launch-kiosk.vbs"
|
|
137
|
-
if (Test-Path $vbsPath) {
|
|
138
|
-
Start-Sleep -Seconds 10
|
|
139
|
-
$chromeRecheck = Get-LightmanChromeProcesses
|
|
140
|
-
if (-not $chromeRecheck) {
|
|
141
|
-
Write-GuardianLog "LIGHTMAN Chrome not running. Launching via VBS..."
|
|
142
|
-
Start-Process "wscript.exe" -ArgumentList """$vbsPath""" -WindowStyle Hidden
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
} catch {
|
|
148
|
-
Write-GuardianLog "Guardian error: $_"
|
|
149
|
-
}
|
|
44
|
+
Start-Sleep -Seconds 5
|
|
45
|
+
$svc.Refresh()
|
|
46
|
+
Write-GuardianLog "After restart: $($svc.Status)"
|
|
47
|
+
}
|
|
48
|
+
elseif ($svc.Status -in @('StartPending', 'StopPending')) {
|
|
49
|
+
Write-GuardianLog "Service stuck in $($svc.Status). Force killing node.exe..."
|
|
50
|
+
Get-Process -Name "node" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
|
|
51
|
+
Start-Sleep -Seconds 3
|
|
52
|
+
if (Test-Path $NssmExe) { & $NssmExe start $ServiceName 2>$null }
|
|
53
|
+
else { Start-Service -Name $svc.Name -ErrorAction SilentlyContinue }
|
|
54
|
+
Start-Sleep -Seconds 5
|
|
55
|
+
$svc.Refresh()
|
|
56
|
+
Write-GuardianLog "After force restart: $($svc.Status)"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# 2. Check Chrome kiosk
|
|
61
|
+
$chrome = Get-Process -Name "chrome" -ErrorAction SilentlyContinue
|
|
62
|
+
if (-not $chrome) {
|
|
63
|
+
$vbsPath = "C:\Program Files\Lightman\Agent\launch-kiosk.vbs"
|
|
64
|
+
if (Test-Path $vbsPath) {
|
|
65
|
+
Start-Sleep -Seconds 10
|
|
66
|
+
$chromeRecheck = Get-Process -Name "chrome" -ErrorAction SilentlyContinue
|
|
67
|
+
if (-not $chromeRecheck) {
|
|
68
|
+
Write-GuardianLog "Chrome not running. Launching via VBS..."
|
|
69
|
+
Start-Process "wscript.exe" -ArgumentList """$vbsPath""" -WindowStyle Hidden
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch {
|
|
74
|
+
Write-GuardianLog "Guardian error: $_"
|
|
75
|
+
}
|
|
@@ -9,14 +9,13 @@
|
|
|
9
9
|
# powershell -ExecutionPolicy Bypass -File install-windows.ps1 -Slug "F-AV01" -Server "http://..." -ShellReplace
|
|
10
10
|
#Requires -RunAsAdministrator
|
|
11
11
|
|
|
12
|
-
param(
|
|
13
|
-
[Parameter(Mandatory=$true)] [string]$Slug,
|
|
14
|
-
[Parameter(Mandatory=$true)] [string]$Server,
|
|
15
|
-
[string]$Timezone = "Asia/Kolkata",
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
|
|
19
|
-
)
|
|
12
|
+
param(
|
|
13
|
+
[Parameter(Mandatory=$true)] [string]$Slug,
|
|
14
|
+
[Parameter(Mandatory=$true)] [string]$Server,
|
|
15
|
+
[string]$Timezone = "Asia/Kolkata",
|
|
16
|
+
[string]$Username = "",
|
|
17
|
+
[switch]$ShellReplace = $false
|
|
18
|
+
)
|
|
20
19
|
|
|
21
20
|
$ErrorActionPreference = "Stop"
|
|
22
21
|
|
|
@@ -28,83 +27,21 @@ $NssmExe = "$NssmDir\nssm.exe"
|
|
|
28
27
|
$ServiceName = "LightmanAgent"
|
|
29
28
|
$GuardianTask = "LIGHTMAN Guardian"
|
|
30
29
|
$KioskTask = "LIGHTMAN Kiosk Browser"
|
|
31
|
-
$AgentTask = "LIGHTMAN Agent"
|
|
32
|
-
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
33
|
-
$AgentDir = Split-Path -Parent $ScriptDir
|
|
34
|
-
|
|
35
|
-
if (-not $Username) { $Username = $env:USERNAME }
|
|
36
|
-
|
|
37
|
-
function Get-LightmanNodeProcesses {
|
|
38
|
-
try {
|
|
39
|
-
@(Get-CimInstance Win32_Process -Filter "Name = 'node.exe'" -ErrorAction SilentlyContinue | Where-Object {
|
|
40
|
-
$_.CommandLine -and (
|
|
41
|
-
$_.CommandLine -like "*$InstallDir*" -or
|
|
42
|
-
$_.CommandLine -like "*$AgentDir*" -or
|
|
43
|
-
$_.CommandLine -match 'dist\\index\.js|src\\index\.ts|cms-agent\.js'
|
|
44
|
-
)
|
|
45
|
-
})
|
|
46
|
-
} catch {
|
|
47
|
-
@()
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function Stop-LightmanNodeProcesses {
|
|
52
|
-
$procs = Get-LightmanNodeProcesses
|
|
53
|
-
if (-not $procs -or $procs.Count -eq 0) {
|
|
54
|
-
Write-Host " No LIGHTMAN-owned node.exe processes found" -ForegroundColor DarkGray
|
|
55
|
-
return
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
foreach ($proc in $procs) {
|
|
59
|
-
try {
|
|
60
|
-
Stop-Process -Id $proc.ProcessId -Force -ErrorAction Stop
|
|
61
|
-
Write-Host " Stopped LIGHTMAN node.exe PID $($proc.ProcessId)" -ForegroundColor DarkGray
|
|
62
|
-
} catch {
|
|
63
|
-
Write-Host " Failed to stop LIGHTMAN node.exe PID $($proc.ProcessId): $_" -ForegroundColor Yellow
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function Get-LightmanChromeProcesses {
|
|
69
|
-
try {
|
|
70
|
-
@(Get-CimInstance Win32_Process -Filter "Name = 'chrome.exe'" -ErrorAction SilentlyContinue | Where-Object {
|
|
71
|
-
$_.CommandLine -and (
|
|
72
|
-
$_.CommandLine -like "*$ChromeData*" -or
|
|
73
|
-
$_.CommandLine -like "*chrome-kiosk*"
|
|
74
|
-
)
|
|
75
|
-
})
|
|
76
|
-
} catch {
|
|
77
|
-
@()
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function Stop-LightmanChromeProcesses {
|
|
82
|
-
$procs = Get-LightmanChromeProcesses
|
|
83
|
-
if (-not $procs -or $procs.Count -eq 0) {
|
|
84
|
-
Write-Host " No LIGHTMAN kiosk Chrome processes found" -ForegroundColor DarkGray
|
|
85
|
-
return
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
foreach ($proc in $procs) {
|
|
89
|
-
try {
|
|
90
|
-
Stop-Process -Id $proc.ProcessId -Force -ErrorAction Stop
|
|
91
|
-
Write-Host " Stopped LIGHTMAN Chrome PID $($proc.ProcessId)" -ForegroundColor DarkGray
|
|
92
|
-
} catch {
|
|
93
|
-
Write-Host " Failed to stop LIGHTMAN Chrome PID $($proc.ProcessId): $_" -ForegroundColor Yellow
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
30
|
+
$AgentTask = "LIGHTMAN Agent"
|
|
31
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
32
|
+
$AgentDir = Split-Path -Parent $ScriptDir
|
|
33
|
+
|
|
34
|
+
if (-not $Username) { $Username = $env:USERNAME }
|
|
97
35
|
|
|
98
36
|
Write-Host ""
|
|
99
37
|
Write-Host "=============================================" -ForegroundColor Cyan
|
|
100
38
|
Write-Host " LIGHTMAN Agent - Complete Windows Installer" -ForegroundColor Cyan
|
|
101
39
|
Write-Host "=============================================" -ForegroundColor Cyan
|
|
102
|
-
Write-Host " Device slug : $Slug"
|
|
103
|
-
Write-Host " Server URL : $Server"
|
|
104
|
-
Write-Host " Username : $Username"
|
|
105
|
-
Write-Host " Mode : $(if ($ShellReplace) { 'Shell Replacement' } else { 'Standard' })"
|
|
106
|
-
Write-Host "
|
|
107
|
-
Write-Host ""
|
|
40
|
+
Write-Host " Device slug : $Slug"
|
|
41
|
+
Write-Host " Server URL : $Server"
|
|
42
|
+
Write-Host " Username : $Username"
|
|
43
|
+
Write-Host " Mode : $(if ($ShellReplace) { 'Shell Replacement' } else { 'Standard' })"
|
|
44
|
+
Write-Host ""
|
|
108
45
|
|
|
109
46
|
# ============================================================
|
|
110
47
|
# PHASE 0: NUKE EVERYTHING FROM PREVIOUS INSTALLS
|
|
@@ -131,11 +68,11 @@ foreach ($tn in @($AgentTask, $KioskTask, $GuardianTask)) {
|
|
|
131
68
|
if ($t) { Stop-ScheduledTask -TaskName $tn -ErrorAction SilentlyContinue; Unregister-ScheduledTask -TaskName $tn -Confirm:$false -ErrorAction SilentlyContinue }
|
|
132
69
|
}
|
|
133
70
|
|
|
134
|
-
# Kill
|
|
135
|
-
Write-Host "[0c]
|
|
136
|
-
Stop-
|
|
137
|
-
Stop-
|
|
138
|
-
Start-Sleep -Seconds 2
|
|
71
|
+
# Kill processes
|
|
72
|
+
Write-Host "[0c] Killing node.exe and Chrome..." -ForegroundColor Yellow
|
|
73
|
+
Get-Process -Name "node" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
|
|
74
|
+
Get-Process -Name "chrome" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
|
|
75
|
+
Start-Sleep -Seconds 2
|
|
139
76
|
|
|
140
77
|
# Remove old files (keep NSSM and logs)
|
|
141
78
|
Write-Host "[0d] Removing old agent files..." -ForegroundColor Yellow
|
|
@@ -205,11 +142,11 @@ Pop-Location
|
|
|
205
142
|
|
|
206
143
|
# --- 6. Generate config ---
|
|
207
144
|
Write-Host "[6/19] Generating config..." -ForegroundColor Yellow
|
|
208
|
-
if ($ShellReplace) {
|
|
209
|
-
& "$ScriptDir\setup.ps1" -Slug $Slug -Server $Server -Timezone $Timezone -
|
|
210
|
-
} else {
|
|
211
|
-
& "$ScriptDir\setup.ps1" -Slug $Slug -Server $Server -Timezone $Timezone -
|
|
212
|
-
}
|
|
145
|
+
if ($ShellReplace) {
|
|
146
|
+
& "$ScriptDir\setup.ps1" -Slug $Slug -Server $Server -Timezone $Timezone -InstallDir $InstallDir -ShellMode
|
|
147
|
+
} else {
|
|
148
|
+
& "$ScriptDir\setup.ps1" -Slug $Slug -Server $Server -Timezone $Timezone -InstallDir $InstallDir
|
|
149
|
+
}
|
|
213
150
|
|
|
214
151
|
# --- 7. Fix BOM ---
|
|
215
152
|
Write-Host "[7/19] Fixing config encoding..." -ForegroundColor Yellow
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
/var/log/lightman/*.log {
|
|
2
|
-
daily
|
|
3
|
-
rotate 7
|
|
4
|
-
compress
|
|
5
|
-
delaycompress
|
|
6
|
-
missingok
|
|
7
|
-
notifempty
|
|
8
|
-
create 0640 lightman lightman
|
|
9
|
-
postrotate
|
|
10
|
-
systemctl reload lightman-agent > /dev/null 2>&1 || true
|
|
11
|
-
endscript
|
|
12
|
-
}
|
|
1
|
+
/var/log/lightman/*.log {
|
|
2
|
+
daily
|
|
3
|
+
rotate 7
|
|
4
|
+
compress
|
|
5
|
+
delaycompress
|
|
6
|
+
missingok
|
|
7
|
+
notifempty
|
|
8
|
+
create 0640 lightman lightman
|
|
9
|
+
postrotate
|
|
10
|
+
systemctl reload lightman-agent > /dev/null 2>&1 || true
|
|
11
|
+
endscript
|
|
12
|
+
}
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
[Unit]
|
|
2
|
-
Description=LIGHTMAN Agent - Museum Display Management
|
|
3
|
-
Documentation=https://github.com/sagrkv/lightman-app01
|
|
4
|
-
After=network-online.target
|
|
5
|
-
Wants=network-online.target
|
|
6
|
-
|
|
7
|
-
[Service]
|
|
8
|
-
Type=simple
|
|
9
|
-
User=lightman
|
|
10
|
-
Group=lightman
|
|
11
|
-
WorkingDirectory=/opt/lightman/agent
|
|
12
|
-
ExecStart=/usr/bin/node dist/index.js
|
|
13
|
-
Restart=always
|
|
14
|
-
RestartSec=10
|
|
15
|
-
StartLimitIntervalSec=300
|
|
16
|
-
StartLimitBurst=5
|
|
17
|
-
|
|
18
|
-
# Environment
|
|
19
|
-
Environment=NODE_ENV=production
|
|
20
|
-
EnvironmentFile=-/opt/lightman/agent/.env
|
|
21
|
-
|
|
22
|
-
# Security hardening
|
|
23
|
-
ProtectSystem=strict
|
|
24
|
-
ReadWritePaths=/opt/lightman/agent /var/log/lightman /tmp
|
|
25
|
-
PrivateTmp=true
|
|
26
|
-
NoNewPrivileges=true
|
|
27
|
-
ProtectHome=true
|
|
28
|
-
ProtectKernelTunables=true
|
|
29
|
-
ProtectControlGroups=true
|
|
30
|
-
RestrictSUIDSGID=true
|
|
31
|
-
|
|
32
|
-
# Logging
|
|
33
|
-
StandardOutput=journal
|
|
34
|
-
StandardError=journal
|
|
35
|
-
SyslogIdentifier=lightman-agent
|
|
36
|
-
|
|
37
|
-
[Install]
|
|
38
|
-
WantedBy=multi-user.target
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=LIGHTMAN Agent - Museum Display Management
|
|
3
|
+
Documentation=https://github.com/sagrkv/lightman-app01
|
|
4
|
+
After=network-online.target
|
|
5
|
+
Wants=network-online.target
|
|
6
|
+
|
|
7
|
+
[Service]
|
|
8
|
+
Type=simple
|
|
9
|
+
User=lightman
|
|
10
|
+
Group=lightman
|
|
11
|
+
WorkingDirectory=/opt/lightman/agent
|
|
12
|
+
ExecStart=/usr/bin/node dist/index.js
|
|
13
|
+
Restart=always
|
|
14
|
+
RestartSec=10
|
|
15
|
+
StartLimitIntervalSec=300
|
|
16
|
+
StartLimitBurst=5
|
|
17
|
+
|
|
18
|
+
# Environment
|
|
19
|
+
Environment=NODE_ENV=production
|
|
20
|
+
EnvironmentFile=-/opt/lightman/agent/.env
|
|
21
|
+
|
|
22
|
+
# Security hardening
|
|
23
|
+
ProtectSystem=strict
|
|
24
|
+
ReadWritePaths=/opt/lightman/agent /var/log/lightman /tmp
|
|
25
|
+
PrivateTmp=true
|
|
26
|
+
NoNewPrivileges=true
|
|
27
|
+
ProtectHome=true
|
|
28
|
+
ProtectKernelTunables=true
|
|
29
|
+
ProtectControlGroups=true
|
|
30
|
+
RestrictSUIDSGID=true
|
|
31
|
+
|
|
32
|
+
# Logging
|
|
33
|
+
StandardOutput=journal
|
|
34
|
+
StandardError=journal
|
|
35
|
+
SyslogIdentifier=lightman-agent
|
|
36
|
+
|
|
37
|
+
[Install]
|
|
38
|
+
WantedBy=multi-user.target
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
#Requires -RunAsAdministrator
|
|
2
|
-
<#
|
|
3
|
-
.SYNOPSIS
|
|
4
|
-
LIGHTMAN Agent - Reinstall (install-windows.ps1 handles cleanup automatically)
|
|
5
|
-
.EXAMPLE
|
|
6
|
-
powershell -ExecutionPolicy Bypass -File scripts\reinstall-windows.ps1 -Slug "F-AV04" -Server "http://192.168.10.100:3401" -ShellReplace
|
|
7
|
-
#>
|
|
8
|
-
param(
|
|
9
|
-
[Parameter(Mandatory=$true)] [string]$Slug,
|
|
10
|
-
[Parameter(Mandatory=$true)] [string]$Server,
|
|
11
|
-
[switch]$ShellReplace = $false,
|
|
12
|
-
[string]$Timezone = "Asia/Kolkata",
|
|
13
|
-
[switch]$NoReboot = $false
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
17
|
-
|
|
18
|
-
$args = @("-ExecutionPolicy", "Bypass", "-File", "$ScriptDir\install-windows.ps1", "-Slug", $Slug, "-Server", $Server, "-Timezone", $Timezone)
|
|
19
|
-
if ($ShellReplace) { $args += "-ShellReplace" }
|
|
20
|
-
& powershell @args
|
|
21
|
-
|
|
22
|
-
if (-not $NoReboot) {
|
|
23
|
-
Write-Host " Rebooting in 10 seconds... (Ctrl+C to cancel)" -ForegroundColor Yellow
|
|
24
|
-
Start-Sleep -Seconds 10
|
|
25
|
-
Restart-Computer -Force
|
|
26
|
-
}
|
|
1
|
+
#Requires -RunAsAdministrator
|
|
2
|
+
<#
|
|
3
|
+
.SYNOPSIS
|
|
4
|
+
LIGHTMAN Agent - Reinstall (install-windows.ps1 handles cleanup automatically)
|
|
5
|
+
.EXAMPLE
|
|
6
|
+
powershell -ExecutionPolicy Bypass -File scripts\reinstall-windows.ps1 -Slug "F-AV04" -Server "http://192.168.10.100:3401" -ShellReplace
|
|
7
|
+
#>
|
|
8
|
+
param(
|
|
9
|
+
[Parameter(Mandatory=$true)] [string]$Slug,
|
|
10
|
+
[Parameter(Mandatory=$true)] [string]$Server,
|
|
11
|
+
[switch]$ShellReplace = $false,
|
|
12
|
+
[string]$Timezone = "Asia/Kolkata",
|
|
13
|
+
[switch]$NoReboot = $false
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
17
|
+
|
|
18
|
+
$args = @("-ExecutionPolicy", "Bypass", "-File", "$ScriptDir\install-windows.ps1", "-Slug", $Slug, "-Server", $Server, "-Timezone", $Timezone)
|
|
19
|
+
if ($ShellReplace) { $args += "-ShellReplace" }
|
|
20
|
+
& powershell @args
|
|
21
|
+
|
|
22
|
+
if (-not $NoReboot) {
|
|
23
|
+
Write-Host " Rebooting in 10 seconds... (Ctrl+C to cancel)" -ForegroundColor Yellow
|
|
24
|
+
Start-Sleep -Seconds 10
|
|
25
|
+
Restart-Computer -Force
|
|
26
|
+
}
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
# LIGHTMAN - Restore Windows Desktop
|
|
2
|
-
# Reverses shell replacement: sets explorer.exe back as the Windows shell.
|
|
3
|
-
# Run via RDP with admin account, or from Safe Mode:
|
|
4
|
-
# powershell -ExecutionPolicy Bypass -File restore-desktop.ps1
|
|
5
|
-
#Requires -RunAsAdministrator
|
|
6
|
-
|
|
7
|
-
$ErrorActionPreference = "Stop"
|
|
8
|
-
|
|
9
|
-
Write-Host ""
|
|
10
|
-
Write-Host "=== LIGHTMAN - Restore Windows Desktop ===" -ForegroundColor Cyan
|
|
11
|
-
Write-Host ""
|
|
12
|
-
|
|
13
|
-
# Restore HKLM shell
|
|
14
|
-
$HKLMPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
|
15
|
-
$original = (Get-ItemProperty -Path $HKLMPath -Name "Shell_Original" -ErrorAction SilentlyContinue).Shell_Original
|
|
16
|
-
if ($original) {
|
|
17
|
-
Set-ItemProperty -Path $HKLMPath -Name "Shell" -Value $original
|
|
18
|
-
Write-Host " HKLM shell restored to: $original" -ForegroundColor Green
|
|
19
|
-
} else {
|
|
20
|
-
Set-ItemProperty -Path $HKLMPath -Name "Shell" -Value "explorer.exe"
|
|
21
|
-
Write-Host " HKLM shell restored to: explorer.exe" -ForegroundColor Green
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
# Remove HKCU shell override
|
|
25
|
-
$HKCUPath = "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
|
26
|
-
Remove-ItemProperty -Path $HKCUPath -Name "Shell" -ErrorAction SilentlyContinue
|
|
27
|
-
Write-Host " HKCU shell override removed" -ForegroundColor Green
|
|
28
|
-
|
|
29
|
-
Write-Host ""
|
|
30
|
-
Write-Host " Desktop will be restored on next reboot." -ForegroundColor Yellow
|
|
31
|
-
Write-Host " Run: Restart-Computer" -ForegroundColor Yellow
|
|
32
|
-
Write-Host ""
|
|
1
|
+
# LIGHTMAN - Restore Windows Desktop
|
|
2
|
+
# Reverses shell replacement: sets explorer.exe back as the Windows shell.
|
|
3
|
+
# Run via RDP with admin account, or from Safe Mode:
|
|
4
|
+
# powershell -ExecutionPolicy Bypass -File restore-desktop.ps1
|
|
5
|
+
#Requires -RunAsAdministrator
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = "Stop"
|
|
8
|
+
|
|
9
|
+
Write-Host ""
|
|
10
|
+
Write-Host "=== LIGHTMAN - Restore Windows Desktop ===" -ForegroundColor Cyan
|
|
11
|
+
Write-Host ""
|
|
12
|
+
|
|
13
|
+
# Restore HKLM shell
|
|
14
|
+
$HKLMPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
|
15
|
+
$original = (Get-ItemProperty -Path $HKLMPath -Name "Shell_Original" -ErrorAction SilentlyContinue).Shell_Original
|
|
16
|
+
if ($original) {
|
|
17
|
+
Set-ItemProperty -Path $HKLMPath -Name "Shell" -Value $original
|
|
18
|
+
Write-Host " HKLM shell restored to: $original" -ForegroundColor Green
|
|
19
|
+
} else {
|
|
20
|
+
Set-ItemProperty -Path $HKLMPath -Name "Shell" -Value "explorer.exe"
|
|
21
|
+
Write-Host " HKLM shell restored to: explorer.exe" -ForegroundColor Green
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Remove HKCU shell override
|
|
25
|
+
$HKCUPath = "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
|
26
|
+
Remove-ItemProperty -Path $HKCUPath -Name "Shell" -ErrorAction SilentlyContinue
|
|
27
|
+
Write-Host " HKCU shell override removed" -ForegroundColor Green
|
|
28
|
+
|
|
29
|
+
Write-Host ""
|
|
30
|
+
Write-Host " Desktop will be restored on next reboot." -ForegroundColor Yellow
|
|
31
|
+
Write-Host " Run: Restart-Computer" -ForegroundColor Yellow
|
|
32
|
+
Write-Host ""
|
package/scripts/setup.ps1
CHANGED
|
@@ -15,14 +15,11 @@ param(
|
|
|
15
15
|
[Parameter(Mandatory=$true)]
|
|
16
16
|
[string]$Server,
|
|
17
17
|
|
|
18
|
-
[Parameter(Mandatory=$false)]
|
|
19
|
-
[string]$Timezone = "Asia/Kolkata",
|
|
20
|
-
|
|
21
|
-
[Parameter(Mandatory=$false)]
|
|
22
|
-
[
|
|
23
|
-
|
|
24
|
-
[Parameter(Mandatory=$false)]
|
|
25
|
-
[string]$InstallDir = $null,
|
|
18
|
+
[Parameter(Mandatory=$false)]
|
|
19
|
+
[string]$Timezone = "Asia/Kolkata",
|
|
20
|
+
|
|
21
|
+
[Parameter(Mandatory=$false)]
|
|
22
|
+
[string]$InstallDir = $null,
|
|
26
23
|
|
|
27
24
|
[Parameter(Mandatory=$false)]
|
|
28
25
|
[switch]$ShellMode = $false
|
|
@@ -39,12 +36,11 @@ if (-not $InstallDir) {
|
|
|
39
36
|
|
|
40
37
|
Write-Host ""
|
|
41
38
|
Write-Host "=== LIGHTMAN Agent - Device Setup ===" -ForegroundColor Cyan
|
|
42
|
-
Write-Host " Slug: $Slug"
|
|
43
|
-
Write-Host " Server: $Server"
|
|
44
|
-
Write-Host " Install dir: $InstallDir"
|
|
45
|
-
Write-Host " Timezone: $Timezone"
|
|
46
|
-
Write-Host "
|
|
47
|
-
Write-Host ""
|
|
39
|
+
Write-Host " Slug: $Slug"
|
|
40
|
+
Write-Host " Server: $Server"
|
|
41
|
+
Write-Host " Install dir: $InstallDir"
|
|
42
|
+
Write-Host " Timezone: $Timezone"
|
|
43
|
+
Write-Host ""
|
|
48
44
|
|
|
49
45
|
# 1. Clear cached identity (CRITICAL - prevents old device credentials leaking)
|
|
50
46
|
$IdentityFile = Join-Path $InstallDir ".lightman-identity.json"
|
|
@@ -87,14 +83,13 @@ $Template = Get-Content $TemplatePath -Raw
|
|
|
87
83
|
$BrowserEscaped = $BrowserPath -replace '\\', '\\'
|
|
88
84
|
$ChromeDirEscaped = $ChromeDataDir -replace '\\', '\\'
|
|
89
85
|
|
|
90
|
-
$Config = $Template `
|
|
91
|
-
-replace '__SERVER_URL__', $Server `
|
|
92
|
-
-replace '__DEVICE_SLUG__', $Slug `
|
|
93
|
-
-replace '__KIOSK_URL__', $KioskUrl `
|
|
94
|
-
-replace '__BROWSER_PATH__', $BrowserEscaped `
|
|
95
|
-
-replace '__CHROME_DATA_DIR__', $ChromeDirEscaped `
|
|
96
|
-
-replace '
|
|
97
|
-
-replace 'Asia/Kolkata', $Timezone
|
|
86
|
+
$Config = $Template `
|
|
87
|
+
-replace '__SERVER_URL__', $Server `
|
|
88
|
+
-replace '__DEVICE_SLUG__', $Slug `
|
|
89
|
+
-replace '__KIOSK_URL__', $KioskUrl `
|
|
90
|
+
-replace '__BROWSER_PATH__', $BrowserEscaped `
|
|
91
|
+
-replace '__CHROME_DATA_DIR__', $ChromeDirEscaped `
|
|
92
|
+
-replace 'Asia/Kolkata', $Timezone
|
|
98
93
|
|
|
99
94
|
# 6. Inject shellMode into kiosk config if requested
|
|
100
95
|
if ($ShellMode) {
|
package/scripts/sync-display.mjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { cpSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
|
|
4
|
-
const rootDir = resolve(import.meta.dirname, '..');
|
|
5
|
-
const displayDistDir = resolve(rootDir, '..', 'display', 'dist');
|
|
6
|
-
const agentPublicDir = resolve(rootDir, 'public');
|
|
7
|
-
|
|
8
|
-
if (!existsSync(displayDistDir)) {
|
|
9
|
-
console.error(`Display build not found: ${displayDistDir}`);
|
|
10
|
-
process.exit(1);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
mkdirSync(agentPublicDir, { recursive: true });
|
|
14
|
-
|
|
15
|
-
cpSync(displayDistDir, agentPublicDir, {
|
|
16
|
-
recursive: true,
|
|
17
|
-
force: true,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
console.log('Display synced to agent/public/');
|
|
1
|
+
import { cpSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const rootDir = resolve(import.meta.dirname, '..');
|
|
5
|
+
const displayDistDir = resolve(rootDir, '..', 'display', 'dist');
|
|
6
|
+
const agentPublicDir = resolve(rootDir, 'public');
|
|
7
|
+
|
|
8
|
+
if (!existsSync(displayDistDir)) {
|
|
9
|
+
console.error(`Display build not found: ${displayDistDir}`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
mkdirSync(agentPublicDir, { recursive: true });
|
|
14
|
+
|
|
15
|
+
cpSync(displayDistDir, agentPublicDir, {
|
|
16
|
+
recursive: true,
|
|
17
|
+
force: true,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
console.log('Display synced to agent/public/');
|