> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vijil.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Install a Collector

> Credentials, prerequisites, and install steps for each Collector kind.

A [Collector](/concepts/discovery/collector) is the software that does the looking. Install
it against a [Target](/owner-guide/discover/targets).

## Before You Install

**Vijil provides the Collector artifacts.** Arrange them before you book an install window.
Package names, services, and paths on this page use the name `vijil-shadow`.

| Kind | Artifact you receive |
| - | - |
| **Endpoint** | A platform package: a `.pkg` for macOS, a `.deb` or `.rpm` for Linux, a ZIP archive for Windows |
| **Network scanner** | A container image, and access to the registry that holds it |
| **In-cluster** | A Helm chart and the same container image |
| **Cloud API** | The same Helm chart |
| **Browser extension** | A Chrome or Edge extension, and the policy to push it |

## Network Requirements

Collectors need outbound DNS and HTTPS to the control plane on port `443`. They only make
outbound connections, so you can leave your inbound firewall rules closed.

Tell your security operations team before the first network-scanner sweep. A scanner
sweeping a `/16` reaches 65,536 addresses and will register on intrusion detection as a port
scan.

## Values Every Collector Needs

Every Collector needs two values.

**Where to report.** The control plane address. On Vijil's hosted service it is
`https://discover.vijil.ai`. On a self-hosted Console, read it with:

```bash theme={null}
vijil discover setup-info
```

**Which Target.** The `id` returned when you created the Target. See
[Create and Manage Targets](/owner-guide/discover/targets).

## Choose a Credential

| Credential | Use when | Mint it with |
| - | - | - |
| **Scanner token** | You install by hand: a virtual machine, a Helm release, a cloud connector. One token per Collector, revocable on its own. | `vijil discover scanner-mint <target-id> --scanner-kind <kind>` |
| **Enrollment code** | The install is unattended and repeated: a laptop fleet through device management. One code serves the whole wave, and each machine registers as its own Collector. | `vijil discover enrollment-code-create <target-id>` |

Both are also available in the Console, on the **Scanners** sub-tab of the Target.

<Frame>
  <img src="https://mintcdn.com/vijil/yqUb77g7JVk3yDhV/images/owner-guide/discover/scanners-tab-empty.jpg?fit=max&auto=format&n=yqUb77g7JVk3yDhV&q=85&s=37e6419abd317dd860bfee9093ee26e3" alt="The Scanners sub-tab of a Target before any Collector has enrolled" width="1390" height="764" data-path="images/owner-guide/discover/scanners-tab-empty.jpg" />
</Frame>

Use **+ Mint scanner token** for a scanner token, or **+ Generate code** for an enrollment
code.

An enrollment code takes two settings:

| Field | What to enter |
| - | - |
| **Allowed scanner kinds** | The kinds this code may enroll, comma separated. Enter `*` to allow any. |
| **TTL (hours)** | How long the code stays usable, up to a maximum of 720 hours. |

For an endpoint rollout, allow only the platform you are deploying to: `endpoint_macos`,
`endpoint_linux`, or `endpoint_windows`.

A code allowing `*` for 720 hours enrolls anything for 30 days. Scope both settings to the
rollout you are running.

<Frame>
  <img src="https://mintcdn.com/vijil/yqUb77g7JVk3yDhV/images/owner-guide/discover/enrollment-code-form.jpg?fit=max&auto=format&n=yqUb77g7JVk3yDhV&q=85&s=75d8bdbbdb490ebfdb9f80e515bb5ef6" alt="The enrollment code form showing allowed scanner kinds and a time to live in hours" width="1390" height="764" data-path="images/owner-guide/discover/enrollment-code-form.jpg" />
</Frame>

The Console shows the code in full **once**, immediately after you generate it. Copy it then.
Afterwards only the identifier and the expiry remain visible.

## Endpoint Collectors

The endpoint Collector runs as a service on the machine you want inventoried. It runs on
macOS, Linux, and Windows.

Use an **enrollment code** for a fleet, and push the package through your device management
or configuration management tool. Every install needs administrator or root privileges.

