Skip to content

Deployment

Deploying Talon

Per-platform, exhaustively — this is where trials die.

Every path below includes silent-install flags, a verification command, uninstall, and log locations. If a path you need is missing, that is a documentation bug and we want to hear about it.

Windows

MSI with a transform

cmd
msiexec /i talon-1.8.2-x64.msi TRANSFORMS=site.mst ^
  ENROLL_TOKEN=<token> DEVICE_GROUP="Standard Laptops" ^
  /qn /norestart /l*v C:\Windows\Temp\talon-install.log
PropertyPurposeRequired
ENROLL_TOKENSingle-use enrollment token from ManningYes
DEVICE_GROUPInitial Cadge group. Determines which Creance policy applies.No
TENANTOnly needed for multi-tenant MSP deploymentsNo
PROXYExplicit egress proxy, e.g. http://proxy:3128No

Intune / Autopilot

  1. 01Wrap the MSI with IntuneWinAppUtil. Install command as above; uninstall command msiexec /x {PRODUCT-GUID} /qn.
  2. 02Detection rule: file %ProgramFiles%\\Kestrel\\talon.exe, version greater than or equal to 1.8.2.
  3. 03Assign to a device group, not a user group. Talon is a machine-scoped service.
  4. 04Set Device restart behaviour to No specific action. Talon never requires a reboot to install.

GPO

Computer Configuration → Policies → Software Settings → Software Installation. Assign, do not publish. Place the MSI on a UNC path readable by Domain Computers, and pass the token via a transform rather than a startup script — a token in a script is a token in SYSVOL.

RMM script deployment

ConnectWise Automate / NinjaOne / Kaseya — PowerShell
$token = "<token>"
$url   = "https://dl.kestrel.io/talon/1.8.2/talon-1.8.2-x64.msi"
$msi   = "$env:TEMP\talon.msi"

Invoke-WebRequest -Uri $url -OutFile $msi -UseBasicParsing

# Verify the Authenticode signature before installing. Do this even though
# you trust the URL — especially in an RMM, where the script is the
# highest-value target on the machine.
$sig = Get-AuthenticodeSignature $msi
if ($sig.Status -ne 'Valid' -or
    $sig.SignerCertificate.Subject -notlike '*Kestrel Systems*') {
  throw "Signature check failed: $($sig.Status)"
}

Start-Process msiexec -ArgumentList @(
  "/i", "`"$msi`"", "ENROLL_TOKEN=$token", "/qn", "/norestart"
) -Wait -NoNewWindow

& "$env:ProgramFiles\Kestrel\talon.exe" status

winget

winget install Kestrel.Talon --silent \
  --override "ENROLL_TOKEN=<token> /qn"

Verify, uninstall, logs

# verify
& "$env:ProgramFiles\Kestrel\talon.exe" status
Get-Service TalonAgent

# uninstall
msiexec /x {A7F2C104-9E31-4B8D-95CE-0D2B7A1F6E44} /qn

# logs
%ProgramData%\Kestrel\logs\talon.log
%ProgramData%\Kestrel\logs\actions\

macOS

The PKG is signed with a Developer ID and notarised. Verify before deploying at scale:

spctl -a -vvv -t install Talon-1.8.2.pkg
pkgutil --check-signature Talon-1.8.2.pkg
READ THIS
Deploy the TCC/PPPC profile before the package. An unapproved consent prompt appearing on 500 Macs at once is a support catastrophe, and there is no way to suppress it after the fact.

The PPPC profile

Copy-paste this payload into Jamf (Configuration Profiles → Privacy Preferences Policy Control), Kandji or Mosyle. The designated requirement is fixed; do not retype it.

PPPC payload — XML
<key>Services</key>
<dict>
  <key>SystemPolicyAllFiles</key>
  <array>
    <dict>
      <key>Identifier</key>
      <string>io.kestrel.talon</string>
      <key>IdentifierType</key>
      <string>bundleID</string>
      <key>CodeRequirement</key>
      <string>identifier "io.kestrel.talon" and anchor apple generic
        and certificate leaf[subject.OU] = "K3STR3LSYS"</string>
      <key>Authorization</key>
      <string>Allow</string>
    </dict>
  </array>
</dict>

Talon requires SystemPolicyAllFiles to read diagnostic metadata across the filesystem. It does not request ScreenCapture, Camera, Microphone, Accessibility or ListenEvent, and the notarised bundle contains no such entitlement — which you can verify yourself with codesign -d --entitlements.

Jamf, Kandji, Mosyle

  1. 01Upload the PPPC profile and scope it to the target smart group. Confirm it lands before proceeding.
  2. 02Upload the signed PKG as a package.
  3. 03Create a policy with a script payload that writes the enrollment token to /var/tmp/kestrel-enroll and then installs.
  4. 04Scope to the same smart group. Set the trigger to enrollment complete plus recurring check-in.
verify / uninstall / logs
# verify
/usr/local/bin/talon status
launchctl print system/io.kestrel.talon

# uninstall
sudo /usr/local/bin/talon uninstall --purge

# logs
/Library/Logs/Kestrel/talon.log
log show --predicate 'subsystem == "io.kestrel.talon"' --last 1h

Linux

Debian / Ubuntu
curl -fsSL https://dl.kestrel.io/apt/kestrel.gpg \
  | sudo tee /usr/share/keyrings/kestrel.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/kestrel.gpg] \
  https://dl.kestrel.io/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/kestrel.list
sudo apt update && sudo apt install talon
sudo talon enroll --token <token> --group "Servers"
RHEL / Rocky / Alma
sudo rpm --import https://dl.kestrel.io/yum/kestrel.asc
sudo tee /etc/yum.repos.d/kestrel.repo <<'EOF'
[kestrel]
name=Kestrel
baseurl=https://dl.kestrel.io/yum/stable
gpgcheck=1
gpgkey=https://dl.kestrel.io/yum/kestrel.asc
EOF
sudo dnf install talon
sudo talon enroll --token <token>
Ansible
- hosts: endpoints
  become: true
  roles:
    - role: kestrel.talon
      vars:
        talon_enroll_token: "{{ vault_kestrel_token }}"
        talon_device_group: "Servers"
        talon_version: "1.8.2"
verify / uninstall / logs
# verify
systemctl status talon
talon status

# uninstall
sudo apt remove --purge talon     # or: sudo dnf remove talon

# logs
journalctl -u talon -f
/var/log/kestrel/talon.log

Network egress

Talon makes outbound connections only. It opens no listening port on any platform.

DestinationPortPurpose
ingest.kestrel.io443 (gRPC/mTLS)Telemetry, action dispatch, results
standdown.kestrel.io443Recall — deliberately separate infrastructure from ingest
dl.kestrel.io443Agent and Quarry bundle downloads
ocsp.kestrel.io80Certificate revocation checking
KNOWN LIMITATION
TLS-inspecting proxies break the mTLS channel — the agent pins our intermediate and will refuse an intercepted connection rather than fall back. Add the four hostnames above to your inspection bypass list. This is intentional and we will not add a flag to disable pinning.