Repository: sharifndlovu123/iot_monitoring · Django 5, Celery, PostgreSQL, Redis, Docker Get it:
git clone https://github.com/sharifndlovu123/iot_monitoring.git && cd iot_monitoringthen follow the README (the repo shipsstart.shandstop.sh; the README text still mentions./build.sh). Linux (Debian/Ubuntu) with Docker and sudo. Scan only networks you own.
NetPulse is a Django platform that discovers, monitors and tracks devices on a local network, combining scanning tools with background tasks for a live view of what is connected. It is a good example of running network tools without root, and of a Django + Celery + Redis stack. Source: the iot_monitoring repo.
Tools at a glance
| Tool | Role |
|---|---|
| Django 5 | Web app, auth, admin |
| PostgreSQL (or SQLite for dev) | Device and scan data |
| Celery + Redis | Background scanning and scheduled monitoring (worker + beat) |
| HTMX + Bootstrap 5 | Live-updating UI without a SPA |
| arp-scan, nmap, ping | Discovery and status checks |
| Docker Compose | PostgreSQL, Redis (and the whole stack in the "complete" option) |
setcap |
Gives scanners raw-socket capability without root |
What It Does
- Device management: inventory with MAC and IP tracking
- Network scanning: ARP scan, nmap and ping discovery
- Live dashboard: device status with alerts
- Camera profiles: IP cameras with RTSP / ONVIF details
- Reports: uptime, latency and inventory history
- Roles: Admin and Viewer permissions
flowchart LR
B[Celery beat: schedules] --> W[Celery worker: scan task]
W --> S[arp-scan / nmap / ping]
S --> DB[(PostgreSQL: devices, scans, status)]
DB --> D[Django views + HTMX dashboard]
W --> R[(Redis: broker)]
B --> R
Layout: one Django app per concern (accounts, cameras, dashboard, devices...), each with models, views, URLs, admin and tests.
How the Scans Work
| Method | What it does | Layer |
|---|---|---|
| ARP scan | Broadcasts "who has this IP?" on the local subnet; every live host answers with its MAC | Layer 2, LAN only, very reliable |
| Ping sweep | ICMP echo to each address | Layer 3, some hosts block it |
| nmap | Host discovery, port scan, service and OS detection | Layers 3-7 |
$ sudo arp-scan --localnet
$ nmap -sn 192.168.1.0/24 # host discovery only, no port scan
$ nmap -sV -p 1-1024 192.168.1.20 # service versions on one host
ARP and nmap theory are in Network Troubleshooting, Network Devices and Switching and VLANs. Only scan networks you own or have permission to scan.
Raw Sockets Without Root: Linux Capabilities
Scanners need raw sockets (craft their own packets). Normally that needs root, but running a whole web app as root is dangerous. Linux capabilities split root's powers into small pieces.
$ sudo setcap cap_net_raw,cap_net_admin+eip /usr/bin/nmap
$ sudo setcap cap_net_raw+ep /usr/sbin/arp-scan
$ getcap /usr/bin/nmap # list the capability on a file
$ sudo setcap -r /usr/bin/nmap # remove it
| Capability | Allows |
|---|---|
CAP_NET_RAW |
Raw and packet sockets (ARP, ICMP, custom packets) |
CAP_NET_ADMIN |
Network configuration, some scan modes |
CAP_NET_BIND_SERVICE |
Bind to ports below 1024 |
Flags: e effective, p permitted, i inheritable. Granting this to a Python interpreter (so Celery tasks can use raw sockets) is powerful: anything running under that Python gets the capability, so keep the environment tightly scoped and avoid untrusted code. A safer pattern is a small helper binary or container that has the capability and nothing else.
The Setup Script Idea
A single setup script (start.sh in the repo; the README refers to it as build.sh) that is safe to re-run: it checks what already exists and skips straight to starting services on later runs.
- Install system dependencies (
arp-scan,nmap) and grant capabilities - Install Docker if missing
- Create a virtualenv and install requirements
- Copy
.env.exampleto.env - Start PostgreSQL and Redis containers (2. Docker Compose)
- Run migrations, optionally create a superuser
- Start Celery worker and beat
- Launch Django on port 8000
stop.sh shuts everything down; logs go to logs/celery_worker.log, logs/celery_beat.log and docker compose logs -f.
Lessons
- Celery beat + worker is the standard way to run recurring jobs in Django; keep tasks short and idempotent
- HTMX gives live dashboards with server-rendered HTML: poll or push partial updates
- Separate concerns into Django apps and give each its own tests
- Least privilege: capabilities instead of root
- Make setup repeatable: scripts that detect existing state
- Ethics and safety: scanning tools are dual-use, so document that they are for networks you own
- See also Siteward Web Security Scanner for a scanner built around a strict "own sites only" rule, and Network Security
Build Your Own Scanner: Concurrency Compared
A companion repo, custom_port_scanner, implements a TCP port scanner in Python three ways to compare I/O-bound concurrency:
| Script | Approach |
|---|---|
main.py |
Sequential, one connection at a time |
concurrent_future.py |
ThreadPoolExecutor with 500 worker threads |
async_scanner.py |
asyncio with a Semaphore(500) capping concurrent connections |
Scanning thousands of ports is waiting on the network, so threads and asyncio finish far faster than the sequential version. Use it only on hosts you own.
A different example of a small ops tool is server_performance_stats: a shell script that prints memory, CPU and disk usage once or on a 5 second refresh, also packaged as a multi-stage Docker image.