### macOS

Write the enrollment code to `/etc/vijil-shadow/enrollment-code` **before** running the
installer:

```bash theme={null}
sudo install -d -m 700 /etc/vijil-shadow
printf '%s' '<enrollment-code>' | sudo tee /etc/vijil-shadow/enrollment-code >/dev/null
sudo chmod 600 /etc/vijil-shadow/enrollment-code
```

The macOS installer does not read environment variables, so the file is the only way to pass
the code. Then run the installer Vijil supplied. It starts the Collector as a service.

Logs land under `/var/log/vijil-shadow/`. Read `endpoint.log` first, then `endpoint.err.log`
if the first is empty.

### Linux

Vijil supplies a `.deb` package for Debian and Ubuntu, and a `.rpm` package for Fedora and
RHEL. Vijil tests both on Ubuntu 22.04 and 24.04, and on RHEL 8 and 9.

Pass the control plane address and the enrollment code on the install command:

<CodeGroup>
  ```bash Debian / Ubuntu theme={null}
  sudo VIJIL_SHADOW_CONTROL_PLANE_URL='<control-plane-url>' \
       VIJIL_SHADOW_ENROLLMENT_CODE='<enrollment-code>' \
       dpkg -i vijil-shadow-endpoint-<version>.x86_64.deb
  ```

  ```bash Fedora / RHEL theme={null}
  sudo VIJIL_SHADOW_CONTROL_PLANE_URL='<control-plane-url>' \
       VIJIL_SHADOW_ENROLLMENT_CODE='<enrollment-code>' \
       rpm -i vijil-shadow-endpoint-<version>-1.x86_64.rpm
  ```
</CodeGroup>

Keep both variables on the `sudo` line, as shown. `sudo -E` does not pass them through on
every distribution, and the install then warns `VIJIL_SHADOW_CONTROL_PLANE_URL not set`.

The package starts the `vijil-shadow-endpoint` service. Confirm it runs:

```bash theme={null}
sudo systemctl status vijil-shadow-endpoint
sudo journalctl -u vijil-shadow-endpoint -f
```

Logs also land in `/var/log/vijil-shadow/endpoint.log`.

### Windows

Vijil supplies a ZIP archive with the Collector and two PowerShell scripts,
`install-service.ps1` and `uninstall-service.ps1`.

Run the install from an elevated PowerShell session:

```powershell theme={null}
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

Expand-Archive vijil-shadow-endpoint-<version>.x86_64.zip -DestinationPath C:\vijil
cd C:\vijil

.\install-service.ps1 `
    -ControlPlaneUrl '<control-plane-url>' `
    -EnrollmentCode '<enrollment-code>'
```

The script installs and starts the `VijilShadowEndpoint` service, then waits for the
Collector to enroll. If enrollment fails, it exits with an error and prints the log lines
that explain why.

<Warning>
  `Get-Service` can report **Running** for a Collector that never enrolled. Confirm that
  `C:\ProgramData\vijil-shadow\identity.json` exists instead.
</Warning>

If the file is missing, read the service log:

```powershell theme={null}
Get-Content 'C:\ProgramData\vijil-shadow\service-stderr.log' -Tail 20 -Wait
```

The Windows Collector does not cover WSL2. Install the Linux endpoint Collector inside WSL2
as well.

