- Go 98.7%
- Dockerfile 1.3%
| .forgejo/workflows | ||
| cmd/netbox-discovery-agent | ||
| internal | ||
| systemd | ||
| .dockerignore | ||
| .gitignore | ||
| .golangci.yml | ||
| config.example.yaml | ||
| docker-compose.example.yml | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| README.md | ||
netbox-discovery-agent
netbox-discovery-agent scans one or more IPv4 networks, checks each usable IP with ICMP ping and reverse DNS, and upserts the results into NetBox IPAM with the official go-netbox client.
Each --network value is expected to match an existing NetBox prefix exactly. The program resolves that prefix first and uses its VRF context so the created IP address objects land under the correct prefix/VRF in NetBox.
For each usable IPv4 address in each target network, the program:
- creates or updates a NetBox IP address record as
x.x.x.x/<prefix-mask>using the scanned network mask - sets
dns_namefrom reverse DNS when a PTR record exists - sets status to
activeonly when ping succeeds - removes existing normal IP address records when ping does not succeed, so the address becomes
availableagain - skips reserved and DHCP IP ranges before probing, so those addresses are not scanned or updated
- leaves existing
reservedanddhcpIP address records untouched
Requirements
- Go 1.26.1 or newer
- a NetBox API token with permission to read and write IP addresses
- raw ICMP socket access on the machine running the program
- the target prefix must already exist in NetBox and be uniquely identifiable by the scanned CIDR
If raw ICMP access is not available, the program exits immediately with an error instead of silently degrading. If a scanned CIDR does not resolve to exactly one NetBox prefix, the program exits with an error instead of guessing.
Environment
Set these environment variables before running the program:
export NETBOX_URL="https://netbox.example.com"
export NETBOX_TOKEN="your-netbox-api-token"
The program also tries to load a .env file from the current working directory at startup. Missing .env files are ignored.
Example .env:
NETBOX_URL=https://netbox.example.com
NETBOX_TOKEN=your-netbox-api-token
Authentication scheme handling:
- tokens starting with
nbt_are sent asAuthorization: Bearer ... - all other tokens default to
Authorization: Token ... - you can override this with
NETBOX_AUTH_SCHEME=bearerorNETBOX_AUTH_SCHEME=token - the YAML config also supports
auth_scheme: bearerorauth_scheme: token
Logging
The program uses logrus.
- default log level is
debug - override with
--log-levelorLOG_LEVEL - the YAML config also supports
log_level - NetBox HTTP requests and responses are logged
- authorization headers are redacted in logs
Example:
LOG_LEVEL=debug ./netbox-discovery-agent --network 172.18.24.0/24 --dry-run
Project layout
cmd/netbox-discovery-agent— CLI entrypointinternal/app— runtime orchestration and schedulinginternal/config— config file loading and CLI/env resolutioninternal/discovery— network discovery logic split across focused filesinternal/netbox— NetBox client and sync logic split across focused files
Usage
Run the scanner against one or more IPv4 CIDRs:
go run ./cmd/netbox-discovery-agent --network 192.0.2.0/24
You can specify --network multiple times:
go run ./cmd/netbox-discovery-agent \
--network 192.0.2.0/24 \
--network 198.51.100.0/24
Use --dry-run to scan and log the intended NetBox changes without writing them:
go run ./cmd/netbox-discovery-agent --network 192.0.2.0/24 --dry-run
You can also load networks from a YAML config file:
netbox_url: https://netbox.example.com
netbox_token: nbt_your-token-here
auth_scheme: bearer
log_level: info
schedule: '0 * * * *'
networks:
- 172.18.24.0/24
- 172.18.25.0/24
An example file is included at config.example.yaml.
Run with:
go run ./cmd/netbox-discovery-agent --config config.yaml
If both --config and --network are used, networks from both sources are merged and duplicates are removed.
If both config and environment variables provide NETBOX_URL or NETBOX_TOKEN, the environment variables win.
If schedule is set in config or via --schedule, the process stays running and executes scans on that cron schedule.
Build a binary if you prefer:
go build -o netbox-discovery-agent ./cmd/netbox-discovery-agent
./netbox-discovery-agent --network 192.0.2.0/24
Flags
--network IPv4 CIDR to scan; repeatable and required
--config Optional YAML config file with a `networks:` list
--schedule Optional cron schedule for recurring scans
--concurrency Number of concurrent probes (default: 64)
--ping-attempts Number of ICMP attempts before marking a host unreachable (default: 3)
--ping-timeout Timeout per ICMP probe (default: 1s)
--dns-timeout Timeout per reverse DNS lookup (default: 1s)
--dry-run Log intended NetBox changes without writing them
Examples
Scan a /24 and write results to NetBox:
NETBOX_URL="https://netbox.example.com" \
NETBOX_TOKEN="token" \
go run ./cmd/netbox-discovery-agent --network 10.0.10.0/24
Scan two networks with lower concurrency:
NETBOX_URL="https://netbox.example.com" \
NETBOX_TOKEN="token" \
go run ./cmd/netbox-discovery-agent \
--network 10.0.10.0/24 \
--network 10.0.20.0/24 \
--ping-attempts 3 \
--concurrency 16
Run as a long-lived scheduled service every hour:
./netbox-discovery-agent --config config.yaml --schedule "0 * * * *"
Scheduling
Schedules use standard 5-field cron syntax:
minute hour day-of-month month day-of-week
Examples:
0 * * * * # every hour
*/15 * * * * # every 15 minutes
0 2 * * * # every day at 02:00
The process launches one scan immediately in scheduled mode, then waits for the next matching cron time. If a scheduled run is still active when the next time arrives, the next run is skipped.
systemd
An example service unit is included at netbox-discovery-agent.service.example. Setup notes are in systemd/README.md.
Container Image
A multi-stage Alpine container build is included in Dockerfile.
The final container runs as root, and the container needs NET_RAW capability so it can send ICMP probes.
Build locally:
docker build -t netbox-discovery-agent:local .
Run locally:
docker run --rm \
--network host \
--cap-add NET_RAW \
-v "$PWD/config.yaml:/work/config.yaml:ro" \
ghcr.io/kmendell/netbox-discovery-agent:latest \
--config /work/config.yaml
An example Compose file is included at docker-compose.example.yml.
The release workflow at release.yml runs on Forgejo for tag pushes like v1.0.0 and publishes multi-arch images to ghcr.io/kmendell/netbox-discovery-agent.
Required Forgejo secrets:
GHCR_USERNAMEGHCR_TOKEN