NetAlertX on AWS User Guide
Overview
This image runs NetAlertX 26.7.1 on Ubuntu 24.04 LTS. NetAlertX (the project formerly known as Pi.Alert) is an open source network presence scanner and intrusion detector. It sweeps the subnet it is attached to on a schedule, keeps an inventory of every device it has ever seen, records a presence timeline for each one, and raises an alert when a new device appears or a known device stops answering.
It answers a question most networks cannot answer honestly: what is actually on this network right now, and what changed?
What is included:
- NetAlertX 26.7.1, installed from the pinned upstream source tree, with its Python scanning and API server and its PHP web interface
- nginx on port
80as the authentication gate, with a password generated uniquely on your instance's first boot - SQLite as the device inventory and presence store
- The scanner toolchain:
fping,nmap,arp-scan,dnsutils,nbtscan,avahi-utils,traceroute,mtr - A scan scope automatically limited to your instance's own subnet on first boot
How this image is secured
NetAlertX upstream ships with its login switched off by default, and when you switch it on it hashes with unsalted SHA256 against a password published in its own documentation. Its web interface is also the control plane for a tool that scans your network. That is a reasonable default for a device on a trusted home LAN. It is not a reasonable default for an instance with a public IP address.
So this image does not rely on it:
- nginx is the authentication gate. Every page requires a username and password that was generated on your instance, on its first boot, and written to a file only
rootcan read. Nothing in the image knows it, and no two instances share one. - The scanner API is bound to
127.0.0.1. The Python API that drives the interface listens on the loopback address only, so the authentication gate cannot be bypassed by reaching the API port directly. nginx reverse proxies the interface's API calls to it internally. - The published default password is removed. The upstream default is scrubbed from the image, and the appliance refuses to start if a placeholder credential is ever detected.
- The image ships no usable credential. Before first boot the authentication file authenticates nobody. Your unique credential is created on first boot.
A note on what this product does
NetAlertX scans networks. This image is configured to scan only the subnet your instance is attached to, resolved from the instance's own network interface on first boot. It never ships pointed at a wider network. Widening the scan is an explicit choice, and you must only ever scan networks you own or are authorised to scan. See Scanning scope and authorisation.
Prerequisites
Before you deploy this image you need:
- An AWS account with permission to launch EC2 instances from the AWS Marketplace
- An EC2 key pair for SSH access
- A security group allowing inbound TCP 22 (SSH) and TCP 80 (the dashboard) from the addresses you will connect from
- The recommended instance type is m5.large; NetAlertX runs comfortably on a general purpose instance
Step 1 - Launch from the AWS Marketplace
- Open the product page in the AWS Marketplace and choose Continue to Subscribe, then Continue to Configuration and Continue to Launch.
- Choose your instance type (m5.large recommended), your VPC and subnet, and your key pair.
- Under Security Group Settings, select or create a security group that allows inbound TCP 22 and TCP 80 from your own address.
- Choose Launch.
Step 2 - Launch from the AWS CLI
You can also launch the image with the CLI. Create a security group that allows SSH and the dashboard from your own public IP, then launch the instance:
# Restrict both ports to YOUR public IP, not 0.0.0.0/0
MYIP=$(curl -s https://checkip.amazonaws.com)/32
aws ec2 create-security-group \
--group-name netalertx-sg \
--description "NetAlertX dashboard + SSH"
aws ec2 authorize-security-group-ingress \
--group-name netalertx-sg --protocol tcp --port 22 --cidr "$MYIP"
aws ec2 authorize-security-group-ingress \
--group-name netalertx-sg --protocol tcp --port 80 --cidr "$MYIP"
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-groups netalertx-sg
Replace <ami-id> with the AMI id shown on the Marketplace launch page for your Region, and <your-key-pair> with your key pair name.
Step 3 - Connect to your instance
Connect over SSH using your key pair. The login user depends on the OS variant you launched:
| OS variant | SSH user |
|---|---|
| Ubuntu 24.04 LTS | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Replace <public-ip> with the public IPv4 address of your instance from the EC2 console.
Step 4 - Confirm the services are running
NetAlertX runs as four systemd units: a first-boot unit that generates your credentials, the NetAlertX scanner and API server, nginx (the authentication gate), and PHP-FPM (the web interface). Confirm the three serving units are active:
systemctl is-active netalertx.service nginx.service php8.3-fpm.service
active
active
active
Confirm that nginx is the public front door on port 80 and that the scanner API is bound to loopback only, where it cannot be reached from outside:
sudo ss -tlnp '( sport = :80 or sport = :20212 )'
State Local Address:Port
LISTEN 127.0.0.1:20212 # the scanner API - loopback only
LISTEN 0.0.0.0:80 # nginx - the authentication gate
LISTEN [::]:80
The API on 20212 is bound to 127.0.0.1, so it is only reachable through nginx, behind your password.
Step 5 - Retrieve your per-instance password
Your instance generated its own admin password on first boot and wrote it, with the API token, to a root-only file. Read it:
sudo cat /root/netalertx-credentials.txt
The file looks like this (your values are unique to your instance):
netalertx_url=http://<public-ip>/
netalertx_admin_user=admin
netalertx_admin_password=<a 28-character password unique to your instance>
netalertx_api_token=<a bearer token unique to your instance>
The username is admin and the password is the value of netalertx_admin_password. Keep this file secret; it is the only place the password exists.
Step 6 - Confirm the gate is protecting the interface
Prove the authentication gate works, without ever printing the password. First, an anonymous request to the interface is refused:
curl -s -o /dev/null -w 'no auth: HTTP %{http_code}\n' http://localhost/devices.php
no auth: HTTP 401
The health probe is intentionally anonymous, so a load balancer can check liveness without a credential:
curl -s -o /dev/null -w 'healthz: HTTP %{http_code}\n' http://localhost/healthz
healthz: HTTP 200
Now the same interface request with your instance's credential succeeds. This proves the credential works without echoing it:
curl -s -o /dev/null -w 'with auth: HTTP %{http_code}\n' \
-u "admin:<admin-password>" http://localhost/devices.php
with auth: HTTP 200
Step 7 - Confirm the scan scope
This image scans only the subnet your instance is attached to, resolved from its own interface on first boot. Confirm the configured scope:
grep '^SCAN_SUBNETS=' /app/config/app.conf
SCAN_SUBNETS=['172.31.80.0/20 --interface=ens5']
The value is your instance's own subnet in CIDR form, pinned to its primary interface. The image never ships pointed at a network you did not deploy it into.
Step 8 - Open the dashboard
In a browser, open http://<public-ip>/ and sign in with admin and your per-instance password. The dashboard opens on your device inventory: a count of what is connected, down, offline, new and favourited; a presence chart for the last 24 hours; and the full device list.

Step 9 - Review the device inventory
Each row in the inventory is a device NetAlertX has seen, keyed on its hardware (MAC) address so it stays stable even when addresses are handed out dynamically. The Status column shows whether a device is online, down, offline or newly seen, and the list enriches each device with a type, a vendor and its last known address. Use the left-hand navigation to filter to New devices, Down or Favorites.
Step 10 - Inspect a device
Click any device to open its detail view. It shows the device's identity (name, owner, type, vendor, MAC and last IP), its notification settings, its network relationships, and a session and presence history. From here you can name a device, mark it a favourite, or enable a down alert.

Step 11 - Review the presence timeline
The Monitoring - Presence view is where NetAlertX earns its name. It plots when each device was present over a day, week, month or year, so you can see at a glance which devices are always on, which come and go, and when something first appeared.

Step 12 - Review events and alerts
The Monitoring - Events view is the running log of everything that changed: a device connecting, a device disconnecting, and a New Device the moment it is first seen. This is the intrusion-detection surface of the product: an unfamiliar device joining the network is recorded here the instant it appears, and can be wired to a notification.

Step 13 - Review the scanners and settings
The Settings view shows the enabled scanner plugins and their schedules, plus the core configuration. This image loads the ICMP status check for presence detection (see the note below on why ICMP rather than ARP), together with the naming plugins that resolve device names and vendors.

Why this image scans with ICMP rather than ARP
NetAlertX's upstream default scanner is arp-scan. On a normal LAN that is the best choice, because every device answers ARP with its own unique hardware address. On a cloud virtual network it is the wrong choice: the software-defined network answers ARP for every address with a single synthetic hardware address, so every device would collapse into one row and the inventory would be silently, fundamentally wrong.
This image therefore uses NetAlertX's own mechanism for networks where real hardware addresses are not visible: the ICMP scanner with synthetic per-address identifiers. Each responding address gets its own stable, clearly-synthetic identifier, so the inventory and presence timeline are correct on a cloud subnet. No scanning, detection or alerting logic is changed; only the scanner selection.
Step 14 - Widen or change the scan scope
To scan a different or wider network, edit SCAN_SUBNETS in Settings - Core (or in /app/config/app.conf) and restart the service. For example, to add a second subnet:
SCAN_SUBNETS=['172.31.80.0/20 --interface=ens5', '10.0.5.0/24 --interface=ens5']
sudo systemctl restart netalertx.service
Only scan networks you own or are authorised to scan. In AWS, ensure any subnet you point NetAlertX at is one you are permitted to probe, and that your security groups and routing allow ICMP to reach it.
Step 15 - Use the API
The scanner exposes a GraphQL API, authenticated by your instance's bearer token. It is reachable through nginx at /server/graphql. This query returns the number of devices in the inventory and proves the token works, without printing the token:
curl -s -o /dev/null -w 'graphql: HTTP %{http_code}\n' \
-X POST -H 'Content-Type: application/json' \
-H "Authorization: Bearer <api-token>" \
--data '{"query":"{ devices { devMac } }"}' \
http://localhost/server/graphql
graphql: HTTP 200
Without a token the same request is refused, which confirms the API is not an anonymous surface:
curl -s -o /dev/null -w 'graphql (no token): HTTP %{http_code}\n' \
-X POST -H 'Content-Type: application/json' \
--data '{"query":"{ devices { devMac } }"}' \
http://localhost/server/graphql
graphql (no token): HTTP 401
Scanning scope and authorisation
NetAlertX is a network scanner. You must only scan networks that you own or are explicitly authorised to scan. Unauthorised network scanning may breach the AWS Acceptable Use Policy and local law.
This image ships scoped to your instance's own subnet precisely so that its first scan cannot reach beyond the network you deployed it into. If you widen SCAN_SUBNETS, you are taking responsibility for ensuring you are authorised to scan every address in the new scope.
Security
- Every page is behind the nginx credential generated uniquely on your instance's first boot and stored only in
/root/netalertx-credentials.txt. - The scanner API is bound to
127.0.0.1, so the authentication gate cannot be bypassed. - Restrict the security group to the addresses that need SSH (22) and the dashboard (80). Do not open port 80 to
0.0.0.0/0unless you intend the dashboard to be internet-facing behind its credential. - Put TLS in front for production: terminate HTTPS at an Application Load Balancer or a reverse proxy so the credential is never sent in clear text.
- Rotate the credential by regenerating the htpasswd entry if you ever need to; the file is at
/etc/nginx/.netalertx.htpasswd.
Maintenance
- Operating system updates are delivered by Ubuntu's unattended-upgrades, enabled on the image.
- NetAlertX is pinned to the reviewed upstream release
v26.7.1. To move to a newer release, review the upstream changes and redeploy a newer cloudimg image when it is published. - Back up the inventory by copying the SQLite database at
/app/db/app.db(stop the service first, or use the SQLite backup API for a consistent copy). - Logs are under
/app/log/.
Licence and source code
NetAlertX is licensed under the GNU General Public License version 3. Because NetAlertX is written in Python and PHP and runs from source, the complete corresponding source is the /app directory on your instance, kept as a git checkout pinned to the exact upstream commit. To see the upstream code and every modification cloudimg made:
sudo git -C /app log -1
sudo git -C /app diff
The verbatim licence, a written offer for the source, and a notice of cloudimg's changes ship on the image:
ls /usr/share/doc/netalertx/
CLOUDIMG-CHANGES.txt LICENSE.txt SOURCE-OFFER.txt pip-audit.json python-requirements.lock.txt
Support
This image is packaged and supported by cloudimg. For help deploying or operating it, contact support@cloudimg.co.uk for 24/7 technical support. NetAlertX itself is developed by the upstream NetAlertX open source project.