To remove the Collector, [revoke it](#revoke-credentials) first, then run
`.\uninstall-service.ps1`.

### Self-Signed Control Plane Certificates

If your control plane uses a self-signed certificate, trust it on the machine before you
install. Otherwise the Collector logs `CERTIFICATE_VERIFY_FAILED` and cannot enroll.

<CodeGroup>
  ```bash Fedora / RHEL theme={null}
  sudo cp <control-plane-cert>.crt /etc/pki/ca-trust/source/anchors/
  sudo update-ca-trust
  ```

  ```bash Debian / Ubuntu theme={null}
  sudo cp <control-plane-cert>.crt /usr/local/share/ca-certificates/
  sudo update-ca-certificates
  ```

  ```powershell Windows theme={null}
  Import-Certificate -FilePath <control-plane-cert>.crt `
      -CertStoreLocation Cert:\LocalMachine\Root
  ```
</CodeGroup>

### Upgrades and Re-Enrollment

An upgrade needs no new enrollment code. On Linux, remove the old package and install the
new one. On Windows, run `install-service.ps1` from the new archive with only
`-ControlPlaneUrl`.

If you revoke a Collector or recreate its Target, give the machine a fresh enrollment code.
Write it to `/etc/vijil-shadow/enrollment-code` on macOS or Linux, or to
`C:\ProgramData\vijil-shadow\config\enrollment-code` on Windows. The Collector re-enrolls
within five minutes and appears as a new Collector, so revoke the old one.

## Network Scanner Collectors

The network scanner runs as a container on a virtual machine inside the network. It finds
services by reaching out to hosts it can route to.

**What you supply**

* A virtual machine inside the target network, with routes to the subnets you want swept
* Docker installed on it
* A language model API key for classification, unless you accept an `Uncertain` group. See [Classification](/concepts/discovery/classification).

Mint a **scanner token**, then write the Collector's environment to a file. Every user who
can run `ps` on the host sees anything you pass with `-e`.

```bash theme={null}
sudo install -m 600 /dev/null /etc/vijil-shadow/secrets.env
sudo tee /etc/vijil-shadow/secrets.env >/dev/null <<'EOF'
LLM_API_KEY=<language-model-api-key>
ANTHROPIC_API_KEY=<language-model-api-key>
SCAN_CIDRS=10.0.0.0/16
CONTROL_PLANE_URL=<control-plane-url>
CONTROL_PLANE_DEPLOYMENT_ID=<target-id>
CONTROL_PLANE_TOKEN=<scanner-token>
EOF
```

Then run the Collector as a resident daemon:

```bash theme={null}
sudo docker run -d --restart unless-stopped \
    --network=host \
    --cap-add=NET_RAW \
    --name vijil-shadow \
    --env-file /etc/vijil-shadow/secrets.env \
    -v /var/lib/vijil-shadow:/out \
    <image> \
    daemon
```

<Warning>
  Use the `daemon` subcommand. The `scan` subcommand runs once and then exits. **Scan now**
  queues work for a Collector to pick up, so it only works while a Collector stays running.
</Warning>

`--network=host` and `--cap-add=NET_RAW` are both required. Without them, the sweep exits
with a permission error.

## In-Cluster Collectors

The in-cluster Collector reads your cluster's services through the Kubernetes API, so you
can skip provisioning a virtual machine.

**What you supply**

* A Kubernetes cluster, 1.27 or later, with `kubectl` configured against it
* Helm 3.8 or later
* A language model API key for classification

Mint a **scanner token**, then install the chart:

```bash theme={null}
helm install vijil-shadow ./vijil-shadow \
    --set scan.mode=k8s \
    --set daemonMode.enabled=true \
    --set daemonMode.persistence.enabled=true \
    --set llmApiKey="$LLM_API_KEY" \
    --set controlPlane.enabled=true \
    --set controlPlane.url="$CONTROL_PLANE_URL" \
    --set controlPlane.deploymentId="$TARGET_ID" \
    --set controlPlane.token="$SCANNER_TOKEN"
```

To keep the key out of the release values, pre-create a Secret and reference it with
`--set existingSecret.name=<secret-name>` instead of `--set llmApiKey`. The chart reads the
key `LLM_API_KEY` from that Secret unless you override `existingSecret.key`.

## Cloud API Collectors

The cloud API Collector lists managed AI in your AWS account: Bedrock models and agents,
SageMaker endpoints, AgentCore runtimes and gateways, and the Guardrails attached to them.

**What you supply**

* An Amazon EKS cluster with an OIDC provider configured
* `kubectl` and Helm 3.8 or later against that cluster
* An IAM role holding read-only list permissions for the services you want listed, with a trust policy admitting your cluster's OIDC issuer

This Collector needs **no language model API key**.

Mint a **scanner token**, then install the chart with the role attached to its service
account:

```bash theme={null}
helm install vijil-shadow-aws ./vijil-shadow \
    --set connector.enabled=true \
    --set connector.mode=cloud-api/aws \
    --set connector.useLlm=false \
    --set connector.aws.region=us-east-1 \
    --set serviceAccount.create=true \
    --set 'serviceAccount.annotations.eks\.amazonaws\.com/role-arn=<role-arn>' \
    --set controlPlane.enabled=true \
    --set controlPlane.url="$CONTROL_PLANE_URL" \
    --set controlPlane.deploymentId="$TARGET_ID" \
    --set controlPlane.token="$SCANNER_TOKEN"
```

It runs on a schedule.

## Browser Extension Collectors

The browser extension reports the AI assistants people use in the browser, per tab.

Use an **enrollment code** and push the extension through browser policy, the same way you
would any other managed extension.

## One-Shot Collectors

These Collectors run once against a specific source and exit. They take the same credentials
and report into the same Target.

| Collector | Reports |
| - | - |
| **EASM** | Internet-facing surface for a domain you own |
| **Egress** | AI destinations reached from your network, read from egress records |
| **Logs** | AI usage found in logs you already collect |
| **Identity provider** | AI applications authorized through your identity provider |
| **Gateway** | AI traffic seen by an API gateway |

A scanner reports what exists. These Collectors report what people actually use.

## Verify a Collector Connected

Open the Target in the Console. The Collector appears on the **Scanners** sub-tab once it
checks in, and the header badge shows one of four states:

| Badge | Meaning |
| - | - |
| **Agent online** | Reporting normally |
| **Agent stale** | Missed its last check-in |
| **No agent reporting** | Has reported before, but not recently |
| **No agent connected** | Has never reported |

**Agent stale** and **No agent reporting** appear only on this badge. Check it when a
Collector stops working.

From the command line:

```bash theme={null}
vijil discover scanner-list <target-id>
```

A new Collector appears within a minute of starting.

A Collector that stays silent for 30 days drops out of the current view, and its findings
with it.

## Troubleshooting

**The Collector never appears on the Scanners sub-tab.** Work down this list:

1. Confirm the service is running, and read its log. On macOS and Linux, read
   `endpoint.log` under `/var/log/vijil-shadow/` first, then `endpoint.err.log` if the first
   is empty. On Windows, read `C:\ProgramData\vijil-shadow\service-stderr.log`.
2. On a macOS or Linux endpoint Collector, confirm `/etc/vijil-shadow/enrollment-code`
   exists and holds the code. On Windows, confirm `C:\ProgramData\vijil-shadow\identity.json` exists.
3. Confirm the host can reach the control plane outbound on port `443`.
4. Confirm the control plane address matches the one `vijil discover setup-info` returns.
5. Confirm the credential is still valid and belongs to **this** Target.

**Uploads fail with HTTP 401.** You minted the token for a different Target than the one the
Collector uses. Re-mint against the Target you meant.

**Scan now appears to do nothing.** Either the Collector ran once and exited, so reinstall
it with the `daemon` subcommand, or no Collector has checked in for 24 hours. In the second
case the Console says *"No agent has checked in during the last 24 hours, so nothing was
queued."*

## Revoke Credentials

Revoking takes effect immediately. Revoking a scanner also removes its findings from the
current view at once, without waiting for the 30-day silence window. Its past reports stay in
scan history.

```bash theme={null}
vijil discover scanner-revoke <scanner-id>
vijil discover enrollment-code-revoke <code-id>
```

You cannot revoke the Collector that uses the Target's own install token. Rotate the install
token instead.

Revoke enrollment codes once you finish the rollout. Every machine that holds a live code
can still enroll with it.

## Next Steps

<CardGroup cols={2}>
  <Card title="Review Discovered Resources" icon="scan-search" href="/owner-guide/discover/reviewing-resources">
    Read what the scan returned.
  </Card>

  <Card title="Register a Discovered Agent" icon="bot" href="/owner-guide/discover/registering-agents">
    Move a finding into the Agent Registry.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.