Sensor configuration
What a sensor scans is set in the Console, not on the host. Open the sensor’s
detail page under Sensors and edit its targets, filters, profile, interval,
timeout, and a pause switch. Targets are one row each, and every row carries its
own ports and, where the port convention is not enough, its own protocol - so a
mail segment and a web segment live in one configuration without being probed on
each other’s ports. The change is delivered to the sensor on
its next check-in - it rides on the report response over the same mTLS channel, so
there is no extra port or credential - and the sensor reconfigures itself live,
without a restart. The config version on the detail page counts the revisions you
have saved; it is the configuration the Console wants, not a receipt that the
sensor is running it. To confirm that, read the sensor’s log: it writes
applied config from console with the version it took.
The command-line flags below still exist. They set the initial values a sensor
runs with, and they let you run a sensor standalone. They keep working until you
save a configuration in the Console for the first time. From that first save on,
the Console is authoritative: it replaces the running config wholesale, it does
not merge, and flags on the host no longer have an effect. Clearing the target
list in the Console therefore stops the sensor scanning even when the host still
passes --targets. To pause a sensor without losing its configuration, use the
pause switch instead.
nextpki-sensor --help is authoritative for the flags; this page explains the
ones with consequences.
Global
Section titled “Global”| Flag | Environment | Default | Notes |
|---|---|---|---|
--data-dir |
NEXTPKI_DATA_DIR |
platform-specific | Where the mTLS identity lives. See install |
--log-level |
NEXTPKI_LOG_LEVEL |
info |
trace, debug, info, warn, error |
--log-format |
NEXTPKI_LOG_FORMAT |
json |
json or text. Use text interactively |
bootstrap
Section titled “bootstrap”Run once, to exchange a token for an identity.
| Flag | Environment | Default | Notes |
|---|---|---|---|
--token |
NEXTPKI_BOOTSTRAP_TOKEN |
- | Single-use, short-lived |
--endpoint |
NEXTPKI_BOOTSTRAP_ENDPOINT |
api.nextpki.com |
Registration host. https:// and the /v1/sensors/bootstrap path are assumed |
--machine-id |
NEXTPKI_MACHINE_ID |
- | Identifies this sensor. Must match the token’s hint if one was set |
Registration is a single HTTPS request; there is no separate registration port to
open. Pass the token by environment variable, not on the command line - a command
line is visible in ps to every user on the host.
| Flag | Environment | Default | Notes |
|---|---|---|---|
--ingest-endpoint |
NEXTPKI_INGEST_ENDPOINT |
from identity | Override the reporting endpoint |
--health-addr |
NEXTPKI_HEALTH_ADDR |
127.0.0.1:18080 |
Local /healthz. Keep it on loopback |
--scan-profile |
NEXTPKI_SCAN_PROFILE |
conservative |
See below |
--targets |
NEXTPKI_TARGETS |
- | Comma-separated. See targets |
--include |
NEXTPKI_INCLUDE |
- | Restrict to these after expansion |
--exclude |
NEXTPKI_EXCLUDE |
- | Never contacted, even if included elsewhere |
--exclude-cert |
NEXTPKI_EXCLUDE_CERTS |
- | Drop certificates by issuer or subject. See certificate filter |
--ports |
NEXTPKI_PORTS |
443 |
Ports for targets that name none of their own. Single ports and ranges: 443,8000-8443 |
--scan-interval-secs |
NEXTPKI_SCAN_INTERVAL_SECS |
3600 |
Seconds between full sweeps |
--config-heartbeat-secs |
NEXTPKI_CONFIG_HEARTBEAT_SECS |
60 |
Seconds between configuration checks, independent of the scan interval. Minimum 15 |
--probe-timeout-ms |
NEXTPKI_PROBE_TIMEOUT_MS |
3000 |
Timeout for each phase that names none of its own |
--dial-timeout-ms |
NEXTPKI_DIAL_TIMEOUT_MS |
probe timeout | TCP connect only. See pace |
--handshake-timeout-ms |
NEXTPKI_HANDSHAKE_TIMEOUT_MS |
probe timeout | TLS handshake and STARTTLS only |
--scan-throttle-delay-ms |
NEXTPKI_SCAN_THROTTLE_DELAY_MS |
0 |
Pause between starting probes |
--enable-ipv4-discovery |
NEXTPKI_ENABLE_IPV4_DISCOVERY |
on | Also scan this host’s own networks, bounded to private space in /24 or narrower, and only once the network is confirmed. See discovery |
--enable-ipv6-discovery |
NEXTPKI_ENABLE_IPV6_DISCOVERY |
off | Also probe known IPv6 neighbours. Linux only |
--relay-listen |
NEXTPKI_RELAY_LISTEN |
off | Forward for sensors without egress. See segments with no route outbound |
Targets
Section titled “Targets”A target is one of three things, and each may carry a port of its own:
| Target | Example | Notes |
|---|---|---|
| CIDR range | 10.0.0.0/24, 2001:db8::/120 |
IPv4 and IPv6. Expanded per cycle |
| Single address | 192.0.2.10, 2001:db8::1 |
|
| Hostname | mail.example.com |
Resolved (A and AAAA) on every cycle, so a host that moves is followed |
A port after the target applies to that target alone:
mail.example.com:993,10.0.0.0/24 scans the mail host on 993 and the range on
whatever --ports says. An IPv6 address needs brackets to carry a port:
[2001:db8::1]:993.
Ports are expressions, not just lists: 443,8000-8443 is valid wherever a port
is typed, up to 4096 ports per target. That limit is not a formality - a mistyped
1-65535 against a /16 is 4.3 billion probes, so it fails at configuration
time instead of running until the next century.
A hostname target sends SNI. That is the only way to see the certificate a virtual host actually serves; an address target sends none and gets the server’s default certificate. The name is reported alongside the finding, so you can tell which line produced it.
A target that cannot be used - a name that does not resolve, a broken port
expression, a range past the address limit - is logged and skipped. The other
targets still run: one typo does not stop a sensor from watching the segments
that are configured correctly. Search the log for scan target skipped.
Protocols
Section titled “Protocols”The port decides how the sensor speaks: 465, 993 and 995 are direct TLS, 25, 587,
143 and 110 are STARTTLS, and anything else is treated as HTTPS. A service on a
non-standard port needs to say so - a mail server on 8993 would otherwise be
probed as HTTPS and report nothing. In the Console, each target has a protocol of
its own for exactly that case: https, smtps, imaps, pop3s, smtp,
imap, pop3.
Automatic discovery
Section titled “Automatic discovery”IPv4 discovery is on by default. IPv6 discovery is off. A discovery agent that finds nothing until you configure it is not much of a discovery agent, so a fresh sensor looks at the segment it is standing in and nothing else.
“Nothing else” is precise, and it is the part worth having in writing, because scanning addresses nobody configured is the kind of thing an auditor asks about. Two bounds apply to what the sensor picks up on its own:
- Private address space only (
10/8,172.16/12,192.168/16). A public network your interface sits in belongs to other people - on a cloud VM that segment is full of strangers’ machines - and carrier-grade NAT space (100.64/10) is your provider’s. Neither is ever entered automatically. /24or narrower. 254 addresses is a segment. A/22or a/16is a routing domain, and the wider the interface, the less it says about what is actually nearby.
Anything outside those bounds is still reachable - it just takes a target you
typed. Every skipped network is logged with the reason, so the boundary is
visible rather than a surprise. Common corporate /23 and /22 segments fall
on the far side of it: configure those explicitly, in the size you mean.
Within the bounds, IPv4 adds the networks the sensor’s own interfaces sit
in. It reads its addresses and netmasks and scans those networks - it does not
sweep for neighbours, probe adjacent ranges, or follow routes. A 10.0.5.17/24
on an interface means 10.0.5.0/24 gets scanned, on your default ports.
To turn it off entirely, --enable-ipv4-discovery=false (or the same through
the console). The exclude filter keeps its precedence either way.
A network it has not been in before waits for a yes
Section titled “A network it has not been in before waits for a yes”A laptop does not stay put. It leaves the office, joins a hotel network, and the
segment its interface sits in is suddenly somebody else’s - a 192.168.178.0/24
full of strangers’ devices. Discovery, left to itself, would scan it.
So it does not. A network your tenant has never confirmed is reported and not scanned. The sensor tells the console what it can see, the network appears under Sensors waiting for a decision, and nothing is probed there until somebody says yes. Reject it and the sensor stops asking.
Confirm it and the sensor scans it on its next sweep. The decision travels with the next configuration check, so it reaches a running sensor within about a minute (sensor 0.9.1 and later; 0.9.0 only noticed a confirmation after a restart or after some other configuration change).
The gate keys on the network, not on how a target got into the list. If one of the host’s own interfaces sits inside a range you typed yourself, that target waits for the same confirmation: the probes would go into whatever segment the host is standing in today, which is the case the rule exists for. A target the host reaches through a router is unaffected. That is a remote network you named on purpose, and it does not change when the laptop moves.
How a network is recognised. Not by its address. 192.168.178.0/24 is the
factory setting of practically every consumer router, so a decision keyed on the
address would either release every employee’s home network at once or, kept per
sensor, quietly cover every hotel using the same range. The sensor derives a
fingerprint from the gateway’s hardware address together with the network, keyed
per tenant, and sends that instead. It is an HMAC: it recognises the same network
again, and it cannot be turned back into a MAC address.
Where no gateway address can be read - a network with no default route through
it, or a platform that does not expose the neighbour cache - the fingerprint
falls back to the network alone. Such a network is marked weakly identified and
is never confirmed by a rule; only a person can confirm it. The console
marks the row weak id, and where several sensors report the same weak network
it says that this is not evidence of one place: without a gateway address, two
machines behind the same model of router look identical.
What is taken as answered. Asking about every new network would turn this into noise that gets clicked away, so three cases need no click:
| Case | Why |
|---|---|
| The first cycle of a freshly registered stationary sensor | Somebody installed that machine somewhere and registered it in the same breath |
| Another stationary sensor of yours already sees the same network | A machine that does not travel sits where you put it, so its agreement is evidence about the place. Two laptops agreeing only proves they are in the same hotel |
| The report arrives from the same public address as a network you have already confirmed | The host is behind your own way out |
Each network records which of these applied, so an audit can tell a rule from a click, and a click from whom and against which wording.
Stationary or mobile is a property of the sensor, set at registration and
changeable afterwards. It defaults to mobile, the cautious direction: a mobile
sensor gets no first-cycle credit, because a notebook rolled out by device
management is typically first switched on at the employee’s kitchen table.
Sensors that existed before this rule are treated as stationary - they were
installed under the earlier behaviour and are, as far as anyone knows, standing
where you put them.
A network nobody decided about and nobody has seen for 30 days is removed together with its address. There is nothing left to decide about it.
A waiting network is not a quiet state. It means a segment is not being scanned, and a gap you do not know about is worse than one you do. After seven days without a decision the network raises an alert on the same channel as an expiring certificate, and it clears itself the moment somebody decides either way.
Confirmations for networks that travel expire. A confirmation says the
segment is yours to scan, and that can stop being true: a customer project ends,
a coworking contract lapses, a router is replaced. So a confirmed network that
no sensor has seen for 60 online days loses its confirmation, with a warning
at 45. The segment stops being scanned, and you are told it did - as
Coverage lost, not as a quiet withdrawal.
Two things bound this deliberately. The clock counts only days on which your sensors actually reported, so a shutdown period or a long leave does not drive it. And it does not run at all for a network any stationary sensor sees: a server standing in a segment is itself the evidence that the segment is still yours. In practice the rule only ever touches networks that a laptop visited and left. When a device returns, one click confirms it again.
You can see what it picked
Section titled “You can see what it picked”The sensor reports its decision with every scan, and the console shows it on the
sensor’s detail page under What this sensor scanned on its own: the networks
it took, and how many it left alone, per reason (outside private address space,
wider than /24, point-to-point link).
Note the asymmetry, which is deliberate. What it scanned is named, because those are your networks and you are entitled to the list. What it declined is counted, not named: a declined network is by definition one outside our limits, so its address belongs to a third party - a hotel’s range, another customer’s VPN - and it is not ours to keep. The count and the reason carry the attestation without carrying the address.
That is not decoration. The bound is what makes an on-by-default scan defensible, and a bound only your own host can see is a claim rather than evidence. It also makes the obvious request answerable: if a sensor picked up a segment you would rather it had not, the networks are on record, and everything found in them can be identified and removed.
IPv6 cannot work the same way. A /64 holds more addresses than a sweep
could finish in a lifetime, so the sensor asks the kernel which neighbours it
already knows and probes those. Be clear about what that gives you: the
neighbour cache fills as the host talks to its segment, so a freshly installed
sensor sees almost nothing there. It grows over the following hours and days. If
you need a specific IPv6 host in your inventory today, add it as a target.
IPv6 discovery is Linux only - the neighbour cache lives behind netlink, and the other platforms expose that information through entirely different interfaces. The switch exists everywhere, because one console configures every sensor, and it does nothing where it cannot be honoured. Unreachable and link-local entries are skipped either way; both appear in a real cache and neither can be probed.
Excludes still win. Everything discovered goes through the same include and exclude filters as a configured target, so an address you excluded stays excluded no matter which switch found it.
Certificate filter
Section titled “Certificate filter”The exclude filter above decides what is contacted. This one decides what is reported: wildcard rules matched against the issuer and the subject of the certificate a host serves.
*O=Ubiquiti**O=Synology*It exists because appliances sit on the same segments as the hosts you care about. An address filter would have to exclude them one by one, and a new device appears next week; a rule on the organisation holds regardless of where the box is plugged in.
* stands for any run of characters, ? for exactly one, and matching ignores
case. A rule is matched against the whole name, so *O=Ubiquiti* needs its
stars: a bare Ubiquiti only matches a certificate whose entire name is that
one word. The console refuses that spelling and suggests the working one, rather
than saving a filter that quietly never fires. Up to 64 rules, 256 characters
each.
The filtering happens on the sensor, before anything is sent. An excluded
certificate never leaves your network - it is not collected and then hidden. The
sensor logs how many it dropped per cycle (certificates excluded by rules);
raise the log level to debug to see which rule caught what.
A certificate the sensor cannot parse is reported, never dropped. The filter removes known noise; something unreadable is the opposite of that, and it is exactly what you want to look at.
On the command line the flag repeats: --exclude-cert '*O=Ubiquiti*' --exclude-cert '*O=Synology*'. The environment variable separates with
semicolons, not commas, because a distinguished name contains commas of its
own: NEXTPKI_EXCLUDE_CERTS='*O=Ubiquiti*;*O=Synology*'.
Two knobs decide how hard a sweep leans on the network: how long the sensor waits, and how fast it starts.
Timeouts are per phase. A probe is a TCP connect and then a handshake, and they want different numbers. An address that has not completed a connect in half a second is not going to; a mail server under load legitimately needs several seconds to finish a STARTTLS greeting. Set the connect timeout low and the handshake timeout high and a large range finishes far sooner without losing the slow-but-real hosts.
Leave a phase empty and it follows the probe timeout, which is what every sensor
did before these existed. Note that the probe timeout was never a per-probe
budget: it applies to each phase separately, so 3000 means up to three seconds
for the connect and another three for the handshake.
The throttle delays the start of each probe. On a fragile network - old switches, a firewall with a session table that fills up, an IDS that reads a sweep as an attack - this is the gentler tool than a smaller scan profile. The profile limits how many probes are in flight at once; the throttle spreads them out in time. The same work still happens, and nothing is skipped.
Rough arithmetic before setting it: the delay applies per probe, so 50 ms
against a /24 on one port is about 13 seconds, and 500 ms is two minutes. If
the number you want makes a sweep longer than the scan interval, the interval is
the knob you actually meant.
Self-update
Section titled “Self-update”| Flag | Environment | Default | Notes |
|---|---|---|---|
--update-base |
NEXTPKI_UPDATE_BASE |
https://sensor.nextpki.com |
Where new releases are fetched from |
--update-interval-secs |
NEXTPKI_UPDATE_INTERVAL_SECS |
86400 |
How often to check |
--no-self-update |
NEXTPKI_NO_SELF_UPDATE |
false |
Turn self-update off entirely |
Set NEXTPKI_NO_SELF_UPDATE=1 where updates go through your own software
distribution - the sensor then never touches its own binary, and you ship new
versions yourself. See staying current.
Scan profiles
Section titled “Scan profiles”The profile sets concurrency, and the default is deliberately timid. A discovery agent that saturates a customer’s firewall state table is a defect.
| Profile | Concurrent connections | When |
|---|---|---|
conservative |
16 | Default. Start here, always |
standard |
64 | After a clean full sweep, if coverage is too slow |
aggressive |
256 | Large flat networks with known-good middleboxes |
A /24 at conservative with eight ports completes in a couple of minutes. The
reason to raise it is a /16, not impatience.
Watch stateful firewalls and IDS: 256 concurrent TLS handshakes from one host is indistinguishable from a scan, because it is one. Tell the security team before raising the profile.
Excludes are absolute
Section titled “Excludes are absolute”--exclude wins over everything. An excluded address is never contacted and never
reported. Use it for:
- Anything fragile - legacy SCADA, medical devices, embedded controllers that fall over on an unexpected handshake.
- Ranges whose hostnames are themselves sensitive, since observed hostnames are transmitted.
- Honeypots and IDS decoys, unless you enjoy the phone call.
Interval
Section titled “Interval”The default hour is a reasonable compromise. Certificate estates change on the scale of days, so a sweep every hour is plenty to keep an inventory current, and frequent enough to notice a new deployment the same working day.
Do not set it very low to get faster change detection. The sensor is not a monitoring probe, and a tight interval multiplies scan traffic without improving the inventory.
Changes you make reach the sensor in a minute, not an hour
Section titled “Changes you make reach the sensor in a minute, not an hour”The scan interval decides how often the sensor looks at your network. It does
not decide how quickly it picks up a change you made in the console. That runs on
its own clock: every 60 seconds by default, adjustable with
--config-heartbeat-secs down to a floor of 15.
This matters most for the settings you change when you want something to stop. Pausing a sensor takes effect within about a minute, and it ends a sweep that is already running - probes in flight finish, no new one starts. A newly added exclude is honoured just as quickly, on the very next probe rather than the next sweep.
The check carries no scan results, so it does not touch “last scanned” in the console; it only keeps “last seen” current, which is what tells you the sensor is alive between sweeps.