lightman-agent 1.0.0

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.
Files changed (54) hide show
  1. package/agent.config.template.json +30 -0
  2. package/bin/cms-agent.js +233 -0
  3. package/nssm/nssm.exe +0 -0
  4. package/package.json +52 -0
  5. package/public/assets/index-CcBNCz6h.css +1 -0
  6. package/public/assets/index-H-8HDl46.js +1 -0
  7. package/public/index.html +19 -0
  8. package/scripts/guardian.ps1 +75 -0
  9. package/scripts/install-linux.sh +134 -0
  10. package/scripts/install-rpi.sh +117 -0
  11. package/scripts/install-windows.ps1 +529 -0
  12. package/scripts/launch-kiosk.vbs +101 -0
  13. package/scripts/lightman-agent.logrotate +12 -0
  14. package/scripts/lightman-agent.service +38 -0
  15. package/scripts/lightman-shell.bat +128 -0
  16. package/scripts/reinstall-windows.ps1 +26 -0
  17. package/scripts/restore-desktop.ps1 +32 -0
  18. package/scripts/setup.ps1 +116 -0
  19. package/scripts/setup.sh +115 -0
  20. package/scripts/uninstall-linux.sh +50 -0
  21. package/scripts/uninstall-windows.ps1 +54 -0
  22. package/src/commands/display.ts +177 -0
  23. package/src/commands/kiosk.ts +113 -0
  24. package/src/commands/maintenance.ts +106 -0
  25. package/src/commands/network.ts +129 -0
  26. package/src/commands/power.ts +163 -0
  27. package/src/commands/rpi.ts +45 -0
  28. package/src/commands/screenshot.ts +166 -0
  29. package/src/commands/serial.ts +17 -0
  30. package/src/commands/update.ts +124 -0
  31. package/src/index.ts +652 -0
  32. package/src/lib/config.ts +69 -0
  33. package/src/lib/identity.ts +40 -0
  34. package/src/lib/logger.ts +137 -0
  35. package/src/lib/platform.ts +10 -0
  36. package/src/lib/rpi.ts +180 -0
  37. package/src/lib/screens.ts +128 -0
  38. package/src/lib/types.ts +176 -0
  39. package/src/services/commands.ts +107 -0
  40. package/src/services/health.ts +161 -0
  41. package/src/services/kiosk.ts +395 -0
  42. package/src/services/localEvents.ts +60 -0
  43. package/src/services/logForwarder.ts +72 -0
  44. package/src/services/multiScreenKiosk.ts +324 -0
  45. package/src/services/oscBridge.ts +186 -0
  46. package/src/services/powerScheduler.ts +260 -0
  47. package/src/services/provisioning.ts +120 -0
  48. package/src/services/serialBridge.ts +230 -0
  49. package/src/services/serviceLauncher.ts +183 -0
  50. package/src/services/staticServer.ts +226 -0
  51. package/src/services/updater.ts +249 -0
  52. package/src/services/watchdog.ts +310 -0
  53. package/src/services/websocket.ts +152 -0
  54. package/tsconfig.json +28 -0
