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

# Install a Sensor

> One install.sh — Cloudflare client cert, Docker Compose OCI, cosign-verified updates.

Deploy a sensor with one command: enroll with your org API key, pull the signed
OCI compose stack, and let the hourly puller keep it current.

## What you run

```bash theme={null}
curl -fsSL 'https://reyhford.com/sensors/install.sh?key=YOUR_API_KEY' | sudo bash
```

(`API_KEY=… curl … | bash` does **not** pass the key into bash — use `?key=`.)

That script:

1. **Enrolls** — EC P-256 key on the node → Cloudflare client certificate via `/sensors/register`
2. **Runs** — `docker compose` from `oci://ghcr.io/reyhford/sensor:latest` + host cert override
3. **Updates** — enables `reyhford-sensor-pull.timer` (`:latest` → cosign verify → `compose up`)

Honeypots and Vector ship inside the OCI artifact — not in `install.sh`.

## Prerequisites

* Linux host (root / sudo)
* Public IPv4 (honeypot ports bind on the host)
* Docker (installed by `install.sh` if missing)
* Org API key from the [developer portal](https://reyhford.com/portal)

## Step 1 — Get your API key

1. Open the [developer portal](https://reyhford.com/portal) and sign in.
2. Copy your org **API key** (same key used for the public API).
3. Or use [Add Sensor](https://reyhford.com/portal/sensors) for the one-liner template.

## Step 2 — Run it

Paste the command on your Linux host. First boot enrolls the node and starts
Cowrie, Dionaea, Conpot, and Vector.

## Step 3 — Confirm

* Containers: `docker ps` (all should be healthy)
* Portal: [My Sensors](https://reyhford.com/portal/sensors/list)
* API: `GET https://reyhford.com/api/v1/sensors/{sensor_id}/status`

## Updates

Do nothing. `reyhford-sensor-pull.timer` runs about hourly: resolves
`ghcr.io/reyhford/sensor:latest`, verifies the cosign signature (GitHub Actions
OIDC / Fulcio), then `docker compose pull && up`. Failed verify = no update.

## Security model (short)

| Layer                   | Mechanism                                                         |
| ----------------------- | ----------------------------------------------------------------- |
| Join                    | Org Zuplo `API_KEY` (not persisted on the node)                   |
| Node identity           | Cloudflare client certificate (fingerprint → Workers KV)          |
| Workload auth to ingest | mTLS to `ingest.reyhford.com`                                     |
| Attribution             | Ingest stamps `sensor_id` / `org_id` from KV (never from payload) |
| Supply chain            | OCI + keyless Cosign (GitHub OIDC)                                |
| Blast radius            | Revoke the client certificate / sensor                            |
