Skip to main content
SaltStack deploys AI Watch to Linux fleets the config-management way: Salt installs the runlayer-aiwatch package on each minion and manages the two config files, so a state.apply both rolls out and continuously asserts the Detect-only contract. This is the same Linux (Detect only) package — see that page for supported distributions, package internals, and the scan cadence. This page covers only the Salt-specific delivery. An example formula ships in the repo at cli/packaging/linux/salt/ (runlayer-aiwatch/init.sls, the config templates, and pillar.example.sls). It is a starting point, not a supported product — copy it into your own Salt tree and adapt it to your conventions.

What it does

  • Installs the .deb / .rpm from your own Salt fileserver (salt://runlayer-aiwatch/), selecting the right filename by OS family.
  • Manages /etc/runlayer/aiwatch/config.json (0644, non-secret) and /etc/runlayer/aiwatch/credentials (0600, root-only) from pillar, so Salt is the source of truth for both.
  • Ensures the cron daemon is enabled. Cron re-reads the packaged /etc/cron.d/runlayer-aiwatch on its own; the config files trigger nothing.
Linux is Detect-only: cron-scheduled scans across all users, no endpoint modes, Sessions, or browser extension. In the dashboard the device shows Detect = Active and Protect / Enforce / Sessions = Disabled — the expected state, not an error.

Prerequisites

  • A Salt master with the minions enrolled, plus a cron daemon on each minion (the package pulls one in automatically — see Linux).
  • The .deb and .rpm on your Salt fileserver under salt://runlayer-aiwatch/. The Runlayer CDN is token-gated, so fetch the packages once with your download token and serve them from salt:// — Salt itself never talks to the CDN:
    Contact your Runlayer account team if you don’t have a download token yet.

Pillar keys

The formula reads a single runlayer_aiwatch pillar. Copy pillar.example.sls, fill it in, and target it at the right minions:
Never put the org API key in config.json, and never commit it in plaintext. config.json is world-readable by design so unprivileged per-user scan children can read managed settings; the key belongs only in the 0600 credentials file. Keep the plaintext key in a GPG-encrypted pillar (Salt’s #!gpg|yaml renderer decrypts it on the master at compile time) or your existing secrets backend. The formula writes the credentials file with show_changes: False so the key is never echoed into Salt job returns or master logs.
config.json always renders "Sessions": false and "Enforcement": false — the formula hard-sets them, so the Detect-only contract holds no matter what the pillar says. It renders "AutoUpdate" from auto_update, which defaults to false so Salt remains the package-version owner. If you set auto_update: true, align the backend AI Watch update policy and target version with the Salt pillar. Otherwise the self-updater can install one version and the next Salt apply can replace it with another.

Apply

The first apply installs the package and writes both config files; cron fires the first scan on the next 15-minute tick. The packaged hourly updater remains disabled with the default auto_update: false.

Verify

In the Runlayer dashboard, go to Shadow AI → Devices: the device appears with OS = Linux, Detect = Active, and Protect / Enforce / Sessions = Disabled within about 15 minutes. Disabled endpoint modes and Sessions are the correct Detect-only state on Linux. For on-host verification (sudo /usr/lib/runlayer/run-aiwatch-scan.sh), see Linux (Detect only).

Idempotency

A second state.apply is a no-op once the installed package and the two config files match the pillar — Salt reports no changes. With auto_update: false, upgrade by bumping version in the pillar and placing the new .deb / .rpm on your fileserver; the next apply installs it in place. Your managed config.json and credentials are re-asserted from pillar on every run.

Other config managers

This generalizes directly: install the .deb / .rpm, manage config.json (0644) and credentials (0600), and ensure cron runs — the same three steps port to Ansible, Puppet, or Chef.