Self-hosted OT inventory with automatic discovery found here OTserver Otter repository
Native OT discovery · Quality-aware inventory · Site-scoped access · Immutable history
Quick start · How it works · Imports · Otter · Development
OTserver provides a trustworthy industrial inventory. Automatic discovery lives in the separate OTserver Otter repository: a cross-platform Rust CLI built specifically for identifying industrial devices through fixed, read-only protocol requests. It collects structured evidence—not just a flat host list—and exports observations, interfaces, ports, and topology through a strict versioned contract understood directly by the manager.
OTserver turns that evidence into a site-scoped inventory with provenance-aware field merging, flexible hierarchies, role-based access, search, and a complete audit trail.
- OTserver Otter — Discover devices on Windows and Linux using native ARP, PROFINET DCP, S7, EtherNet/IP, BACnet, Omron FINS, Niagara Fox, DNP3, IEC 61850, OPC UA, SNMP, and LLDP requests.
- Rich discovery evidence — Preserve per-protocol observations, field quality, interfaces, ports, topology links, warnings, and partial failures in a validated JSON contract.
- OT inventory — Automatically track vendor, model, firmware, protocols, ownership, location, status, criticality, and custom fields.
- Flexible site hierarchy — Model regions, plants, areas, lines, cells, or any structure your organization uses.
- Scoped access — Grant read-only or read/write access to a site and all its descendants. A protected Admin role retains unrestricted access.
- Discovery imports — Ingest Siemens PRONETA XML, Nmap XML, and OTserver Otter JSON into a selected site.
- Reliable correlation — Assets are identified only by normalized MAC address, never by a changeable IP address or device name.
- Evidence-aware merging — Higher-quality discoveries can improve lower-quality data while human edits remain authoritative. Protocol evidence is combined across sources.
- Search and filters — Use the graphical filter builder or a supported Lucene query syntax for precise inventory searches.
- Traceable history — Retain source observations and topology links alongside an immutable, secret-redacting audit log.
- Passive vulnerability lookup — Match recorded vendor, product, and version data against local CISA KEV and NVD catalogs without probing the device.
Deploy the prebuilt image from GitHub Container Registry:
ghcr.io/ruveydac/otserver:latest. Release images also have version tags (X.Y.Z and
X.Y); use an exact version tag for a pinned deployment.
With Docker Engine and Compose installed, create a deployment directory containing this
compose.yaml:
services:
otserver:
image: ghcr.io/ruveydac/otserver:latest
restart: unless-stopped
ports:
- '3000:3000'
environment:
DATABASE_URL: mongodb://mongo:27017/otserver
OTSERVER_SECRET: ${OTSERVER_SECRET:?Set OTSERVER_SECRET in .env}
volumes:
- import-files:/app/import-files
depends_on:
- mongo
mongo:
image: mongo:8
restart: unless-stopped
volumes:
- data:/data/db
volumes:
data:
import-files:Create a .env file beside it with a long random secret, and keep that secret across restarts:
OTSERVER_SECRET=replace-with-a-long-random-secretPull the images and start the application and MongoDB:
docker compose pull
docker compose up -dOpen http://localhost:3000/admin and create the first administrator account. The named volumes persist database data and uploaded import files.
To upgrade, back up those volumes, update the image tag if pinned, then run
docker compose pull && docker compose up -d again.
Requirements: Node.js 20.9+, pnpm 9–11, and MongoDB.
cp .env.example .env
# Set DATABASE_URL and replace OTSERVER_SECRET with a long random value.
pnpm install
pnpm devThen open http://localhost:3000/admin. The first account receives the protected Admin role.
For container-based development, the repository's docker-compose.yml runs the source with
pnpm dev: prepare .env as above and run docker compose up from the repository root.
- Create your hierarchy under Sites. Use any site types and nesting depth that fit the plant.
- Add assets manually, or open Imports → Create New and select a discovery source.
- Review created, updated, skipped, and unresolved records on the completed import.
- Search the inventory or open an asset to inspect its details, observations, topology, and history.
Every asset and import belongs to a site. During import, the application normalizes each MAC address to uppercase colon-separated form and uses it as the sole identity key. Records without a usable MAC address are skipped rather than attached to the wrong device.
Field values are merged in this order:
human > high > medium > low
Empty values can always be filled. Equal-quality evidence may replace changed values, stronger evidence may replace weaker values, and weaker evidence cannot overwrite stronger data. Manual edits are recorded as human provenance and survive future imports.
OTserver downloads the CISA Known Exploited Vulnerabilities catalog, NVD JSON 2.0 feeds, the
CERT@VDE CSAF 2.0 aggregator, CISA's OT and IT CSAF ROLIE feeds, and the ICS Advisory Project master
CSV in the background when the application starts. Each start first checks when the catalogs were
last pulled and downloads nothing until they are seven days old, so restarts are cheap. Set
OTSERVER_VULNERABILITY_FEEDS=off for an air-gapped installation.
The first import is the expensive one: NVD publishes one file per year from 2002 onward, roughly 600 MB compressed and a dozen minutes of work, with a peak heap near 880 MB for the largest year. Each year is recorded as it lands, so an interrupted import resumes where it stopped instead of starting over.
Assets store only a derived vulnerability count. A CVE is counted only when its NVD or CSAF vendor and product match the recorded asset data and the asset reports a version satisfying the affected exact version or range. CISA KEV enriches matching records with known-exploitation information and the ICS Advisory Project adds CISA ICS advisory identifiers, critical-infrastructure sectors, product distribution, and vendor headquarters; neither can create a count on its own because neither carries affected-version constraints.
The asset detail view lists the five most severe matches — known-exploited first, then highest CVSS — and links to a paginated subview holding every match plus its evidence. Results are unvalidated metadata matches, not evidence that the device is vulnerable. OTserver does not run active vulnerability checks.
For a GUI smoke test, upload tests/otserver_otter_files/OTserver-Otter-known-vulnerability.json
under Imports as an OTserver Otter file. It creates a demo Siemens S7-1500 CPU with firmware
V2.8.0, which matches NVD CVE-2020-15782 while the catalog is loaded.
| Source | Input | Default quality | Best for |
|---|---|---|---|
| OTserver Otter | Schema-version-2 JSON | Observation-specific | Native discovery with observations, interfaces, and topology |
| Siemens PRONETA | Topology XML | High | Siemens-oriented discovery and topology exports |
| Nmap | XML produced with -oX |
Medium | Existing Nmap-based discovery workflows |
Import files are treated as untrusted input: parsers enforce size and structure limits, tolerate
optional vendor data, and report malformed or uncorrelatable observations as warnings. The canonical
wire contract is pinned through the otserver-otter submodule at
otserver-otter/contracts/otserver-scan-v2.schema.json.
Example searches:
vendor:Siemens AND status:online
protocol:profinet AND criticality:critical
site:"Plant 1" AND type:plc
lastseen:[2026-01-01 TO *]
Download the scanner for your platform from the OTserver Otter releases page.
Otter is not a wrapper around a general-purpose scanning engine. Its discovery, protocol framing, response validation, correlation, and export contract are implemented together for this inventory workflow.
- Native protocol identity — Uses fixed queries designed to retrieve device identity without configuration changes, vulnerability scripts, or exploit behavior.
- Evidence-preserving output — Keeps protocol observations and raw source data alongside normalized devices instead of collapsing a scan into one guessed record.
- Topology-aware collection — Carries LLDP, SNMP, and PROFINET link evidence, network interfaces, and ports into OTserver.
- Quality-aware by design — Each observation reaches the importer with its source quality, so stronger evidence improves the inventory without overwriting human edits.
- Predictable failure handling — Produces valid partial results with warnings when individual probes fail, while malformed and unsolicited responses are rejected.
Otter requires --ack-authorized before a scan. Linux uses AF_PACKET raw sockets and needs
root or CAP_NET_RAW; Windows 10+ uses native Win32 IP Helper, a separately installed Npcap for
active PROFINET DCP, and Packet Monitor (pktmon) as a passive fallback.
otserver-otter doctor
sudo otserver-otter scan \
--target 192.168.1.0/24 \
--interface eth0 \
--source-mac 00:11:22:33:44:55 \
--output scan.otserver.json \
--ack-authorizedOnly scan networks you own or are authorized to assess. Otter does not perform configuration writes, SNMP SET, DCP Set, DNP3 writes, operates, class assignment, freezes, or restarts, brute force, exploits, vulnerability scripts, or Modbus requests.
Users can enable a Payload API key on their account. With an OTserver URL, site ID, and that key in
the Otter environment or executable-adjacent otter.json, Otter can send its completed
JSON directly to the existing REST importer with the user's current site permissions. The local
scan file is retained.
OTserver Otter, its platform guide, contract, tests, and interoperability lab are maintained in the
separate otserver-otter repository.
- Collection access rules enforce site permissions on the server; hiding an admin view is never the security boundary.
- Read and write permissions inherit through every descendant of the selected site.
- The protected Admin role is created automatically and cannot be renamed or deleted.
- All registered collections are audited for creates, updates, deletes, and authentication events.
- Audit entries are immutable and redact fields resembling passwords, secrets, tokens, hashes, or sessions.
- Otter SNMP and OPC UA settings, including credentials, live in executable-adjacent
otter.jsonand are never included in logs or scan exports.
| Layer | Technology |
|---|---|
| Application | Next.js 16, React 19, TypeScript |
| Admin and API | OTserver, built on Payload CMS 3 |
| Database | MongoDB |
| Search | Lucene subset translated to Payload queries |
| Otter | Rust, native Windows and Linux capture |
| Validation | Vitest integration tests |
src/collections/ OTserver collections, hooks, and domain rules
src/access/ Shared site-scoped authorization
src/importers/ PRONETA, Nmap, Otter parsers, and quality merging
src/search/ Lucene query translation and graphical-filter integration
src/vulnerabilities/ Feed synchronization, CPE parsing, and passive matching
src/components/ OTserver admin views, branding, and fields
otserver-otter/ Pinned scanner repository and canonical export contract
tests/int/ Application and importer integration tests
Run the smallest relevant check while working, then the full application suite:
pnpm test
pnpm lint
pnpm buildCoverage is enforced at 90% for the application:
pnpm test:coverageRegenerate OTserver's Payload artifacts after schema or admin component changes:
pnpm generate:types
pnpm generate:importmapOTserver and OTserver Otter are dual-licensed:
The open-source core will remain open source: the scanner, all detection needed to find assets and device capabilities, and the base asset-management interface features. Enterprise offerings may add optional proprietary add-ons, such as SSO integrations or customized dashboards; they do not replace or restrict the open-source core.
- Open Source (GNU AGPLv3): available under the GNU Affero General Public License v3.
- Commercial License: available for enterprises, SaaS providers, or organizations integrating OTserver into their systems.
For a commercial license, custom SLA support, enterprise features, or help choosing the right license, visit otserver.org/enterprise.
