◆CF-LSH/Agent Guide

Agent Installation & Diagnostics

Platform-specific installation, verification, service management, troubleshooting, and diagnostics for the CF-LSH endpoint agent.

⚠ Authorization required
  • Only install on systems you own or are authorized to manage.
  • Each enrollment token is device-specific. Never reuse tokens.
  • Never share credentials or identity files.
Choose your operating systemOne click updates every command on this page

Quick Start

Select your platform for step-by-step installation instructions.

1

Download

powershell
curl.exe -fsSL -o "$env:TEMP\cf-lsh-agent-windows-amd64.exe" "https://sec-nerves.vercel.app/api/agent-downloads/cf-lsh-agent-windows-amd64.exe"
2

Verify

powershell
# Expected hash from manifest
curl.exe -fsSL "https://sec-nerves.vercel.app/api/agent-downloads/manifest.json" -o "$env:TEMP\manifest.json"
Get-Content "$env:TEMP\manifest.json" | ConvertFrom-Json | Select-Object -ExpandProperty 'windows-amd64' | Format-List

# Actual hash
Get-FileHash "$env:TEMP\cf-lsh-agent-windows-amd64.exe" -Algorithm SHA256
3

Install

powershell
& "$env:TEMP\cf-lsh-agent-windows-amd64.exe" install --manager "https://sec-nerves.vercel.app" --token "<token>" --device-id "<id>"
4

Start service

powershell
Start-Service -Name "cf-lsh-agent"
Get-Service -Name "cf-lsh-agent"
5

Verify identity

powershell
& "C:\ProgramData\cf-lsh-agent\cf-lsh-agent.exe" status

Service

The agent runs as a system service. All commands require admin or root privileges. First, discover the real service name — do not assume 'cf-lsh-agent'.

⚠ Always discover first

The service name, executable path, and registration vary by installation method and version. Always discover them before stopping or replacing anything.

Discover the real Windows service:

powershell
Get-CimInstance Win32_Service | Where-Object { $_.Name -match 'cf-lsh' -or $_.DisplayName -match 'CF-LSH' -or $_.PathName -match 'cf-lsh-agent' } | Select-Object Name, DisplayName, State, StartMode, StartName, PathName
ℹ Info
Note the exact Name and PathName. Use these as <verified-service-name> and <verified-executable-path> in all commands.
powershell
# Discover service first
Get-CimInstance Win32_Service | Where-Object { $_.Name -match 'cf-lsh' -or $_.DisplayName -match 'CF-LSH' -or $_.PathName -match 'cf-lsh-agent' } | Select-Object Name, DisplayName, State, StartMode, StartName, PathName

# Then use the discovered name
Get-Service -Name "<verified-service-name>"          # status
Stop-Service -Name "<verified-service-name>"         # stop
Start-Service -Name "<verified-service-name>"        # start
Restart-Service -Name "<verified-service-name>"      # restart
(Get-CimInstance Win32_Service -Filter "Name='<verified-service-name>'").PathName  # registered path

Debug Mode

Run the agent in the foreground to see structured output. This is the primary method for diagnosing startup failures, connection issues, and collector errors.

powershell
Stop-Service -Name "cf-lsh-agent"
& "C:\ProgramData\cf-lsh-agent\cf-lsh-agent.exe" run

Press Ctrl+C to stop, then restart:

powershell
Start-Service -Name "cf-lsh-agent"
Get-Service -Name "cf-lsh-agent"
ℹ Info
Interactive mode does not suppress errors — if a collector command fails, the error appears in the terminal.

Verify Binary

Compare the installed binary SHA-256 against the published manifest. A mismatch means the installed binary differs from the current release.

powershell
# Binary info
Get-Item "C:\ProgramData\cf-lsh-agent\cf-lsh-agent.exe" | Format-List FullName, Length, LastWriteTime

# SHA-256
Get-FileHash "C:\ProgramData\cf-lsh-agent\cf-lsh-agent.exe" -Algorithm SHA256 | Format-List

# Published manifest
curl.exe -fsSL "https://sec-nerves.vercel.app/api/agent-downloads/manifest.json" -o "$env:TEMP\manifest.json"
Get-Content "$env:TEMP\manifest.json" | ConvertFrom-Json | Select-Object -ExpandProperty 'windows-amd64' | Format-List

# Version
& "C:\ProgramData\cf-lsh-agent\cf-lsh-agent.exe" version
⚠ Warning
Stop the service before replacing the binary. Preserve config and identity files.

Safe Binary Update

Updating the agent binary is not the same as re-enrolling the device. Follow this procedure to replace only the executable without losing identity, configuration, or service registration.

