Open enrollment (OPEN_ENROLLMENT=true in .env): - Agents can register with just --server <url>, no token needed - Machines assigned to OPEN_ENROLLMENT_USER_EMAIL, first admin, or first user - Falls back gracefully if env var not set - agent.py register() now takes optional token; --server alone triggers registration Agent CLI changes: - --server without --enroll triggers open enrollment registration on first run - --enroll still works for token-based or re-enrollment - Error message updated to reflect new syntax NSIS installer changes: - Interactive mode: custom page prompts for server URL + optional token - Silent mode: /SERVER= alone works with open enrollment, /ENROLL= still supported - Cleans up config on uninstall agent.spec: add pyperclip, base64, struct, uuid to hidden imports docker-compose + .env: OPEN_ENROLLMENT and OPEN_ENROLLMENT_USER_EMAIL vars Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
115 lines
2.6 KiB
Python
115 lines
2.6 KiB
Python
# PyInstaller spec for RemoteLink Agent
|
|
# Build: pyinstaller agent.spec
|
|
|
|
import sys
|
|
from PyInstaller.utils.hooks import collect_data_files, collect_submodules
|
|
|
|
block_cipher = None
|
|
|
|
# Collect mss data files (monitor detection)
|
|
mss_datas = collect_data_files('mss')
|
|
|
|
a = Analysis(
|
|
['agent.py'],
|
|
pathex=[],
|
|
binaries=[],
|
|
datas=mss_datas,
|
|
hiddenimports=[
|
|
'mss',
|
|
'mss.windows',
|
|
'mss.darwin',
|
|
'mss.linux',
|
|
'PIL',
|
|
'PIL.Image',
|
|
'PIL.JpegImagePlugin',
|
|
'pynput',
|
|
'pynput.mouse',
|
|
'pynput.keyboard',
|
|
'pynput._util',
|
|
'pynput._util.win32',
|
|
'pynput._util.darwin',
|
|
'pynput._util.xorg',
|
|
'websockets',
|
|
'websockets.legacy',
|
|
'websockets.legacy.client',
|
|
'httpx',
|
|
'httpcore',
|
|
'pyperclip',
|
|
'asyncio',
|
|
'json',
|
|
'logging',
|
|
'platform',
|
|
'subprocess',
|
|
'signal',
|
|
'base64',
|
|
'struct',
|
|
'uuid',
|
|
],
|
|
hookspath=[],
|
|
runtime_hooks=[],
|
|
excludes=['tkinter', 'matplotlib', 'numpy', 'scipy'],
|
|
win_no_prefer_redirects=False,
|
|
win_private_assemblies=False,
|
|
cipher=block_cipher,
|
|
noarchive=False,
|
|
)
|
|
|
|
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
|
|
|
# Single-file portable executable
|
|
exe = EXE(
|
|
pyz,
|
|
a.scripts,
|
|
a.binaries,
|
|
a.zipfiles,
|
|
a.datas,
|
|
[],
|
|
name='remotelink-agent',
|
|
debug=False,
|
|
bootloader_ignore_signals=False,
|
|
strip=False,
|
|
upx=True,
|
|
upx_exclude=[],
|
|
runtime_tmpdir=None,
|
|
console=False, # No console window (set True for debugging)
|
|
disable_windowed_traceback=False,
|
|
target_arch=None,
|
|
codesign_identity=None,
|
|
entitlements_file=None,
|
|
icon='assets/icon.ico' if sys.platform == 'win32' else None,
|
|
version='version_info.txt' if sys.platform == 'win32' else None,
|
|
)
|
|
|
|
# Windows service executable (separate build target)
|
|
svc_a = Analysis(
|
|
['service_win.py'],
|
|
pathex=[],
|
|
binaries=[],
|
|
datas=mss_datas,
|
|
hiddenimports=[
|
|
'win32serviceutil', 'win32service', 'win32event', 'servicemanager',
|
|
'agent',
|
|
] + collect_submodules('win32'),
|
|
hookspath=[],
|
|
runtime_hooks=[],
|
|
excludes=['tkinter'],
|
|
cipher=block_cipher,
|
|
)
|
|
|
|
svc_pyz = PYZ(svc_a.pure, svc_a.zipped_data, cipher=block_cipher)
|
|
|
|
svc_exe = EXE(
|
|
svc_pyz,
|
|
svc_a.scripts,
|
|
svc_a.binaries,
|
|
svc_a.zipfiles,
|
|
svc_a.datas,
|
|
[],
|
|
name='remotelink-agent-service',
|
|
debug=False,
|
|
strip=False,
|
|
upx=True,
|
|
console=True,
|
|
icon='assets/icon.ico' if sys.platform == 'win32' else None,
|
|
)
|