Edge scanner (Resilic Edge)
Resilic Edge is a discovery scanner you run yourself: one Docker container on a Raspberry Pi 4/5, a SIMATIC IOT2050 or any Linux Docker host in the control cabinet. It discovers the devices on the machine network (controllers, I/O, gateways, HMIs) and reports device metadata only to Resilic – vendor, type/order number, serial number, firmware. No payloads, no packet captures.
The connection is outbound only (HTTPS to api.resilic.ai). No port has to be opened; the
local status page is reachable on the LAN only and can be switched off.
What this release does
Section titled “What this release does”Enrolment and connectivity (the device shows up in Resilic with status, hardware, version and address), on-site device discovery (the scanner listens on the machine network and sends the standard identify requests engineering tools send too) and continuous reporting to Resilic: every cycle is uploaded, a baseline you accept serves as the reference, and every deviation – new device, missing device, changed firmware, address or name – shows up in Resilic and triggers a notification.
How discovery works
Section titled “How discovery works”Every cycle (default: every 60 minutes, configurable in Resilic) has two phases:
-
Listen (about 45 seconds, sends nothing): ARP, LLDP, mDNS and SSDP – the announcements controllers, switches and HMIs put on the wire all the time anyway.
-
Identify (only in active mode and inside a maintenance window, if one is configured): one PROFINET DCP Identify-All request, one EtherNet/IP ListIdentity request, one mDNS service query and one SSDP search. These are the same read-only broadcasts TIA Portal or PRONETA send when opened – no port scan, no writes, no login attempts. In addition, when the ARP sweep method is on, one ARP request (“who-has”) per address in the allowed range (default: the scanner’s own subnet, at most 1024 addresses, 40 requests per second). Every IPv4 device answers ARP, so this also finds devices that never speak up on their own and support no identify protocol – a server, an HMI panel, a camera, a Modbus gateway. Whatever answers then gets the read-only per-host queries.
-
Ask directly (again only active and inside the window): every device already heard in this cycle and inside the allowed range gets up to six read-only standard requests in turn – SNMP GET of the system group (community
public), OPC UA GetEndpoints (no session, no credentials), Modbus/TCP Read Device Identification (function 43/14), an HTTPGET /with the TLS certificate details, and for Windows devices (HMI tablets, industrial PCs) a NetBIOS name query (nbtstat -A: computer name and workgroup) and an SMB2 Negotiate (the protocol version only, no session, no logon – nothing lands in the device’s security log). One host at a time, at least 250 ms apart, 2 s timeout, backing off on errors. Addresses that stayed silent in this cycle are never touched – there is no port scan.
Allowed range: the default is the scanner’s own subnet. In Resilic you can allow and exclude ranges (CIDR); exclusions always win.
The vendor is derived from the MAC address (bundled OT vendor list, extendable via
/data/oui.csv in IEEE format); station name, type, role, firmware, serial number and OPC UA
security profiles come from the answers themselves. Every attribute carries its source; on
conflict the more reliable one wins (e.g. PROFINET DCP over mDNS over SSDP).
Dry run: http://<device-ip>:8480/api/dry-run shows which packets a cycle with the current
configuration would send – before the first cycle runs. In passive mode nothing is sent.
Scan now on the status page starts a cycle immediately.
Enrol a scanner
Section titled “Enrol a scanner”-
In Resilic, under Settings → Edge scanners, click Download install package. You get a ZIP with
compose.yml(the current signed release, pinned by digest),.env(with an enrolment token valid for 24 hours and exactly once) and instructions. -
Copy the folder to the device and start it:
Terminal window docker compose up -d -
Within a minute the scanner reports in and shows as Online in Resilic.
Prerequisite: a Linux Docker host. The scanner runs on the host network (network_mode: host)
because it has to listen on the machine network itself. That only works with Docker Engine on Linux –
a Raspberry Pi, an IOT2050, a Linux server or a Linux VM with a bridged network adapter. Docker
Desktop on Windows or macOS is not suitable for operation: there the container runs inside its own
VM, does not see the machine network, and the status page is not reachable from outside.
Raspberry Pi OS: the container’s memory limit (mem_limit: 300m) only takes effect once the memory
cgroup is enabled. Append cgroup_enable=memory cgroup_memory=1 to the end of the line in
/boot/firmware/cmdline.txt once and reboot; docker stats then shows memory figures instead of
0B / 0B. Without it the scanner runs the same, just without a hard ceiling.
For a pure connection test on a Windows or Mac PC, replace the line network_mode: host in
compose.yml with
ports: - "8480:8480"The status page is then at http://localhost:8480 and the scanner reports in to Resilic – but
discovery finds nothing in this mode. On a Linux host, TCP port 8480 must be open in the host
firewall if other machines are to reach the status page.
Alternatively, Create token only gives you a token to put into a .env yourself or to enter
on the local status page at http://<device-ip>:8480. The compose file for that ships with every
GitHub release.
Only Owners and Admins (permission edit settings) can create tokens and revoke scanners. Each of these actions appears in the audit log.
Configuration in Resilic
Section titled “Configuration in Resilic”Under Settings → Edge scanners → Configure you set, per scanner:
| Setting | Meaning |
|---|---|
| Mode | Active (default): listen, identify, ask. Passive: listen only, nothing is sent. |
| Cycle | Interval between two cycles (5 minutes to 24 hours; default 60 minutes) – applies while no schedule is set. |
| Schedule | Fixed start times per weekday (device time), e.g. Mon–Fri 02:00 and Sun 03:30. With a schedule, cycles start exactly then; a missed slot (e.g. after a restart) is caught up once. |
| Methods | Which listen, identify and ask methods the scanner uses. Scanners set up before the ARP sweep existed keep their list: tick ARP sweep if silent devices are missing. |
| Allowed / excluded ranges | CIDR ranges for per-host queries. Empty = own subnet. Exclusions win. |
| Purpose | Monitoring (default): watch one network for good, with a baseline and deviations. Commissioning: capture one machine after another on the bench – see Commissioning. |
| Updates | Manual (default): new versions only via “Update now”. Automatic: the scanner applies new versions itself – inside a maintenance window if one is set, never during a cycle. See Updates. |
| Maintenance windows | Weekdays and times (device time) during which sending is allowed. No windows: any time. If a window ends during a cycle, the active phase stops at once and the cycle is marked partial. |
| Spacing / timeout | At least 250 ms between per-host queries and a 2 s timeout – these floors cannot be lowered. |
The scanner picks up saved changes on its next heartbeat (within a minute); the version number shows which state is active on the device. Every change appears in the audit log.
Updates
Section titled “Updates”Every scanner version is a signed image (cosign, SBOM as an attestation). Resilic knows the current version and shows Update available: X.Y.Z in the scanner list as soon as a device runs an older one. Three ways to apply it:
- By hand on the device: download a fresh install bundle (it pins the current version) or change
the
image:line incompose.yml, thendocker compose pull && docker compose up -d. Credentials, configuration and the outbox stay in/data; no re-enrolment. - Update now in Resilic: needs the updater container on the device
(
docker compose --profile updater up -d, once). The scanner learns of the request with its next heartbeat and applies it as soon as no cycle is running; the result then shows in the list. - Automatic (the “Updates” setting in the scanner’s configuration): like 2 without the click – inside a maintenance window if one is set, otherwise at the next idle moment.
The updater container has no network. It talks only to the device’s Docker socket and only ever starts images from the signed Resilic repository, whatever the request file says. It copies the running container’s configuration one to one (capabilities, volumes, environment), starts the new one, checks after ten seconds that it runs, and otherwise restores the old one. Because it sits on the Docker socket, it is deliberately optional.
The local status page
Section titled “The local status page”http://<device-ip>:8480 (LAN only, disable with EDGE_LOCAL_PORT=0) shows, in the Resilic look,
enrolment, hardware, address, the configuration pulled from Resilic and the dry run – the list
of packets the next cycle would send. There you also choose the network interface to scan on
(for devices with two ports), start a cycle with Scan now and see the devices found last. The
page is available in German and English (by browser language, switchable).
Password: on the first visit you set a password (at least 8 characters); after that every
function of the page requires signing in. Repeated wrong attempts lock the page with a growing
wait. Alternatively preset the password with EDGE_LOCAL_PASSWORD in .env. The password is
stored only as a hash on the device; Resilic does not know it.
What you see in Resilic
Section titled “What you see in Resilic”| Column | Meaning |
|---|---|
| Status | Online (heartbeat within the last 3 minutes), Offline or Revoked |
| Hardware / Version | What the scanner reports about itself (e.g. “Raspberry Pi 4 Model B”, v0.1.0) |
| Address | The scanner’s own LAN address – how you find the box in the cabinet |
| Last seen | Time of the last heartbeat |
Commissioning: one machine after another
Section titled “Commissioning: one machine after another”When the scanner is not in a cabinet at the customer but on your test bench, it sees a different machine every week. That is what the purpose Commissioning in the scanner’s configuration is for: such a scanner has no baseline and raises no deviations. You work with captures instead (tab Commissioning):
- Start a capture for a machine in the register – an existing one (product → version → customer / site) or a new one you create right here (product version, customer, site, serial number).
- Let a scan run – “Scan now” on the device, or the next cycle. Every cycle that arrives while the capture is open updates the working list.
- Review: every device with vendor, model, firmware, serial, a suggested role (controller, drive, HMI, I/O, network, camera) and the “part of it” tick. The technician’s laptop or the bench switch stay out. Devices an earlier cycle of the same capture saw but the last one did not are shown greyed – nothing is lost silently.
- Confirm: the last cycle is frozen, the list becomes the machine’s as-built inventory (shown on the machine in the product register), the capture is closed and the scanner is free for the next machine. A machine can be captured again later, say after a retrofit before shipping; the earlier inventory stays readable.
The as-built inventory is the evidence of which controller, drives, cameras and HMIs the machine left with, at which firmware – and the starting point for the field comparison once a scanner sits in the machine’s cabinet.
Identity: what a device is
Section titled “Identity: what a device is”During the review Resilic suggests, for every device, which catalogue product it is – with its source and a match percentage, never as a decision. The sources, in this order:
- Remembered: an identity you confirmed before for the same device fingerprint (PROFINET vendor / device id, EtherNet/IP product code, order number, or vendor|model).
- Device identifier: what the device itself reports – for example the Siemens order number (6ES7 …) in its SNMP system description, from which Resilic also reads the firmware.
- Version SBOM: the component of the product version whose vendor, name, order number or firmware matches.
- Vendor advisory: products from the CSAF advisories of your connected suppliers. When an advisory lists the observed firmware as affected, that is shown on the device with the advisory id and version range; the highest “below X” bound appears as a note that versions below it are listed as affected. Resilic does not turn this into a recommendation – it cites.
- CPE dictionary: the entry in the NVD product dictionary whose identifier vulnerability correlation keys on.
- AI proposal: only for devices none of the other sources places with confidence, and only with your confirmation – “AI drafts, human signs”.
You pick a suggestion, “No identity”, or type name, manufacturer, CPE and order number yourself. Remember makes the next machine with the same part get the suggestion at full match; remembered identities are listed under the tab and can be forgotten. Next to it you map the device to the SBOM component of the product version it is.
Export and write-back
Section titled “Export and write-back”On confirm Resilic writes the as-built inventory back as an SBOM revision of the machine (CycloneDX 1.6, components of type device with manufacturer, firmware, CPE and the observation sources as properties; the product version’s SBOM is referenced as the parent BOM). Every later change to the inventory writes a new revision; all revisions stay downloadable on the machine, and Export CycloneDX delivers the current one. The product version’s SBOM remains the as-designed list – untouched.
Identified devices enter the component registry with the firmware they shipped with. Vulnerability correlation therefore runs per machine on the firmware actually built in: a hit on a controller shows exactly the machines that carry that firmware, not every deployment of the version.
Later, in the field: the as-built inventory as baseline
Section titled “Later, in the field: the as-built inventory as baseline”When a scanner later sits in the machine’s cabinet, nobody has to “accept” a baseline on site: under Devices choose As-built inventory as baseline for the scanner and the machine (product → version → machine with an as-built inventory). The confirmed inventory becomes the scanner’s baseline, the scanner takes the machine’s site, and the version-bearing device is mapped to the machine. From then on every deviation means differs from what we shipped – a missing device, a new device, or a changed firmware on a component. A changed firmware is a high-urgency deviation: it is exactly the per-component difference from the as-built inventory.
Version-bearing component
Section titled “Version-bearing component”On a product version’s SBOM you choose the version-bearing component – typically the PLC or IPC whose firmware constitutes the version. When a machine’s as-built inventory maps a device to that component, the machine’s version in the register counts as verified if the shipped firmware matches the registered version and as drift if it does not – even without a scanner in the field. A later scanner observation takes precedence.
Devices and the product register
Section titled “Devices and the product register”A discovered device can be mapped to a deployment in the product register. Resilic suggests matching entries — by serial number, vendor, product name, firmware and site — and stores the mapping only once you confirm it. A device reporting the serial number the register holds for the machine is the strongest signal. After confirmation Resilic compares the firmware it reads with the registered version on every cycle: if they match, the machine’s version in the register counts as verified; if they differ, a deviation appears that you can accept into the register.
Handover to the operator
Section titled “Handover to the operator”When the machine leaves the factory with the scanner in its cabinet, the scanner changes owner (owner decision, 18 October 2026): the operator owns it and everything it observes from the handover on – in their own Resilic organisation. What the scanner observed before stays your evidence and stays with you.
- Hand over on the scanner creates a one-time handover code (valid 7 days). An open capture has to be confirmed or discarded first.
- The operator redeems the code in their organisation under Edge scanners → Accept handover. The scanner appears there as “Taken over on …”, reports there from now on and keeps its credential – nothing to do on the box. Baseline, site, recipients and portal settings are reset, because they pointed into your organisation; the operator sets them anew.
- You keep read access: under Scanners → Scanners shared by operators you see the latest cycle and the open deviations, read-only. The operator sees that access under Read access to your scanners and can end it at any time.
If the operator has no Resilic organisation of their own, the scanner stays with you: switch on Show findings in the customer portal in the scanner’s configuration, and the operator sees the latest cycle and the open deviations on the portal page of the customer whose site the scanner is installed at. The portal page is reachable by link – give the link to the operator only.
Revoke access
Section titled “Revoke access”Revoke invalidates the scanner’s credential immediately. The device then forgets its enrolment and waits for a new token; data it already reported is kept. Use it when a device is removed, sold or lost.
Security and privacy
Section titled “Security and privacy”- The device holds only a random secret; Resilic stores nothing but a hash of it. A revoke makes a copied file worthless.
- The container runs read-only and without
privileged; of all Linux capabilities it keeps onlyNET_RAWandNET_ADMIN– the minimum needed to listen on layer 2. - The scanner belongs to the tenant that enrolled it. A machine builder operating a device at a customer’s site sees its data in their own tenant; sharing with the operator goes through the existing customer/site relationship, never automatically.
- Default: active, read-only. The targeted per-host queries (SNMP, OPC UA, Modbus, HTTP) go only to devices already heard inside the allowed range, one host at a time, with fixed minimum spacing. A purely passive mode is always available.
- TLS certificates are read, never validated or trusted: the scanner sends nothing confidential; subject, issuer and expiry are inventory data only.