> For the complete documentation index, see [llms.txt](https://docs.layeronecloud.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.layeronecloud.com/network-monitor/setup.md).

# L1 Network Monitor

Source project: `L1 Network Monitor` (migrated from `README.md`). Run commands from the code checkout and directory specified below, not from this documentation repository.

L1 Network Monitor is an operational network-observability system for Proxmox VE 9 clusters. A small Rust sensor runs on every traffic-carrying Proxmox node, aggregates libpcap observations locally, and sends bounded telemetry over outbound HTTPS to a separate Django control plane. Each host uses a revocable, host-scoped API key; the control plane stores only the key hash.

Linux interface counters are the source of truth for total bandwidth; libpcap observations add per-address host, device, application, service-port, and bounded DDoS attribution. Capture loss is reported as coverage rather than hidden by scaling estimates. The dashboard defaults to a rolling one-hour live view of designated uplinks, with separate download and upload series, the WAN's average probe latency as a dotted line and its packet loss as a red one that is drawn only for the minutes that actually lost packets, and the ten busiest current hosts. A host there is one address, so a machine holding several addresses ranks once per address, under the device name it belongs to. Hosts are ranked from both vantage points: a guest bridged straight onto the uplink is seen only there, a machine behind a router only on its bridge, and a flow the node routes itself is counted once. Selecting a six- or 24-hour range ranks the hosts by the bytes they moved over that span, and while live telemetry is not arriving the card falls back to the last day's ranking instead of going blank. Beside that ranking are the busiest applications and, on the Applications page, the busiest Internet destinations over the last 24 hours. The view defaults to outbound Internet use, separates inbound hosted services from internal LAN traffic, and expands each application to its ten busiest destinations and ten busiest devices. Applications remain listed for 24 hours after the last observed outbound traffic on that IP and service port, including replies from hosted services. The application window is independent of chart ranges; inbound traffic and scan results cannot renew it. Internet traffic is counted where it crosses the uplink; LAN observations of the same minute add device names behind routers rather than a second copy of the bytes. A catalog of several hundred well-known service domains names the application, and anything it does not know keeps its port-based label with the destination shown as evidence. Sensors learn destinations from TLS SNI, HTTP Host or CONNECT, and DNS answers, reduce them to registrable domains before spooling, and use a canonical remote IP when no domain evidence exists. The dashboard hover shows the five busiest source/client → destination/service IP pairs, with bytes sent to the service and replies. The Applications page shows the leading pair in its Top connection column. Exact pairs cover the last 24 hours; older sensors fall back to explicitly labeled device attribution. The page exposes the same filters and collection-coverage notices in full. The dashboard refreshes that database-backed ranking every five minutes while its live readings continue at their faster cadence. Each WAN in the status sidebar carries its own live throughput above the latency block, drawn as five minutes of five-second samples taken from the capture domains on that interface. WAN discovery is shared by every feature: assigned public IPs identify WANs, a default route leaving through an interface identifies one even behind a NAT gateway, and bridge topology selects the physical, bond, or VLAN uplink to capture. A bridge such as `vmbr0` that holds the address and the route is therefore captured and counted on its port `nic2`, whose counters include the guests' forwarded traffic that the bridge device's own counters omit; the console names both. Bonds are captured once, not again on their member NICs. Non-overlapping infrastructure bridges remain LAN; SDN and per-VM plumbing cannot become WAN from a saved role or a manual DDoS target. Discovered hosts are named rather than addressed: a matched billing VM name, a manufacturer resolved from the MAC prefix, or an operator's own label, with the MAC always carried in its own column. VLAN tags are detected from traffic, and hosts are learned passively from observed MAC activity on both LAN and WAN captures, so logical segment and customer-managed CIDR configuration are not required. WAN-bound traffic is attributed to WAN rather than being added again to internal LAN totals. A sensor that stops reporting is escalated by telephone: every on-call number is called on a repeating interval until somebody answers and presses 1. Texting can accompany the calls, with one message when an alert opens and one when the sensor recovers, and a reply of 1 or ALL acknowledges. A DDoS attack whose estimated traffic reaches a configurable rate, five gigabits per second by default, is escalated the same way. Twilio credentials, on-call numbers, thresholds, and timings are managed from the web console, and the auth token is stored encrypted. WAN DDoS monitoring combines conservative absolute limits with a learned per-target baseline. It detects volumetric, SYN, UDP/reflection, ICMP, fragmentation, TCP RST, and ACK-only floods, correlates duplicate observations from sensors at the same site, and separates suspected attack traffic from other observed inbound traffic on synchronized bandwidth and packet-rate charts. Operators choose the protected destinations: usable interface addresses are added automatically as exact hosts, and routed or bridged ranges can be added explicitly. When packet evidence is enabled, the sensor keeps a short protected rolling buffer and uploads 256-byte-truncated PCAP chunks for seven-day forensic retention in private object storage. **LayerOne Aegis** connects these correlated incidents and customer traffic to Pulsar Operations through the existing encrypted Admin API credential. Exact target IPs and mapped clusters identify customer resources, with attack status, recovery, and customer-configurable alerts in **Networking**. Client dashboards show their own observed inbound/outbound bandwidth, combined packets per second, attributed applications, expected traffic and suspected DDoS traffic. Assignment boundaries exclude previous owners' history, and site or shared-device totals are never exported as customer traffic. The separately supervised sender retries delivery and preserves sensor observation times; missing telemetry is reported as stale rather than as a confirmed recovery. See the [Aegis setup instructions](https://docs.layeronecloud.com/network-monitor/operations/aegis).

Continuous active port discovery runs on each hypervisor against only its running guests from the existing Pulsar device inventory. Hourly scans request the top 100 TCP and UDP ports; daily and customer-requested scans request all ports through the WAN's IP-owning interface (`vmbr0` when appropriate), then identify services on confirmed open ports. Monitor and Aegis Applications group these findings with observed applications and show scan freshness and partial coverage independently of traffic measurements. Each active host scan is isolated from normal telemetry and other scans with a one-logical-CPU quota and 512 MiB memory limit. Eight daily full-scan slots, two customer full-scan slots and two hourly common-port slots can run together, with automatic host-pressure backoff.

Applications flag **Potential Vulnerabilities** by comparing confidently detected software versions with cached NIST NVD advisories. Counts distinguish active, ignored, stale and unassessed evidence; operators and customers can ignore and restore individual findings without hiding new CVEs. Background refreshes update advisory matches daily, even when the detected version is unchanged. The initial product mappings are deliberately explicit; unknown products, ambiguous versions and platform-dependent matches are not declared safe. Version banners cannot establish whether vendor security backports are installed.

Aegis customers can request a priority port scan per running device after an update. Requests use their own two full-scan slots, keep per-host resource limits, and have a ten-minute cooldown. Aegis Settings lets customers disable their views and alerts while clearly explaining that network security monitoring and DDoS protection continue. Priority requests require sensor **0.1.24**, its updated systemd unit, and the coordinated Operations and Monitor migrations for the separate pools. **Agents & Settings → Host port scans → Scan schedule** sets the daily full-scan time, defaulting to 10:00 PM America/New\_York. Common scans become eligible hourly; full scans once per scheduled local day. Active scans run to completion without a per-host time limit and never overlap another scan of the same IP. Reserved customer slots do not preempt an existing scan or pending result for that IP.

Operations now owns the manual and automatic full-scan queue. Monitor submits daily intents and polls/claims immutable Operations IDs through its existing Aegis worker. A claim stays Queued; actual Nmap spawn and supervised heartbeats report Running. The two Operations Jobs tabs retain manual and automatic full attempts independently of newer hourly observations. Completed sweeps may have filtered or unanswered ports: those stay uncertain without making successful execution Partial or erasing older positive port evidence. See the [scan lifecycle contract and rollout](https://docs.layeronecloud.com/network-monitor/scan-lifecycle).

## Repository layout <a href="#repository-layout" id="repository-layout"></a>

* `agent/` — Rust/libpcap Proxmox sensor and local durable spool.
* `server/` — Django ASGI control plane, ingestion worker, APIs, and UI.
* `proto/` — versioned sensor-to-server telemetry contract.
* `deploy/` — local Docker Compose stack and Proxmox systemd packaging.
* `Dockerfile` and `.railway/railway.ts` — Linux agent/web build and Railway project IaC.
* `docs/` — pointer to the developer docs; the reference itself lives at <https://docs.layeronecloud.com>.

## Development <a href="#development" id="development"></a>

The server requires Python 3.13 and PostgreSQL in production. SQLite and an in-memory channel layer are supported only by the test settings.

```sh
python3 -m venv .venv
.venv/bin/pip install -r server/requirements-dev.txt
.venv/bin/python -m grpc_tools.protoc \
  -I proto --python_out=server/monitoring/proto proto/telemetry.proto
.venv/bin/python server/manage.py test monitoring --settings=l1monitor.test_settings
node --test server/monitoring/tests/*.test.js
```

The sensor requires Rust, libpcap development headers, and pkg-config:

```sh
cargo test --manifest-path agent/Cargo.toml
```

How uploads are committed, how many worker processes commit them, and how long the application ranking is cached are console settings under **Agents & Settings > Telemetry processing**, not environment variables.

Monitoring history is kept for three months and DDoS attack records for a year, after which the hourly maintenance job deletes them; see `server/monitoring/retention.py` and <https://docs.layeronecloud.com/network-monitor/operations/retention-and-memory>.

Start the development control plane with:

```sh
cp .env.example .env
docker compose -f deploy/compose.yaml up --build
```

See <https://docs.layeronecloud.com/network-monitor/railway> to deploy the control plane and <https://docs.layeronecloud.com/network-monitor/operations/central-server> before installing a sensor on a Proxmox node.

The deployed web service exposes a fixed allowlist of credential-free agent artifacts under `/downloads/agent/`. Creating a site or agent produces a copyable, host-scoped install command; no key file upload is required.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.layeronecloud.com/network-monitor/setup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