@@ -0,0 +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
@@ -0,0 +1,128 @@
1
+ @echo off
2
+ REM ================================================================
3
+ REM LIGHTMAN Shell - Replaces explorer.exe as the Windows shell
4
+ REM ================================================================
5
+ REM SINGLE SOURCE OF TRUTH: agent.config.json
6
+ REM
7
+ REM Boot flow:
8
+ REM 1. Auto-login (no password)
9
+ REM 2. This script runs INSTEAD of explorer.exe
10
+ REM 3. Reads slug + browser from agent.config.json (THE ONLY SOURCE)
11
+ REM 4. Waits for agent service (port 3403)
12
+ REM 5. Launches Chrome fullscreen
13
+ REM 6. If Chrome crashes, relaunches in 3 seconds (infinite loop)
14
+ REM ================================================================
15
+
16
+ set INSTALL_DIR=C:\Program Files\Lightman\Agent
17
+ set CONFIG_FILE=%INSTALL_DIR%\agent.config.json
18
+ set CHROME_DATA=C:\ProgramData\Lightman\chrome-kiosk
19
+ set LOG_FILE=C:\ProgramData\Lightman\logs\shell.log
20
+
21
+ REM Ensure directories exist
22
+ if not exist "C:\ProgramData\Lightman\logs" mkdir "C:\ProgramData\Lightman\logs"
23
+ if not exist "%CHROME_DATA%" mkdir "%CHROME_DATA%"
24
+
25
+ echo [%date% %time%] ===== LIGHTMAN Shell starting ===== >> "%LOG_FILE%"
26
+
27
+ REM ----------------------------------------------------------------
28
+ REM Read slug and browser from agent.config.json ONLY
29
+ REM No sidecar files, no hardcoded URLs, no confusion.
30
+ REM ----------------------------------------------------------------
31
+ set DEVICE_SLUG=
32
+ set BROWSER=
33
+ set URL=
34
+
35
+ REM Wait for node.exe to be available
36
+ set NODE_WAIT=0
37
+ :wait_for_node
38
+ where node >nul 2>&1
39
+ if %errorlevel%==0 goto node_ready
40
+ set /a NODE_WAIT+=1
41
+ if %NODE_WAIT% geq 30 (
42
+ echo [%date% %time%] ERROR: node.exe not found after 30s >> "%LOG_FILE%"
43
+ goto use_fallbacks
44
+ )
45
+ timeout /t 1 /nobreak >nul
46
+ goto wait_for_node
47
+
48
+ :node_ready
49
+
50
+ REM Read slug from config
51
+ if exist "%CONFIG_FILE%" (
52
+ for /f "delims=" %%a in ('node -e "try{console.log(JSON.parse(require('fs').readFileSync(String.raw`%CONFIG_FILE%`,'utf8')).deviceSlug)}catch(e){console.log('')}" 2^>nul') do set DEVICE_SLUG=%%a
53
+ )
54
+
55
+ REM Read browser from config
56
+ if exist "%CONFIG_FILE%" (
57
+ for /f "delims=" %%a in ('node -e "try{const c=JSON.parse(require('fs').readFileSync(String.raw`%CONFIG_FILE%`,'utf8'));console.log(c.kiosk&&c.kiosk.browserPath||'')}catch(e){console.log('')}" 2^>nul') do set BROWSER=%%a
58
+ )
59
+
60
+ :use_fallbacks
61
+
62
+ REM Build URL from slug (ALWAYS from config, never from sidecar)
63
+ if not "%DEVICE_SLUG%"=="" (
64
+ set URL=http://localhost:3403/display/%DEVICE_SLUG%
65
+ echo [%date% %time%] Slug: %DEVICE_SLUG% >> "%LOG_FILE%"
66
+ ) else (
67
+ set URL=http://localhost:3403/display
68
+ echo [%date% %time%] WARNING: No slug in config! >> "%LOG_FILE%"
69
+ )
70
+
71
+ REM Fallback browser
72
+ if "%BROWSER%"=="" (
73
+ if exist "C:\Program Files\Google\Chrome\Application\chrome.exe" (
74
+ set "BROWSER=C:\Program Files\Google\Chrome\Application\chrome.exe"
75
+ ) else if exist "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" (
76
+ set "BROWSER=C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
77
+ ) else (
78
+ echo [%date% %time%] ERROR: Chrome not found! >> "%LOG_FILE%"
79
+ start explorer.exe
80
+ exit /b 1
81
+ )
82
+ )
83
+
84
+ echo [%date% %time%] Browser: %BROWSER% >> "%LOG_FILE%"
85
+ echo [%date% %time%] URL: %URL% >> "%LOG_FILE%"
86
+
87
+ REM ----------------------------------------------------------------
88
+ REM Wait for agent service (port 3403)
89
+ REM ----------------------------------------------------------------
90
+ echo [%date% %time%] Waiting for port 3403... >> "%LOG_FILE%"
91
+ set WAIT_COUNT=0
92
+ set MAX_WAIT=60
93
+
94
+ :wait_for_agent
95
+ netstat -an | findstr ":3403.*LISTENING" >nul 2>&1
96
+ if %errorlevel%==0 goto agent_ready
97
+ set /a WAIT_COUNT+=1
98
+ if %WAIT_COUNT% geq %MAX_WAIT% (
99
+ echo [%date% %time%] Port 3403 not ready after %MAX_WAIT%s, launching anyway >> "%LOG_FILE%"
100
+ goto agent_ready
101
+ )
102
+ timeout /t 1 /nobreak >nul
103
+ goto wait_for_agent
104
+
105
+ :agent_ready
106
+ echo [%date% %time%] Agent ready >> "%LOG_FILE%"
107
+
108
+ REM ----------------------------------------------------------------
109
+ REM Infinite Chrome loop
110
+ REM ----------------------------------------------------------------
111
+ :loop
112
+ REM Re-read slug from config on every loop iteration
113
+ REM This way if someone changes agent.config.json, the next
114
+ REM Chrome restart picks up the new slug automatically.
115
+ if exist "%CONFIG_FILE%" (
116
+ for /f "delims=" %%a in ('node -e "try{console.log(JSON.parse(require('fs').readFileSync(String.raw`%CONFIG_FILE%`,'utf8')).deviceSlug)}catch(e){console.log('')}" 2^>nul') do (
117
+ if not "%%a"=="" set URL=http://localhost:3403/display/%%a
118
+ )
119
+ )
120
+
121
+ echo [%date% %time%] Launching Chrome: %URL% >> "%LOG_FILE%"
122
+
123
+ start /wait "" "%BROWSER%" --kiosk --noerrdialogs --disable-infobars --disable-session-crashed-bubble --no-first-run --no-default-browser-check --start-fullscreen --disable-translate --disable-extensions --autoplay-policy=no-user-gesture-required --disable-features=TranslateUI --user-data-dir="%CHROME_DATA%" "%URL%"
124
+
125
+ echo [%date% %time%] Chrome exited (code: %errorlevel%). Restarting in 3s... >> "%LOG_FILE%"
126
+ timeout /t 3 /nobreak >nul
127
+
128
+ goto loop
@@ -0,0 +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.1.180: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
+ }
@@ -0,0 +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 ""
@@ -0,0 +1,116 @@
1
+ # LIGHTMAN Agent - Device Setup Script (Windows)
2
+ # Generates agent.config.json for this specific device.
3
+ #
4
+ # Usage (run from agent directory or scripts directory):
5
+ # powershell -ExecutionPolicy Bypass -File setup.ps1 -Slug "f-av01" -Server "http://192.168.1.100:3401"
6
+ # powershell -ExecutionPolicy Bypass -File setup.ps1 -Slug "f-av01" -Server "http://192.168.1.100:3401" -Timezone "Asia/Kolkata"
7
+ #
8
+ # This script MUST be run once on every new device installation.
9
+ # It clears any cached identity so the device provisions fresh.
10
+
11
+ param(
12
+ [Parameter(Mandatory=$true)]
13
+ [string]$Slug,
14
+
15
+ [Parameter(Mandatory=$true)]
16
+ [string]$Server,
17
+
18
+ [Parameter(Mandatory=$false)]
19
+ [string]$Timezone = "Asia/Kolkata",
20
+
21
+ [Parameter(Mandatory=$false)]
22
+ [string]$InstallDir = $null,
23
+
24
+ [Parameter(Mandatory=$false)]
25
+ [switch]$ShellMode = $false
26
+ )
27
+
28
+ $ErrorActionPreference = "Stop"
29
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
30
+ $AgentDir = Split-Path -Parent $ScriptDir
31
+
32
+ # Default install dir: the agent folder itself (for dev) or passed explicitly
33
+ if (-not $InstallDir) {
34
+ $InstallDir = $AgentDir
35
+ }
36
+
37
+ Write-Host ""
38
+ Write-Host "=== LIGHTMAN Agent - Device Setup ===" -ForegroundColor Cyan
39
+ Write-Host " Slug: $Slug"
40
+ Write-Host " Server: $Server"
41
+ Write-Host " Install dir: $InstallDir"
42
+ Write-Host " Timezone: $Timezone"
43
+ Write-Host ""
44
+
45
+ # 1. Clear cached identity (CRITICAL - prevents old device credentials leaking)
46
+ $IdentityFile = Join-Path $InstallDir ".lightman-identity.json"
47
+ if (Test-Path $IdentityFile) {
48
+ Remove-Item $IdentityFile -Force
49
+ Write-Host "[OK] Cleared old identity cache (.lightman-identity.json)" -ForegroundColor Green
50
+ } else {
51
+ Write-Host "[OK] No existing identity cache found (clean install)" -ForegroundColor DarkGray
52
+ }
53
+
54
+ # 2. Kiosk display URL - always localhost since agent runs the static server locally on port 3403
55
+ $KioskUrl = "http://localhost:3403/display/$Slug"
56
+
57
+ # 3. Detect browser path
58
+ $BrowserPath = "C:\Program Files\Google\Chrome\Application\chrome.exe"
59
+ if (-not (Test-Path $BrowserPath)) {
60
+ $BrowserPath = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
61
+ }
62
+ if (-not (Test-Path $BrowserPath)) {
63
+ $BrowserPath = "chromium-browser"
64
+ Write-Host "[WARN] Chrome not found - using 'chromium-browser'" -ForegroundColor Yellow
65
+ }
66
+
67
+ $ChromeDataDir = "C:\ProgramData\Lightman\chrome-kiosk"
68
+
69
+ # 4. Read template
70
+ $TemplatePath = Join-Path $AgentDir "agent.config.template.json"
71
+ if (-not (Test-Path $TemplatePath)) {
72
+ # If running from install dir (post-install), template should have been copied there
73
+ $TemplatePath = Join-Path $InstallDir "agent.config.template.json"
74
+ }
75
+ if (-not (Test-Path $TemplatePath)) {
76
+ Write-Host "[ERROR] Template not found. Expected: $TemplatePath" -ForegroundColor Red
77
+ exit 1
78
+ }
79
+
80
+ $Template = Get-Content $TemplatePath -Raw
81
+
82
+ # 5. Replace placeholders
83
+ $BrowserEscaped = $BrowserPath -replace '\\', '\\'
84
+ $ChromeDirEscaped = $ChromeDataDir -replace '\\', '\\'
85
+
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
93
+
94
+ # 6. Inject shellMode into kiosk config if requested
95
+ if ($ShellMode) {
96
+ # Parse as object, set shellMode, re-serialize (reliable, no regex fragility)
97
+ $configObj = $Config | ConvertFrom-Json
98
+ $configObj.kiosk | Add-Member -NotePropertyName "shellMode" -NotePropertyValue $true -Force
99
+ $Config = $configObj | ConvertTo-Json -Depth 4
100
+ Write-Host "[OK] Shell replacement mode enabled in config" -ForegroundColor Magenta
101
+ }
102
+
103
+ # 7. Write config
104
+ $ConfigPath = Join-Path $InstallDir "agent.config.json"
105
+ # Write as UTF-8 WITHOUT BOM (BOM breaks JSON parsing in Node.js)
106
+ [System.IO.File]::WriteAllText($ConfigPath, $Config, [System.Text.UTF8Encoding]::new($false))
107
+
108
+ Write-Host "[OK] Created agent.config.json" -ForegroundColor Green
109
+ Write-Host ""
110
+ Write-Host " Device slug : $Slug"
111
+ Write-Host " Server : $Server"
112
+ Write-Host " Kiosk URL : $KioskUrl"
113
+ Write-Host ""
114
+ Write-Host "Setup complete. Start the agent - it will provision automatically." -ForegroundColor Cyan
115
+ Write-Host "(If IP matches, provisioning is instant. Otherwise enter pairing code shown in admin.)" -ForegroundColor DarkGray
116
+ Write-Host ""
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env bash
2
+ # LIGHTMAN Agent — Device Setup Script (Linux / Raspberry Pi)
3
+ # Generates agent.config.json for this specific device.
4
+ #
5
+ # Usage:
6
+ # sudo bash setup.sh --slug f-av01 --server http://192.168.1.100:3401
7
+ # sudo bash setup.sh --slug f-av01 --server http://192.168.1.100:3401 --timezone Asia/Kolkata --dir /opt/lightman/agent
8
+ #
9
+ # This script MUST be run once on every new device installation.
10
+ # It clears any cached identity so the device provisions fresh.
11
+
12
+ set -euo pipefail
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ AGENT_DIR="$(dirname "$SCRIPT_DIR")"
16
+
17
+ # Defaults
18
+ SLUG=""
19
+ SERVER=""
20
+ TIMEZONE="Asia/Kolkata"
21
+ INSTALL_DIR="/opt/lightman/agent"
22
+
23
+ # ── Parse arguments ──
24
+ while [[ $# -gt 0 ]]; do
25
+ case $1 in
26
+ --slug) SLUG="$2"; shift 2 ;;
27
+ --server) SERVER="$2"; shift 2 ;;
28
+ --timezone) TIMEZONE="$2"; shift 2 ;;
29
+ --dir) INSTALL_DIR="$2"; shift 2 ;;
30
+ -h|--help)
31
+ echo "Usage: bash setup.sh --slug SLUG --server http://SERVER:3401 [--timezone TZ] [--dir /path]"
32
+ exit 0
33
+ ;;
34
+ *) echo "Unknown option: $1"; exit 1 ;;
35
+ esac
36
+ done
37
+
38
+ if [[ -z "$SLUG" ]]; then
39
+ echo "Error: --slug is required"
40
+ echo "Usage: bash setup.sh --slug f-av01 --server http://192.168.1.100:3401"
41
+ exit 1
42
+ fi
43
+
44
+ if [[ -z "$SERVER" ]]; then
45
+ echo "Error: --server is required"
46
+ echo "Usage: bash setup.sh --slug f-av01 --server http://192.168.1.100:3401"
47
+ exit 1
48
+ fi
49
+
50
+ echo ""
51
+ echo "=== LIGHTMAN Agent — Device Setup ==="
52
+ echo " Slug: $SLUG"
53
+ echo " Server: $SERVER"
54
+ echo " Install dir: $INSTALL_DIR"
55
+ echo " Timezone: $TIMEZONE"
56
+ echo ""
57
+
58
+ # ── 1. Clear cached identity (CRITICAL — prevents old device credentials leaking) ──
59
+ IDENTITY_FILE="$INSTALL_DIR/.lightman-identity.json"
60
+ if [[ -f "$IDENTITY_FILE" ]]; then
61
+ rm -f "$IDENTITY_FILE"
62
+ echo "[OK] Cleared old identity cache (.lightman-identity.json)"
63
+ else
64
+ echo "[OK] No existing identity cache found (clean install)"
65
+ fi
66
+
67
+ # ── 2. Derive kiosk display URL from server URL ──
68
+ # Replace port with 3403 (display server)
69
+ KIOSK_BASE="$(echo "$SERVER" | sed 's/:[0-9]*$//')"
70
+ KIOSK_URL="${KIOSK_BASE}:3403/display/${SLUG}"
71
+
72
+ # ── 3. Detect browser ──
73
+ BROWSER_PATH="chromium-browser"
74
+ if command -v chromium &>/dev/null; then
75
+ BROWSER_PATH="chromium"
76
+ elif command -v chromium-browser &>/dev/null; then
77
+ BROWSER_PATH="chromium-browser"
78
+ elif command -v google-chrome &>/dev/null; then
79
+ BROWSER_PATH="google-chrome"
80
+ fi
81
+ CHROME_DATA_DIR="/opt/lightman/chrome-kiosk"
82
+
83
+ # ── 4. Find template ──
84
+ TEMPLATE="$AGENT_DIR/agent.config.template.json"
85
+ if [[ ! -f "$TEMPLATE" ]]; then
86
+ # Post-install: template may be in install dir
87
+ TEMPLATE="$INSTALL_DIR/agent.config.template.json"
88
+ fi
89
+ if [[ ! -f "$TEMPLATE" ]]; then
90
+ echo "[ERROR] Template not found at $TEMPLATE"
91
+ exit 1
92
+ fi
93
+
94
+ # ── 5. Create install dir if needed ──
95
+ mkdir -p "$INSTALL_DIR"
96
+
97
+ # ── 6. Replace placeholders and write config ──
98
+ sed \
99
+ -e "s|__SERVER_URL__|${SERVER}|g" \
100
+ -e "s|__DEVICE_SLUG__|${SLUG}|g" \
101
+ -e "s|__KIOSK_URL__|${KIOSK_URL}|g" \
102
+ -e "s|__BROWSER_PATH__|${BROWSER_PATH}|g" \
103
+ -e "s|__CHROME_DATA_DIR__|${CHROME_DATA_DIR}|g" \
104
+ -e "s|Asia/Kolkata|${TIMEZONE}|g" \
105
+ "$TEMPLATE" > "$INSTALL_DIR/agent.config.json"
106
+
107
+ echo "[OK] Created agent.config.json"
108
+ echo ""
109
+ echo " Device slug : $SLUG"
110
+ echo " Server : $SERVER"
111
+ echo " Kiosk URL : $KIOSK_URL"
112
+ echo ""
113
+ echo "Setup complete. Start the agent — it will provision automatically."
114
+ echo "(If IP matches, provisioning is instant. Otherwise enter pairing code shown in admin.)"
115
+ echo ""
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+ # LIGHTMAN Agent — Linux Uninstaller
3
+ # Run as root: sudo bash uninstall-linux.sh
4
+ set -euo pipefail
5
+
6
+ INSTALL_DIR="/opt/lightman/agent"
7
+ LOG_DIR="/var/log/lightman"
8
+ SERVICE_NAME="lightman-agent"
9
+
10
+ if [[ $EUID -ne 0 ]]; then
11
+ echo "Error: This script must be run as root (use sudo)."
12
+ exit 1
13
+ fi
14
+
15
+ echo "=== LIGHTMAN Agent — Linux Uninstaller ==="
16
+ echo ""
17
+
18
+ # --- Stop and disable service ---
19
+ echo "[1/5] Stopping service..."
20
+ systemctl stop "$SERVICE_NAME" 2>/dev/null || true
21
+ systemctl disable "$SERVICE_NAME" 2>/dev/null || true
22
+
23
+ # --- Remove systemd unit ---
24
+ echo "[2/5] Removing systemd unit..."
25
+ rm -f "/etc/systemd/system/${SERVICE_NAME}.service"
26
+ systemctl daemon-reload
27
+
28
+ # --- Remove logrotate config ---
29
+ echo "[3/5] Removing logrotate config..."
30
+ rm -f "/etc/logrotate.d/${SERVICE_NAME}"
31
+
32
+ # --- Remove installation directory ---
33
+ echo "[4/5] Removing ${INSTALL_DIR}..."
34
+ rm -rf "$INSTALL_DIR"
35
+
36
+ # --- Remove log directory ---
37
+ echo "[5/5] Removing ${LOG_DIR}..."
38
+ rm -rf "$LOG_DIR"
39
+
40
+ # --- Remove user/group (optional) ---
41
+ read -rp "Remove 'lightman' user and group? [y/N]: " REMOVE_USER
42
+ if [[ "$REMOVE_USER" =~ ^[Yy]$ ]]; then
43
+ userdel lightman 2>/dev/null || true
44
+ groupdel lightman 2>/dev/null || true
45
+ echo "User and group removed."
46
+ fi
47
+
48
+ echo ""
49
+ echo "=== Uninstallation Complete ==="
50
+ echo ""
@@ -0,0 +1,54 @@
1
+ # LIGHTMAN Agent - Windows Uninstaller
2
+ # Removes everything: service, tasks, processes, files, shell.
3
+ #Requires -RunAsAdministrator
4
+
5
+ $ErrorActionPreference = "Continue"
6
+ $NssmExe = "C:\ProgramData\Lightman\nssm\nssm.exe"
7
+ $ServiceName = "LightmanAgent"
8
+
9
+ Write-Host ""
10
+ Write-Host "=== LIGHTMAN Agent - Uninstaller ===" -ForegroundColor Cyan
11
+
12
+ # 1. Service
13
+ Write-Host "[1/6] Removing service..." -ForegroundColor Yellow
14
+ if (Test-Path $NssmExe) { & $NssmExe stop $ServiceName 2>$null; & $NssmExe remove $ServiceName confirm 2>$null }
15
+ foreach ($sn in @($ServiceName,"lightmanagent.exe")) { sc.exe stop $sn 2>$null; sc.exe delete $sn 2>$null }
16
+ $s = Get-Service -DisplayName "LIGHTMAN*" -ErrorAction SilentlyContinue
17
+ if ($s) { Stop-Service $s.Name -Force -ErrorAction SilentlyContinue; sc.exe delete $s.Name 2>$null }
18
+
19
+ # 2. Tasks
20
+ Write-Host "[2/6] Removing tasks..." -ForegroundColor Yellow
21
+ foreach ($tn in @("LIGHTMAN Agent","LIGHTMAN Kiosk Browser","LIGHTMAN Guardian")) {
22
+ $t = Get-ScheduledTask -TaskName $tn -ErrorAction SilentlyContinue
23
+ if ($t) { Stop-ScheduledTask -TaskName $tn -ErrorAction SilentlyContinue; Unregister-ScheduledTask -TaskName $tn -Confirm:$false -ErrorAction SilentlyContinue }
24
+ }
25
+
26
+ # 3. Processes
27
+ Write-Host "[3/6] Killing processes..." -ForegroundColor Yellow
28
+ Get-Process -Name "node" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
29
+ Get-Process -Name "chrome" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
30
+
31
+ # 4. Firewall
32
+ Write-Host "[4/6] Removing firewall rule..." -ForegroundColor Yellow
33
+ Remove-NetFirewallRule -DisplayName "LIGHTMAN Agent WebSocket" -ErrorAction SilentlyContinue
34
+
35
+ # 5. Shell
36
+ Write-Host "[5/6] Restoring shell..." -ForegroundColor Yellow
37
+ $HKLMPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
38
+ $shell = (Get-ItemProperty -Path $HKLMPath -Name "Shell" -ErrorAction SilentlyContinue).Shell
39
+ if ($shell -and $shell -like "*lightman*") {
40
+ $orig = (Get-ItemProperty -Path $HKLMPath -Name "Shell_Original" -ErrorAction SilentlyContinue).Shell_Original
41
+ Set-ItemProperty -Path $HKLMPath -Name "Shell" -Value $(if ($orig) { $orig } else { "explorer.exe" })
42
+ Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name "Shell" -ErrorAction SilentlyContinue
43
+ Write-Host " Shell restored"
44
+ }
45
+
46
+ # 6. Files
47
+ Write-Host "[6/6] Removing files..." -ForegroundColor Yellow
48
+ Remove-Item "C:\Program Files\Lightman" -Recurse -Force -ErrorAction SilentlyContinue
49
+ $choice = Read-Host "Remove all data (logs, chrome cache, nssm)? [y/N]"
50
+ if ($choice -eq 'y') { Remove-Item "C:\ProgramData\Lightman" -Recurse -Force -ErrorAction SilentlyContinue }
51
+
52
+ Write-Host ""
53
+ Write-Host "=== Done. Reboot: Restart-Computer ===" -ForegroundColor Green
54
+ Write-Host ""