✕ Critical: Never re-enrol to update the binary

Re-enrolling a device creates a new installation ID and orphaned device record. Instead, replace only the executable while preserving everything else.

1

Download the new artifact

powershell
curl.exe -fsSL -o "$env:TEMP\cf-lsh-agent-windows-amd64.exe" "https://sec-nerves.vercel.app/api/agent-downloads/cf-lsh-agent-windows-amd64.exe"
2

Verify the artifact SHA-256 against the manifest

powershell
curl.exe -fsSL "https://sec-nerves.vercel.app/api/agent-downloads/manifest.json" -o "$env:TEMP\manifest.json"
Get-Content "$env:TEMP\manifest.json" | ConvertFrom-Json | Select-Object -ExpandProperty 'windows-amd64' | Format-List
Get-FileHash "$env:TEMP\cf-lsh-agent-windows-amd64.exe" -Algorithm SHA256
3

Discover the real service name (do not assume cf-lsh-agent)

powershell
Get-CimInstance Win32_Service | Where-Object { $_.Name -match 'cf-lsh' -or $_.DisplayName -match 'CF-LSH' -or $_.PathName -match 'cf-lsh-agent' } | Select-Object Name, DisplayName, State, StartMode, StartName, PathName
4

Discover the registered executable path

powershell
(Get-CimInstance Win32_Service -Filter "Name='<verified-service-name>'").PathName
5

Stop the service

powershell
Stop-Service -Name '<verified-service-name>' -Force
6

Back up the existing executable with a timestamp

powershell
Copy-Item -Path '<verified-executable-path>' -Destination "<verified-executable-path>.backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
7

Replace only the executable

powershell
Copy-Item -Path "$env:TEMP\cf-lsh-agent-windows-amd64.exe" -Destination '<verified-executable-path>' -Force
8

Preserve all identity and configuration files — do not touch them

text
Do NOT delete, modify, or replace:
- identity.json or identity.yml
- installation ID
- device ID
- permanent credential
- configuration file
- service registration
9

Restart the same service

powershell
Start-Service -Name '<verified-service-name>'
10

Confirm the agent version changed

powershell
& '<verified-executable-path>' --version
11

Confirm heartbeat and telemetry return HTTP 200

powershell
# Run interactively to verify
Stop-Service -Name '<verified-service-name>' -Force
& '<verified-executable-path>' run
12

Confirm processesCollected is greater than zero

text
Check the Processes tab in the dashboard.
Expected: processesCollected > 0, submitResponse status=200

Heartbeat

The agent sends an authenticated heartbeat every 60 seconds. Heartbeats are required for Connected status — enrollment or approval does not establish connectivity.

Expected

  • Accepted → HTTP 200
  • Server updates lastSeenAt
  • Device → Connected
  • Missed → Stale → Disconnected

Troubleshoot

  1. Verify service is running
  2. Run agent interactively
  3. Check manager URL reachability
  4. Check firewall rules
  5. Inspect agent logs

Telemetry

System telemetry (CPU, memory, disk, network, OS) submits automatically after heartbeat. Process telemetry uses a separate collector and is persisted as ProcessSnapshot and DeviceProcess records.

Expected

  • Authenticated → persisted
  • Heartbeat first, telemetry follows
  • Record count increases each cycle
  • Failed fields → Unavailable
  • Healthy = recent report with 200

Metrics Unavailable?

The platform collector failed to query the host. Run interactively to see errors. Compare with host verification commands.

⚠ Warning
Never fabricate missing values. The system does not simulate or default telemetry. Connections telemetry is not yet implemented.

Process Telemetry

Process telemetry is now implemented and runtime-verified on Windows using Toolhelp32 snapshot enumeration. The agent sends ProcessInfoV1, which is persisted as ProcessSnapshot and DeviceProcess records. The UI renders real process names, PIDs, and memory values.

Implementation Status

  • ✅ Windows: implemented and verified
  • ⬜ Linux: not yet implemented
  • ⬜ macOS: not yet implemented
  • Two latest snapshots retained
  • Unsupported fields → Not reported

Healthy Submission

  • processesCollected > 0
  • submitResponse status=200
  • ProcessSnapshot rows exist
  • DeviceProcess rows exist
  • UI receives latest snapshot
1

Check agent version — must be process-enabled (e.g. 898dd04 or later)

powershell
& '<verified-executable-path>' --version
2

Run agent interactively to verify process collection

powershell
Stop-Service -Name '<verified-service-name>' -Force
& '<verified-executable-path>' run

Look for processesCollected=<number> and submitResponse status=200

3

Verify the service is not running an older binary from a different path

powershell
(Get-CimInstance Win32_Service -Filter "Name='<verified-service-name>'").PathName
4

