Skip to content

Latest commit

 

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Netwatcher

Network device scanner for Proxmox LXC (Debian 13 / Trixie). Scans the local network every 5 minutes for new devices (arp-scan), runs detailed scans (nmap -O -sV) every 6 hours, stores everything in SQLite and provides a web UI for viewing, searching, filtering, exporting and configuration. Newly discovered devices trigger a Gotify notification.

Language: English (German version: README.de.md) — UI supports DE/EN with browser auto-detection and cookie persistence (switch via navbar).

Requirements (in LXC)

  • Debian 13 (Trixie) – Python 3.12+
  • arp-scan, nmap, sudo (container needs CAP_NET_RAW)
  • python3-venv

LXC must allow CAP_NET_RAW, otherwise arp-scan cannot send Layer-2 packets. In the Proxmox container config (/etc/pve/lxc/CTID.conf) ensure no lxc.cap.drop contains net_raw. Unprivileged containers additionally need /dev/net/just_network_access – usually CAP_NET_RAW up to 25 is sufficient.

Installation (automatic)

The installer scripts/install.sh performs all steps automatically:

# as root in LXC
bash scripts/install.sh

The installer asks interactively for:

  • System user (default: netwatcher)
  • Directories (default: /opt/netwatcher)
  • Web UI host/port
  • Admin username and password

Afterwards all systemd units are active and the web UI is reachable.

Non-interactive installation (CI/automation):

INTERACTIVE=0 bash scripts/install.sh

After a code update, only update units + web service:

bash scripts/install.sh --update

Uninstall:

bash scripts/install.sh --uninstall

Manual installation

# as root in LXC
apt update
apt install -y python3-venv python3-pip arp-scan nmap sudo

useradd --system --create-home --home-dir /opt/netwatcher netwatcher
sudo -u netwatcher git clone <repo-url> /opt/netwatcher/app

sudo -u netwatcher bash -lc '
  cd /opt/netwatcher/app
  python3 -m venv .venv
  .venv/bin/pip install -r requirements.txt
'

export NETWATCHER_DB=/opt/netwatcher/data/netwatcher.db
export NETWATCHER_SECRET="$(openssl rand -hex 32)"
mkdir -p /opt/netwatcher/data
chown -R netwatcher:netwatcher /opt/netwatcher/data

sudo -u netwatcher bash -lc "
  export NETWATCHER_DB=$NETWATCHER_DB
  cd /opt/netwatcher/app
  .venv/bin/python -m netwatcher init-db
  .venv/bin/python -m netwatcher add-user admin
"

systemd units (manual)

Templates in scripts/ contain placeholders (__NETWATCHER_USER__ etc.). The install.sh installer fills them automatically. For manual installation:

Placeholder Example
__NETWATCHER_USER__ netwatcher
__NETWATCHER_DIR__ /opt/netwatcher/app
__NETWATCHER_DB__ /opt/netwatcher/data/netwatcher.db
__NETWATCHER_DB_DIR__ /opt/netwatcher/data
__NETWATCHER_BIN__ /opt/netwatcher/app/.venv/bin/python -m netwatcher
__GUNICORN_BIN__ /opt/netwatcher/app/.venv/bin/gunicorn
__NETWATCHER_SECRET__ <Secret from Setup step>
__WEB_BIND__ 0.0.0.0
__WEB_PORT__ 5000
# Replace placeholders via sed (example: SERVICEFILE)
SUD_BIN="/opt/netwatcher/app/.venv/bin/python -m netwatcher"
for f in scripts/netwatcher-*.service; do
  sed -e "s|__NETWATCHER_USER__|netwatcher|g" \
      -e "s|__NETWATCHER_DIR__|/opt/netwatcher/app|g" \
      -e "s|__NETWATCHER_DB__|/opt/netwatcher/data/netwatcher.db|g" \
      -e "s|__NETWATCHER_DB_DIR__|/opt/netwatcher/data|g" \
      -e "s|__NETWATCHER_BIN__|$SUD_BIN|g" \
      -e "s|__GUNICORN_BIN__|/opt/netwatcher/app/.venv/bin/gunicorn|g" \
      -e "s|__NETWATCHER_SECRET__|$NETWATCHER_SECRET|g" \
      -e "s|__WEB_BIND__|0.0.0.0|g" \
      -e "s|__WEB_PORT__|5000|g" \
      $f > /etc/systemd/system/$(basename $f)
done

cp scripts/netwatcher-*.timer /etc/systemd/system/

systemctl daemon-reload
mkdir -p /opt/netwatcher/data
chown -R netwatcher:netwatcher /opt/netwatcher/data
systemctl enable --now netwatcher-web.service
systemctl enable --now netwatcher-scan.timer
systemctl enable --now netwatcher-detail.timer

Usage

  • Web UI: http://<lxc-ip>:5000/
  • Login with the created user
  • Language: auto-detected from browser (Accept-Language), switch via navbar DE/EN, stored in cookie and language config (also used for Gotify/MQTT notifications)
  • Devices: search/filter/sort, show/hide columns, inline editing (name/status/notes/tags)
  • Export: CSV/JSON via buttons in device list
  • Configuration: IP range, interface, scan interval, detail scan every 6h, DNS/mDNS/IPv6/HTTP/TLS/UPnP/SMB, Gotify, OPNsense sync, date format (auto from language)
  • External integrations: arpwatch (/var/lib/arpwatch/arp.dat), LibreNMS REST API and Greenbone report URL; all optional and syncable via configuration
  • LibreNMS and Greenbone are hidden by default. Enable server-side with NETWATCHER_REMOTE_INTEGRATIONS=1 during install or systemd update.
  • "Scan now" / "Detail scan" triggers manual scans
  • Scan profiles: Quick, Detail and Full (all ports) via device list
  • OPNsense Dnsmasq integration: read static DHCP hosts and active leases via API, merge IPv4/IPv6 and match by MAC
  • Manufacturers page with device counts, search, sorting and direct manufacturer filter in device list

CLI commands

python -m netwatcher init-db              # initialize DB
python -m netwatcher add-user <name>      # create web UI user
python -m netwatcher scan                 # run arp scan now (like timer)
python -m netwatcher detail-scan          # nmap detail for all devices
python -m netwatcher cleanup-history      # delete yesterday's history
python -m netwatcher opnsense-sync        # sync OPNsense Dnsmasq hosts
python -m netwatcher profile-scan --profile quick   # top 20 ports
python -m netwatcher profile-scan --profile detail  # OS and services
python -m netwatcher profile-scan --profile full    # all TCP ports
python -m netwatcher integrations-sync              # arpwatch, LibreNMS, Greenbone
python -m netwatcher mqtt-sync                      # publish all devices to MQTT
python -m netwatcher serve                          # Flask dev server (test only)

Tests

.venv/bin/pip install pytest
.venv/bin/python -m pytest tests/ -v

Tests run fully offline (arp-scan fixtures instead of real scans, Gotify endpoint is mocked).

Database schema

See netwatcher/db.py. Tables:

  • devices: all ever found devices (unique by MAC)
  • scan_history: each scan per device + type (arp/detail/offline)
  • config: key/value config (editable in web UI, includes language)
  • users: web UI logins (bcrypt hashes)
  • tags / device_tags: device grouping (many-to-many)

Gotify

In the web UI under Configuration:

  • Gotify Server URL (e.g. https://gotify.example.com)
  • App Token (Gotify app token, not client token!)
  • "Send test message" checks the connection

For new devices, offline devices or new ports a message with IP/MAC/manufacturer is sent (language per language config).

About

Überwachung der Geräte im Netzwerk

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages