ScanopyScanopy

Architecture

Technical overview of Scanopy's system design and components.

Technical overview of Scanopy's system design, components, and data flows.

Components

Server

Purpose: Central hub for data storage, API, and web UI serving

Responsibilities:

  • Store network discovery data in PostgreSQL
  • Serve REST API for daemons and UI
  • Generate topology visualizations
  • Manage user authentication and sessions
  • Orchestrate scheduled discoveries
  • Handle organization and user management
  • Provide real-time updates via Server-Sent Events

Implementation:

  • Language: Rust
  • Framework: Axum (async web framework)
  • Database: PostgreSQL 17 with sqlx
  • Authentication: tower-sessions + OIDC (openidconnect crate)
  • Frontend bundling: Integrated Svelte build in Docker image

Runs as: Docker container (recommended) or standalone binary

Daemon

Purpose: Distributed discovery agent that scans networks and reports findings

Responsibilities:

  • Scan IPv4 addresses on configured subnets
  • Detect open TCP ports
  • Identify services via pattern matching
  • Connect to Docker socket for container discovery
  • Report host interfaces and capabilities
  • Maintain server connection via periodic polling (each poll implicitly updates the daemon's health status)
  • Execute scheduled discovery tasks

Implementation:

  • Language: Rust
  • Network scanning: Custom async TCP scanner with tokio
  • Docker API: bollard crate for Docker socket communication
  • Service detection: Pattern matching engine with 200+ definitions
  • Configuration: JSON file + environment variables + CLI args

Runs as: Docker container (Linux only) or standalone binary (all platforms)

UI

Purpose: Web-based interface for viewing and managing network data

Responsibilities:

  • Display interactive topology diagrams
  • Provide CRUD interfaces for all entities
  • Monitor discovery sessions in real-time
  • Manage users and organizations
  • Configure discovery schedules
  • Export topology visualizations

Implementation:

  • Framework: Svelte 5 + SvelteKit
  • State management: Svelte stores with derived reactivity
  • Visualization: @xyflow/svelte for topology rendering
  • Forms: svelte-forms with custom validation
  • Styling: Tailwind CSS
  • Real-time: Native EventSource for SSE

Runs as: Static files served by the server (bundled in Docker image)

Data Flows

DaemonPoll Mode

DaemonPoll is the default mode. The daemon initiates all connections to the server, making it ideal for daemons behind NAT or firewalls.

Initialization (DaemonPoll)

Runtime Polling (DaemonPoll)

Discovery Flow (DaemonPoll)

  1. User triggers a scan via the UI or API — the server creates a discovery session in Pending state
  2. On its next polling cycle, the daemon receives the pending session as part of the request-work response
  3. The server transitions the session to Starting to prevent re-dispatch to other polls
  4. The daemon executes the discovery (network scan, Docker scan, or self-report depending on type)
  5. The daemon sends periodic progress updates to the server, including discovered entities
  6. The server processes entities immediately — deduplicating and persisting via upsert
  7. The server broadcasts progress to the UI via SSE
  8. The daemon sends a terminal phase (Completed or Failed) to end the session

ServerPoll Mode

ServerPoll mode is for DMZ deployments where the daemon cannot make outbound connections. The server initiates all connections to the daemon. Requires the daemon to be network-accessible from the server.

Initialization (ServerPoll)

Runtime Polling (ServerPoll)

Discovery Flow (ServerPoll)

Mode Comparison

AspectDaemonPollServerPoll
Connection directionDaemon → ServerServer → Daemon
SetupDaemon self-registersAdmin provisions in UI
Firewall requirementsOutbound only from daemonInbound to daemon (port 60073)
Best forNAT/firewall environmentsDMZ deployments
Entity handlingImmediate processingBuffered with confirmation

Discovery Pipeline

Network Scanning

Network scanning runs in three phases:

  1. ARP Discovery — The daemon sends ARP broadcasts across configured subnets to discover active hosts. This is the primary mechanism for finding devices on the local network, returning IP and MAC address pairs.
  2. Deep Scanning — Each discovered host is scanned in detail:
    • TCP and UDP port scanning on configurable port lists
    • DNS reverse lookup for hostname resolution
    • SNMP queries for system information (if credentials are configured)
    • Service detection by matching open ports against 235 service definitions
  3. Grace Period — A brief window after deep scanning completes to catch any late ARP responses. Newly discovered hosts receive a full deep scan before the session completes.

The UI displays real-time progress across all three phases via Server-Sent Events.

Docker Discovery


For implementation details, see the source code.

On this page