lightman-agent 1.0.4 → 1.0.6

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 (115) hide show
  1. package/agent.config.template.json +30 -30
  2. package/package.json +52 -52
  3. package/public/assets/index-CcBNCz6h.css +1 -1
  4. package/public/assets/index-D9QHMG8k.js +1 -0
  5. package/public/assets/index-H-8HDl46.js +1 -1
  6. package/public/assets/index-YodeiCia.css +1 -0
  7. package/public/assets/index-legacy-DWtNM8y7.js +41 -0
  8. package/public/assets/museum-map-CwVDA2z1.svg +4182 -0
  9. package/public/assets/polyfills-legacy-DyVYWHbW.js +4 -0
  10. package/public/index.html +7 -2
  11. package/public/templates/custom08/elements/back-button.svg +20 -0
  12. package/public/templates/custom08/elements/base-map-background.svg +37 -0
  13. package/public/templates/custom08/elements/base-map.svg +1191 -0
  14. package/public/templates/custom08/elements/gallery-1-2-3-info-panel.svg +236 -0
  15. package/public/templates/custom08/elements/gallery-4-5-6-7-info-panel.svg +266 -0
  16. package/public/templates/custom08/elements/gallery-8-9-info-panel.svg +274 -0
  17. package/public/templates/custom08/elements/gallery-labels/_nav-map-styles.css +554 -0
  18. package/public/templates/custom08/elements/gallery-labels/_styles.css +556 -0
  19. package/public/templates/custom08/elements/gallery-labels/gallery-1.svg +35 -0
  20. package/public/templates/custom08/elements/gallery-labels/gallery-2.svg +34 -0
  21. package/public/templates/custom08/elements/gallery-labels/gallery-3.svg +34 -0
  22. package/public/templates/custom08/elements/gallery-labels/gallery-4.svg +37 -0
  23. package/public/templates/custom08/elements/gallery-labels/gallery-5.svg +34 -0
  24. package/public/templates/custom08/elements/gallery-labels/gallery-6.svg +34 -0
  25. package/public/templates/custom08/elements/gallery-labels/gallery-7.svg +34 -0
  26. package/public/templates/custom08/elements/gallery-labels/gallery-8.svg +37 -0
  27. package/public/templates/custom08/elements/gallery-labels/gallery-9.svg +34 -0
  28. package/public/templates/custom08/elements/hand-hint.png +0 -0
  29. package/public/templates/custom08/elements/idle-screen-bg.svg +5 -0
  30. package/public/templates/custom08/elements/idle-screen-map.svg +627 -0
  31. package/public/templates/custom08/elements/idle-screen-text.svg +350 -0
  32. package/public/templates/custom08/elements/key-map-1.svg +986 -0
  33. package/public/templates/custom08/elements/key-map-2.svg +1018 -0
  34. package/public/templates/custom08/elements/key-map-3.svg +1019 -0
  35. package/public/templates/custom08/elements/key-map-combined.svg +1001 -0
  36. package/public/templates/custom08/elements/map-highlight-marker.svg +11 -0
  37. package/public/templates/custom08/elements/map-pin-marker.svg +15 -0
  38. package/public/templates/custom08/elements/map-teardrop-star-marker.svg +13 -0
  39. package/public/templates/custom08/elements/nav-circle-galleries-1-3.svg +21 -0
  40. package/public/templates/custom08/elements/nav-circle-galleries-4-7.svg +24 -0
  41. package/public/templates/custom08/elements/nav-circle-galleries-8-9.svg +20 -0
  42. package/public/templates/custom08/elements/section1-map.svg +1435 -0
  43. package/public/templates/custom08/elements/section2-map.svg +1724 -0
  44. package/public/templates/custom08/elements/section3-map.svg +1295 -0
  45. package/public/templates/custom08/fonts/CabinetGrotesk-Variable.ttf +0 -0
  46. package/public/templates/custom08/images/highlights/Screenshot_2026-03-05_at_7.23.12_PM.png +0 -0
  47. package/public/templates/custom08/images/highlights/Screenshot_2026-03-05_at_7.23.56_PM.png +0 -0
  48. package/public/templates/custom08/images/highlights/Screenshot_2026-03-05_at_7.24.24_PM.png +0 -0
  49. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.31.58_PM.jpg +0 -0
  50. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.11_PM.jpg +0 -0
  51. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.36_PM.jpg +0 -0
  52. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.48_PM.jpg +0 -0
  53. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.59_PM.jpg +0 -0
  54. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.15_PM.jpg +0 -0
  55. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.27_PM.jpg +0 -0
  56. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.34_PM.jpg +0 -0
  57. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.42_PM.jpg +0 -0
  58. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.50_PM.jpg +0 -0
  59. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.58_PM.jpg +0 -0
  60. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.04_PM.jpg +0 -0
  61. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.11_PM.jpg +0 -0
  62. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.20_PM.jpg +0 -0
  63. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.57_PM.jpg +0 -0
  64. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.35.03_PM.jpg +0 -0
  65. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.35.16_PM.jpg +0 -0
  66. package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.35.23_PM.jpg +0 -0
  67. package/public/templates/custom08/images/highlights/prologue-highlight.png +0 -0
  68. package/scripts/guardian.ps1 +75 -75
  69. package/scripts/install-linux.sh +134 -134
  70. package/scripts/install-rpi.sh +117 -117
  71. package/scripts/install-windows.ps1 +513 -512
  72. package/scripts/launch-kiosk.vbs +101 -101
  73. package/scripts/lightman-agent.logrotate +12 -12
  74. package/scripts/lightman-agent.service +38 -38
  75. package/scripts/lightman-shell.bat +107 -107
  76. package/scripts/reinstall-windows.ps1 +26 -26
  77. package/scripts/restore-desktop.ps1 +32 -32
  78. package/scripts/setup.ps1 +116 -116
  79. package/scripts/setup.sh +115 -115
  80. package/scripts/sync-display.mjs +20 -0
  81. package/scripts/uninstall-linux.sh +50 -50
  82. package/scripts/uninstall-windows.ps1 +54 -54
  83. package/src/commands/display.ts +177 -177
  84. package/src/commands/kiosk.ts +113 -113
  85. package/src/commands/maintenance.ts +106 -106
  86. package/src/commands/network.ts +129 -129
  87. package/src/commands/power.ts +163 -163
  88. package/src/commands/rpi.ts +45 -45
  89. package/src/commands/screenshot.ts +166 -166
  90. package/src/commands/serial.ts +17 -17
  91. package/src/commands/update.ts +124 -124
  92. package/src/index.ts +652 -652
  93. package/src/lib/config.ts +69 -69
  94. package/src/lib/identity.ts +40 -40
  95. package/src/lib/logger.ts +137 -137
  96. package/src/lib/platform.ts +10 -10
  97. package/src/lib/rpi.ts +180 -180
  98. package/src/lib/screens.ts +128 -128
  99. package/src/lib/types.ts +176 -176
  100. package/src/services/commands.ts +107 -107
  101. package/src/services/health.ts +161 -161
  102. package/src/services/kiosk.ts +384 -384
  103. package/src/services/localEvents.ts +60 -60
  104. package/src/services/logForwarder.ts +72 -72
  105. package/src/services/multiScreenKiosk.ts +324 -324
  106. package/src/services/oscBridge.ts +186 -186
  107. package/src/services/powerScheduler.ts +260 -260
  108. package/src/services/provisioning.ts +120 -120
  109. package/src/services/serialBridge.ts +230 -230
  110. package/src/services/serviceLauncher.ts +183 -183
  111. package/src/services/staticServer.ts +226 -226
  112. package/src/services/updater.ts +249 -249
  113. package/src/services/watchdog.ts +310 -310
  114. package/src/services/websocket.ts +152 -152
  115. package/tsconfig.json +28 -28