Restart the service after testing

powershell
Start-Service -Name '<verified-service-name>'
✕ Do not
  • Skip agent version verification
  • Assume process collection works without checking processesCollected > 0
  • Fabricate or simulate process data
  • Re-enrol the device to fix process telemetry

Connections Telemetry

Connections telemetry is implemented but requires runtime verification on each platform. The agent collects real TCP and UDP connections using platform-native APIs.

ℹ Implementation status — not yet runtime-verified

The Connections tab currently shows "Waiting for connection telemetry" until the enrolled agent sends its first connection snapshot. This is expected until the Windows service binary is updated and runtime-verified.

Platform Support

  • Windows: collector code added via IP Helper API (GetExtendedTcpTable, GetExtendedUdpTable), requires runtime verification
  • Linux: collector code added via /proc/net parsing, requires runtime verification
  • macOS: collector code added via lsof -i parsing, requires runtime verification

Implementation Details

  • TCP and UDP connections
  • Local/remote address and port
  • Protocol and connection state
  • Owning PID and process name
  • Max 1000 connections per snapshot
  • Latest 2 snapshots retained
  • Tenant-scoped persistence
  • Same snapshot architecture as process telemetry
  • No packet contents
  • No geolocation or risk scoring

HTTP Status Reference

HTTP status codes returned by the CF-LSH agent API endpoints for heartbeat, telemetry, and enrollment.

ErrorMeaningAction
200Request accepted and persisted successfully.No action required.
400Malformed payload, missing required fields, unsupported schema, or validation failure.Run agent interactively to see the exact validation error. Check agent version.
401Missing, invalid, revoked, or incorrectly loaded permanent agent credential.Verify credential file exists and is readable. Re-enrol if credential is revoked.
403Credential rejected for device or organisation, device access revoked, or tenant authorisation failure.Confirm credential belongs to the expected device and organisation.
404Incorrect manager URL, incorrect API route, outdated agent route, or deployment mismatch.Verify manager URL and DNS resolution.
409Stale sequence, replay, duplicate submission, consumed enrollment token, or identity conflict.Check system clock. Do not reuse consumed tokens.
429Submission frequency too high or rate limiting.Reduce submission frequency. Verify system clock.
500Server persistence, migration, schema, database, or unhandled route failure.Inspect server logs. Verify deployment health.
502/503/504Proxy, deployment, upstream, or temporary availability failure.Verify deployment status. Retry after infrastructure stabilises.
✕ Never

Weaken authentication, credential validation, sequence checking, or tenant isolation to make requests pass. Always investigate root cause first.

Host Verification

Compare collected metrics against actual host state.

powershell
# CPU
powershell -NoP -NonI -Command "Get-CimInstance Win32_Processor | Select-Object Name,NumberOfCores,NumberOfLogicalProcessors,LoadPercentage"

# Memory & OS
powershell -NoP -NonI -Command "Get-CimInstance Win32_OperatingSystem | Select-Object Caption,Version,BuildNumber,LastBootUpTime,TotalVisibleMemorySize,FreePhysicalMemory"

# Disk
powershell -NoP -NonI -Command "Get-CimInstance Win32_LogicalDisk -Filter 'DriveType=3' | Select-Object DeviceID,FileSystem,Size,FreeSpace"

# Network
Get-NetAdapter | Select-Object Name,InterfaceDescription,MacAddress,Status
Get-NetIPAddress | Select-Object InterfaceAlias,AddressFamily,IPAddress

# OS version
cmd /c ver
ℹ Info
WMIC is deprecated on modern Windows. Prefer PowerShell CIM. All commands use -NoProfile for service context consistency.

Logs

Agent logs are written to platform-specific paths. If no logs exist, run interactively.

powershell
Get-ChildItem "$env:ProgramData\cf-lsh-agent" -Recurse -File | Select-Object FullName,Length,LastWriteTime
Get-Content "$env:ProgramData\cf-lsh-agent\logs\agent.log" -Tail 50

Never expose identity.json contents.

bash
sudo journalctl -u cf-lsh-agent -n 200 --no-pager
sudo journalctl -u cf-lsh-agent -f
sudo journalctl -u cf-lsh-agent --since "5 minutes ago" --no-pager
bash
sudo log show --last 1h --predicate 'process == "cf-lsh-agent"' --style compact
sudo log stream --predicate 'process == "cf-lsh-agent"' --style compact

Log Sanitisation

Before sharing agent logs or diagnostic output, remove all sensitive values. Sanitized logs should contain only operational values.

