Run a sensor
A BoarNet sensor is a low-interaction honeypot. After 48 hours of valid telemetry your API key is promoted to Participant — full JA3/JA4 access, per-sensor sightings, 90-day history.
5-minute quickstart
The fastest path from this page to events flowing from your own box. Assumes a Linux host (VPS, Pi, or old laptop) with a public-reachable IP, and that you're signed in to BoarNet. Total time: ~5 minutes, mostly waiting for the first scanner.
- Mint a token. Go to /dashboard/sensors, click New token, label it (e.g.
home-pi), copy thebn_…value. The token is shown once; paste it into your shell history at your own discretion. - Run the agent. SSH into your box and run:Pure Go, no dependencies. The agent stays in the foreground — you should seebash
curl -LO https://github.com/Bino97/boarnet/releases/latest/download/boarnet-linux-amd64 chmod +x boarnet-linux-amd64 ./boarnet-linux-amd64 \ --token=bn_<paste-here> \ --ingest-url=https://www.boarnet.io/api/ingest/v1/events \ --sensor-id=$(hostname) \ --fleet=mesh
agent readywithin a couple seconds. Wrap innohup,tmux, or a systemd unit for production. - Watch the dashboard. Open /dashboard/sensorsin another tab. The token's Last used column updates within ~5 seconds of the first heartbeat.
- Wait for an attacker. Median time to first non-heartbeat event from a fresh public IP: 30 seconds to 5 minutes (a Shodan crawl, a Mirai scanner, an SSH-bruteforce bot — pick one). When something hits, your tier flips from
OBSERVERtoPARTICIPANTand the dashboard pulse shows the event.
What you'll see
Three signals confirm the sensor is healthy and pulling its weight:
- On the agent's log:
ssh honeypot listening/tls honeypot listening/agent ready — draining buffer every 5s. Subsequent attacker connections log ascaptured tcp connect src=… port=22. - On /dashboard/sensors: your token row shows Last used ticking forward; click through to the sensor detail page for live event-type breakdowns and the raw envelope dump.
- On /dashboard: the 24-hour pulse counter increments; your sensor appears in the fleet table with a
LIVEbadge.
If 30 minutes pass with nothing but heartbeats, jump to Troubleshooting — almost always a port-forward / firewall issue, not a sensor bug.
Hardware
Anything Linux-capable works. A few combinations that people in the community have run for months:
- A spare Raspberry Pi 3 or 4 on a home network (port-forward recommended)
- A $5/month VPS at your cloud provider of choice
- An old laptop running Ubuntu Server in a closet
- A repurposed mini-PC or NAS with Docker installed
CPU and RAM requirements are modest: a single sensor comfortably fits in 512 MB of RAM and uses less than 1% of a Pi 4's CPU during normal activity.
Install
Three supported paths. All three produce the same sensor — pick whichever fits your host.
Option A · Install script (recommended)
One-liner that detects your OS+architecture, fetches the latest signed binary, verifies it against SHA256SUMS, and atomically swaps it into /usr/local/bin/boarnet. Same command works for first install and upgrades — re-run it whenever you want to update.
curl -fsSL https://boarnet.io/install.sh | sudo bash
Then start the agent with your token:
boarnet \ --token=bn_<your-token> \ --ingest-url=https://www.boarnet.io/api/ingest/v1/events \ --sensor-id=$(hostname) \ --fleet=mesh
Pin a specific version with BOARNET_VERSION=v0.4.1 sudo bash. Force a reinstall (overwriting the same version) with BOARNET_FORCE=1 sudo bash. If you have a boarnet-agent systemd unit installed, the script restarts it automatically.
Option B · Manual binary download
For locked-down hosts where piping to bashisn't an option:
curl -LO https://github.com/Bino97/boarnet/releases/latest/download/boarnet-linux-amd64 chmod +x boarnet-linux-amd64 ./boarnet-linux-amd64 \ --token=bn_<your-token> \ --ingest-url=https://www.boarnet.io/api/ingest/v1/events \ --sensor-id=$(hostname) \ --fleet=mesh
Binaries are built for linux-amd64, linux-arm64, darwin-amd64, and darwin-arm64. Pure-Go, statically linked — no libc or Go toolchain required on the host. Verify with SHA256SUMS attached to the same release.
Option C · Docker
Multi-arch image (linux/amd64 + linux/arm64). The simplest deployment uses --network host so the container auto-exposes every port the agent listens on (SSH/TLS/HTTP + the 15 SYN-sink ports):
docker run -d \ --name boarnet-sensor \ --restart unless-stopped \ --network host \ -v boarnet-data:/data \ ghcr.io/bino97/boarnet-sensor:latest \ --token=bn_<your-token> \ --ingest-url=https://www.boarnet.io/api/ingest/v1/events \ --sensor-id=$(hostname) \ --fleet=mesh \ --data-dir=/data
--network host is Linux-only. On Docker Desktop (macOS / Windows) map each port explicitly — at minimum the three honeypots:
docker run -d \ --name boarnet-sensor \ --restart unless-stopped \ -p 2222:2222 \ -p 8443:8443 \ -p 8080:8080 \ -v boarnet-data:/data \ ghcr.io/bino97/boarnet-sensor:latest \ --token=bn_<your-token> \ --ingest-url=https://www.boarnet.io/api/ingest/v1/events \ --sensor-id=$(hostname) \ --fleet=mesh \ --data-dir=/data
The boarnet-data volume persists the encrypted event buffer, HMAC pepper, and SSH host key across restarts — important for honeypot identity stability.
Verify the sensor is reporting
Open the Sensors pageon your dashboard — the token's Last used column updates on every drain cycle (~every 5 seconds once events land). Your tier pill flips from OBSERVER to PARTICIPANT on the first successful ingest.
Enrollment
Enrollment is a single token. Mint one on the Sensors page, paste it into the --token flag, and your sensor is online.
- Sign in to the dashboard
- Mint a token (label it something you'll recognize — e.g.
home-pi,vps-frankfurt) - Paste the
bn_…value into the sensor's--tokenflag - Start the binary or container; it registers on first event
Minting a token grants your account an immediate 48h Participant trial. Every subsequent sensor event (including heartbeats every ~60s) rolls the grace window forward — so as long as your sensor stays online, you stay Participant.
How location is determined
The map and the per-record sensor list show where each sensor is. Location is derived entirely at the ingest API from the public IP the sensor uses to reach us — the same IP the OS network stack already exposes to any server the sensor connects to. No probe of the host, no query of its filesystem or WiFi state.
GeoIP gives us the country, and often the nearest metro area for the city. If you want the sensor pinned to a specific spot in the map grid, raise an issue on GitHub— we're planning a self-declared override flag for future versions.
Privacy boundary
The sensor is purpose-built to collect as little about you as possible while still being useful to the mesh. Everything the mesh learns about a sensor is listed below — if it's not here, we don't have it.
| Leaves your box | Never leaves |
|---|---|
| Attacker connection metadata (source IP, port, timestamp) | Your home network shape or internal IPs |
| TLS ClientHello bytes (for JA3/JA4 hashing) | Any non-attack traffic on your network |
| SSH handshake (for fingerprinting) | WiFi SSIDs or connected-device inventory |
| Low-interaction session transcript (attacker commands) | System telemetry or machine fingerprint |
| Your sensor's public IP (seen by the ingestion API) and optional self-declared city | Precise coordinates, street address, or device location |
Troubleshooting
Sensor is online but not seeing traffic
Most likely your IP isn't reachable from the public internet. Confirm port forwarding is in place and run nc from another machine to verify.
Sensor has been up 48 hours but isn't promoted
The promotion check looks for unique attacker signatures. If your network only sees the same scanner repeatedly, wait — real diversity arrives with time.