@@ -1,75 +1,75 @@
1
- # LIGHTMAN Guardian - Service Health Monitor
2
- # Runs every 5 minutes via Task Scheduler.
3
- # Restarts the NSSM service if it's down. Checks Chrome kiosk health.
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
- 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 }
14
- Add-Content -Path $LogFile -Value "[$ts] $msg" -ErrorAction SilentlyContinue
15
- if ((Get-Item $LogFile -ErrorAction SilentlyContinue).Length -gt 1MB) {
16
- $rotated = "$LogFile.old"
17
- if (Test-Path $rotated) { Remove-Item $rotated -Force }
18
- Rename-Item $LogFile $rotated -Force
19
- }
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
- }
29
-
30
- if (-not $svc) {
31
- Write-GuardianLog "CRITICAL: Service not found!"
32
- exit 1
33
- }
34
-
35
- if ($svc.Status -ne 'Running') {
36
- Write-GuardianLog "WARNING: Service is $($svc.Status). Restarting..."
37
-
38
- if ($svc.Status -eq 'Stopped') {
39
- if (Test-Path $NssmExe) {
40
- & $NssmExe start $ServiceName 2>$null
41
- } else {
42
- Start-Service -Name $svc.Name -ErrorAction SilentlyContinue
43
- }
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
- }
1
+ # LIGHTMAN Guardian - Service Health Monitor
2
+ # Runs every 5 minutes via Task Scheduler.
3
+ # Restarts the NSSM service if it's down. Checks Chrome kiosk health.
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
+ 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 }
14
+ Add-Content -Path $LogFile -Value "[$ts] $msg" -ErrorAction SilentlyContinue
15
+ if ((Get-Item $LogFile -ErrorAction SilentlyContinue).Length -gt 1MB) {
16
+ $rotated = "$LogFile.old"
17
+ if (Test-Path $rotated) { Remove-Item $rotated -Force }
18
+ Rename-Item $LogFile $rotated -Force
19
+ }
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
+ }
29
+
30
+ if (-not $svc) {
31
+ Write-GuardianLog "CRITICAL: Service not found!"
32
+ exit 1
33
+ }
34
+
35
+ if ($svc.Status -ne 'Running') {
36
+ Write-GuardianLog "WARNING: Service is $($svc.Status). Restarting..."
37
+
38
+ if ($svc.Status -eq 'Stopped') {
39
+ if (Test-Path $NssmExe) {
40
+ & $NssmExe start $ServiceName 2>$null
41
+ } else {
42
+ Start-Service -Name $svc.Name -ErrorAction SilentlyContinue
43
+ }
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
+ }
@@ -1,134 +1,134 @@
1
- #!/usr/bin/env bash
2
- # LIGHTMAN Agent — Linux Installer
3
- # Run as root:
4
- # sudo bash install-linux.sh --slug f-av01 --server http://192.168.1.100:3401
5
- set -euo pipefail
6
-
7
- INSTALL_DIR="/opt/lightman/agent"
8
- LOG_DIR="/var/log/lightman"
9
- SERVICE_NAME="lightman-agent"
10
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
- AGENT_DIR="$(dirname "$SCRIPT_DIR")"
12
-
13
- # Defaults
14
- SLUG=""
15
- SERVER=""
16
- TIMEZONE="Asia/Kolkata"
17
-
18
- # ── Parse arguments ──
19
- while [[ $# -gt 0 ]]; do
20
- case $1 in
21
- --slug) SLUG="$2"; shift 2 ;;
22
- --server) SERVER="$2"; shift 2 ;;
23
- --timezone) TIMEZONE="$2"; shift 2 ;;
24
- -h|--help)
25
- echo "Usage: sudo bash install-linux.sh --slug f-av01 --server http://192.168.1.100:3401 [--timezone Asia/Kolkata]"
26
- exit 0
27
- ;;
28
- *) echo "Unknown option: $1"; exit 1 ;;
29
- esac
30
- done
31
-
32
- # ── Validate required args ──
33
- if [[ -z "$SLUG" ]]; then
34
- echo "Error: --slug is required"
35
- echo "Usage: sudo bash install-linux.sh --slug f-av01 --server http://192.168.1.100:3401"
36
- exit 1
37
- fi
38
-
39
- if [[ -z "$SERVER" ]]; then
40
- echo "Error: --server is required"
41
- echo "Usage: sudo bash install-linux.sh --slug f-av01 --server http://192.168.1.100:3401"
42
- exit 1
43
- fi
44
-
45
- # ── Pre-checks ──
46
- if [[ $EUID -ne 0 ]]; then
47
- echo "Error: This script must be run as root (use sudo)."
48
- exit 1
49
- fi
50
-
51
- if ! command -v node &> /dev/null; then
52
- echo "Error: Node.js is not installed. Install Node.js 20+ first."
53
- exit 1
54
- fi
55
-
56
- NODE_VERSION=$(node -v | sed 's/v//' | cut -d. -f1)
57
- if [[ "$NODE_VERSION" -lt 20 ]]; then
58
- echo "Error: Node.js 20+ required, found v${NODE_VERSION}."
59
- exit 1
60
- fi
61
-
62
- echo ""
63
- echo "=== LIGHTMAN Agent — Linux Installer ==="
64
- echo " Device slug : $SLUG"
65
- echo " Server URL : $SERVER"
66
- echo ""
67
-
68
- # --- Create user/group ---
69
- if ! id -u lightman &> /dev/null; then
70
- echo "[1/7] Creating lightman user and group..."
71
- groupadd --system lightman
72
- useradd --system --gid lightman --home-dir /opt/lightman --shell /usr/sbin/nologin lightman
73
- else
74
- echo "[1/7] User 'lightman' already exists, skipping."
75
- fi
76
-
77
- # --- Create directories ---
78
- echo "[2/7] Creating directories..."
79
- mkdir -p "$INSTALL_DIR"
80
- mkdir -p "$LOG_DIR"
81
-
82
- # --- Copy agent files ---
83
- echo "[3/7] Copying agent files to ${INSTALL_DIR}..."
84
- cp -r "$AGENT_DIR/dist" "$INSTALL_DIR/"
85
- cp "$AGENT_DIR/package.json" "$INSTALL_DIR/"
86
- cp "$AGENT_DIR/package-lock.json" "$INSTALL_DIR/" 2>/dev/null || true
87
- # Copy template so setup.sh can use it post-install
88
- cp "$AGENT_DIR/agent.config.template.json" "$INSTALL_DIR/"
89
-
90
- # Install production dependencies
91
- echo "[4/7] Installing production dependencies..."
92
- cd "$INSTALL_DIR"
93
- npm ci --omit=dev --ignore-scripts 2>/dev/null || npm install --omit=dev --ignore-scripts
94
-
95
- # --- Configure this device (generates agent.config.json, clears any stale identity) ---
96
- echo "[5/7] Configuring device '$SLUG'..."
97
- bash "$SCRIPT_DIR/setup.sh" \
98
- --slug "$SLUG" \
99
- --server "$SERVER" \
100
- --timezone "$TIMEZONE" \
101
- --dir "$INSTALL_DIR"
102
-
103
- # --- Set permissions ---
104
- echo "[6/7] Setting permissions..."
105
- chown -R lightman:lightman "$INSTALL_DIR"
106
- chown -R lightman:lightman "$LOG_DIR"
107
- chmod 750 "$INSTALL_DIR"
108
- chmod 750 "$LOG_DIR"
109
-
110
- # --- Install systemd service ---
111
- echo "[7/7] Installing systemd service..."
112
- cp "$SCRIPT_DIR/lightman-agent.service" "/etc/systemd/system/${SERVICE_NAME}.service"
113
- systemctl daemon-reload
114
- systemctl enable "$SERVICE_NAME"
115
-
116
- # --- Install logrotate config ---
117
- cp "$SCRIPT_DIR/lightman-agent.logrotate" "/etc/logrotate.d/${SERVICE_NAME}" 2>/dev/null || true
118
-
119
- echo ""
120
- echo "=== Installation Complete ==="
121
- echo ""
122
- echo " Device slug : $SLUG"
123
- echo " Server : $SERVER"
124
- echo " Install dir : ${INSTALL_DIR}"
125
- echo " Log dir : ${LOG_DIR}"
126
- echo " Service : ${SERVICE_NAME}"
127
- echo ""
128
- echo " Start : sudo systemctl start ${SERVICE_NAME}"
129
- echo " Status : sudo systemctl status ${SERVICE_NAME}"
130
- echo " Logs : sudo journalctl -u ${SERVICE_NAME} -f"
131
- echo ""
132
- echo "The agent will now provision with the LIGHTMAN server."
133
- echo "If pairing is needed, a 6-digit code will appear in the logs."
134
- echo ""
1
+ #!/usr/bin/env bash
2
+ # LIGHTMAN Agent — Linux Installer
3
+ # Run as root:
4
+ # sudo bash install-linux.sh --slug f-av01 --server http://192.168.1.100:3401
5
+ set -euo pipefail
6
+
7
+ INSTALL_DIR="/opt/lightman/agent"
8
+ LOG_DIR="/var/log/lightman"
9
+ SERVICE_NAME="lightman-agent"
10
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
+ AGENT_DIR="$(dirname "$SCRIPT_DIR")"
12
+
13
+ # Defaults
14
+ SLUG=""
15
+ SERVER=""
16
+ TIMEZONE="Asia/Kolkata"
17
+
18
+ # ── Parse arguments ──
19
+ while [[ $# -gt 0 ]]; do
20
+ case $1 in
21
+ --slug) SLUG="$2"; shift 2 ;;
22
+ --server) SERVER="$2"; shift 2 ;;
23
+ --timezone) TIMEZONE="$2"; shift 2 ;;
24
+ -h|--help)
25
+ echo "Usage: sudo bash install-linux.sh --slug f-av01 --server http://192.168.1.100:3401 [--timezone Asia/Kolkata]"
26
+ exit 0
27
+ ;;
28
+ *) echo "Unknown option: $1"; exit 1 ;;
29
+ esac
30
+ done
31
+
32
+ # ── Validate required args ──
33
+ if [[ -z "$SLUG" ]]; then
34
+ echo "Error: --slug is required"
35
+ echo "Usage: sudo bash install-linux.sh --slug f-av01 --server http://192.168.1.100:3401"
36
+ exit 1
37
+ fi
38
+
39
+ if [[ -z "$SERVER" ]]; then
40
+ echo "Error: --server is required"
41
+ echo "Usage: sudo bash install-linux.sh --slug f-av01 --server http://192.168.1.100:3401"
42
+ exit 1
43
+ fi
44
+
45
+ # ── Pre-checks ──
46
+ if [[ $EUID -ne 0 ]]; then
47
+ echo "Error: This script must be run as root (use sudo)."
48
+ exit 1
49
+ fi
50
+
51
+ if ! command -v node &> /dev/null; then
52
+ echo "Error: Node.js is not installed. Install Node.js 20+ first."
53
+ exit 1
54
+ fi
55
+
56
+ NODE_VERSION=$(node -v | sed 's/v//' | cut -d. -f1)
57
+ if [[ "$NODE_VERSION" -lt 20 ]]; then
58
+ echo "Error: Node.js 20+ required, found v${NODE_VERSION}."
59
+ exit 1
60
+ fi
61
+
62
+ echo ""
63
+ echo "=== LIGHTMAN Agent — Linux Installer ==="
64
+ echo " Device slug : $SLUG"
65
+ echo " Server URL : $SERVER"
66
+ echo ""
67
+
68
+ # --- Create user/group ---
69
+ if ! id -u lightman &> /dev/null; then
70
+ echo "[1/7] Creating lightman user and group..."
71
+ groupadd --system lightman
72
+ useradd --system --gid lightman --home-dir /opt/lightman --shell /usr/sbin/nologin lightman
73
+ else
74
+ echo "[1/7] User 'lightman' already exists, skipping."
75
+ fi
76
+
77
+ # --- Create directories ---
78
+ echo "[2/7] Creating directories..."
79
+ mkdir -p "$INSTALL_DIR"
80
+ mkdir -p "$LOG_DIR"
81
+
82
+ # --- Copy agent files ---
83
+ echo "[3/7] Copying agent files to ${INSTALL_DIR}..."
84
+ cp -r "$AGENT_DIR/dist" "$INSTALL_DIR/"
85
+ cp "$AGENT_DIR/package.json" "$INSTALL_DIR/"
86
+ cp "$AGENT_DIR/package-lock.json" "$INSTALL_DIR/" 2>/dev/null || true
87
+ # Copy template so setup.sh can use it post-install
88
+ cp "$AGENT_DIR/agent.config.template.json" "$INSTALL_DIR/"
89
+
90
+ # Install production dependencies
91
+ echo "[4/7] Installing production dependencies..."
92
+ cd "$INSTALL_DIR"
93
+ npm ci --omit=dev --ignore-scripts 2>/dev/null || npm install --omit=dev --ignore-scripts
94
+
95
+ # --- Configure this device (generates agent.config.json, clears any stale identity) ---
96
+ echo "[5/7] Configuring device '$SLUG'..."
97
+ bash "$SCRIPT_DIR/setup.sh" \
98
+ --slug "$SLUG" \
99
+ --server "$SERVER" \
100
+ --timezone "$TIMEZONE" \
101
+ --dir "$INSTALL_DIR"
102
+
103
+ # --- Set permissions ---
104
+ echo "[6/7] Setting permissions..."
105
+ chown -R lightman:lightman "$INSTALL_DIR"
106
+ chown -R lightman:lightman "$LOG_DIR"
107
+ chmod 750 "$INSTALL_DIR"
108
+ chmod 750 "$LOG_DIR"
109
+
110
+ # --- Install systemd service ---
111
+ echo "[7/7] Installing systemd service..."
112
+ cp "$SCRIPT_DIR/lightman-agent.service" "/etc/systemd/system/${SERVICE_NAME}.service"
113
+ systemctl daemon-reload
114
+ systemctl enable "$SERVICE_NAME"
115
+
116
+ # --- Install logrotate config ---
117
+ cp "$SCRIPT_DIR/lightman-agent.logrotate" "/etc/logrotate.d/${SERVICE_NAME}" 2>/dev/null || true
118
+
119
+ echo ""
120
+ echo "=== Installation Complete ==="
121
+ echo ""
122
+ echo " Device slug : $SLUG"
123
+ echo " Server : $SERVER"
124
+ echo " Install dir : ${INSTALL_DIR}"
125
+ echo " Log dir : ${LOG_DIR}"
126
+ echo " Service : ${SERVICE_NAME}"
127
+ echo ""
128
+ echo " Start : sudo systemctl start ${SERVICE_NAME}"
129
+ echo " Status : sudo systemctl status ${SERVICE_NAME}"
130
+ echo " Logs : sudo journalctl -u ${SERVICE_NAME} -f"
131
+ echo ""
132
+ echo "The agent will now provision with the LIGHTMAN server."
133
+ echo "If pairing is needed, a 6-digit code will appear in the logs."
134
+ echo ""