Redact before sharing

  • Authorization headers
  • Bearer tokens
  • Enrollment tokens
  • Permanent credentials
  • Cookies
  • API keys
  • Database URLs
  • Installation IDs*
  • Device IDs*
  • Private usernames
  • Internal IP addresses*
  • Email addresses

*Only include if required for the diagnosis.

Safe examples

agentVersion=898dd04processesCollected=155submitResponse status=200heartbeatAccepted=true
ℹ Tip
Replace secrets with [REDACTED] rather than removing the entire line.
powershell
# List files — do not print contents
Get-ChildItem "$env:ProgramData\cf-lsh-agent" -Recurse -File | Select-Object FullName, Length, LastWriteTime

# Check for identity files without exposing their contents
Test-Path "$env:ProgramData\cf-lsh-agent\identity.json"

Never output the contents of identity.json, identity.yml, or any file containing credentials.

bash
ls -la /etc/cf-lsh-agent/
# Do not cat identity files
bash
ls -la "/Library/Application Support/cf-lsh-agent/"
# Do not cat identity files

Error Codes

Codes that may appear in agent logs or API responses.

ErrorMeaningAction
RATE_LIMIT_UNAVAILABLEServer rate-limit infrastructure unavailable.Verify deployment, retry later. Do not reinstall first.
INVALID_CREDENTIALAgent credential rejected.Verify identity and enrollment. Re-enroll if revoked.
INSTALLATION_ID_MISMATCHIdentity belongs to a different installation.Inspect identity path and server mapping.
NONCE_USEDDuplicate nonce — possible replay.Verify system clock. Do not disable replay protection.
TOKEN_EXPIREDEnrollment token expired.Generate a new token from the device page.
DEVICE_NOT_FOUNDDevice ID not registered.Verify ID matches enrollment record.
Telemetry accepted, metrics unavailableTelemetry persisted but collector omitted failed fields.Compare binary hash. Run interactively.
Service runs, no heartbeatAgent running but not sending heartbeats.Verify manager URL, network. Run interactively.

Troubleshooting Decision Flow

Follow this flow to systematically diagnose agent issues. Each step narrows the root cause before you take action.

1. Artifact hash matches?
No → Delete the download, investigate URL/proxy/cache. Never install with a mismatched hash.
Yes → Continue to service check.
2. Service registered?
No → Repair installation or re-register the service.
Yes → Continue to service running check.
3. Service running?
No → Inspect permissions, service logs, and binary path.
Yes → Continue to heartbeat check.
4. Heartbeat returns HTTP 200?
No → Inspect manager URL, credential, clock, and status code. See HTTP Status section.
Yes → Continue to telemetry check.
5. Telemetry returns HTTP 200?
No → Inspect payload validation, credential, and server persistence.
Yes → Continue to process check.
6. processesCollected > 0?
No → Verify agent version, permissions, and collector support.
Yes → Continue to database check.
7. ProcessSnapshot and DeviceProcess rows exist?
No → Inspect backend persistence and migration (admin).
Yes → Continue to UI check.
8. UI displays the latest process snapshot?
No → Inspect device API response, tenant scope, polling/SSE, and frontend mapping.
Yes → Runtime verified.
ℹ Info
Connections telemetry is not yet implemented — the decision flow for connections will be added when the feature is runtime-verified.

Uninstall

Before uninstalling, note the device name and ID. Deleting the identity file requires a new enrollment token.

powershell
# First discover the service name
Get-CimInstance Win32_Service | Where-Object { $_.Name -match 'cf-lsh' -or $_.DisplayName -match 'CF-LSH' -or $_.PathName -match 'cf-lsh-agent' } | Select-Object Name, DisplayName, State, StartMode, StartName, PathName

Stop-Service -Name "<verified-service-name>" -Force
& "<verified-executable-path>" uninstall
bash
# First discover the unit name
systemctl list-unit-files --type=service | grep -i 'cf-lsh'

sudo systemctl stop "<verified-service-name>"
sudo "<verified-executable-path>" uninstall
bash
# First discover the plist
sudo find /Library/LaunchDaemons -maxdepth 1 -iname '*cf-lsh*.plist' -print

sudo launchctl bootout system "<verified-plist-path>"
sudo "<verified-executable-path>" uninstall
⚠ Warning
Preserve identity and config files if reinstalling on the same device.

Security

✕ Never do the following
  • Share credentials, identity files, or enrollment tokens
  • Print or log Authorization headers or identity-file secrets
  • Reuse one device's enrollment link on another device
  • Disable HMAC verification, nonce checks, or replay protection
  • Weaken tenant isolation or bypass authentication
  • Delete identity files without a recovery plan
  • Manually construct unsigned heartbeat or telemetry requests
  • Mark a device healthy without persisted data