Deployment guide

WatchYourLAN 2.1.4

Overview

WatchYourLAN is a lightweight network IP scanner with a web interface. Every two minutes, it runs arp-scan on the network that the instance is attached to and records every address that answers: its name, IP address, MAC address, hardware vendor and when it was last seen. You mark the hosts you know, and WatchYourLAN flags any host that is not marked as known, so a new instance, endpoint or device in the subnet stands out.

WatchYourLAN keeps an online/offline history for every host and can probe a host's TCP ports. It can send a notification when an unknown host appears, through Shoutrrr (email, Slack, Discord, Telegram, Gotify and many more), and it can export to Prometheus or InfluxDB.

Upstream WatchYourLAN has no login of its own. Anyone who can reach its port can read your network map, start scans, probe ports and change its settings. The SecureAnyCloud image makes it safe to run on Amazon EC2. This guide covers launching and using the WatchYourLAN 2.1.4 on Ubuntu 24.04 AMI. It is one version of the SecureAnyCloud network monitoring listing on AWS Marketplace, which you pick as the software version when you subscribe and launch.

What you get:

  • A password on every page. nginx puts the whole application behind an HTTP Basic Auth prompt whose password is generated on your instance's first boot. The image ships with an empty password file, so if anything goes wrong at first boot, nobody gets in. Wrong passwords are rate limited.
  • HTTPS from the first boot. nginx serves WatchYourLAN on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS.
  • WatchYourLAN listens on localhost only. Its service unit fixes it to 127.0.0.1:8840, so nginx is its only client. Saving another Host or Port on the settings page does not open it to the network.
  • Other web sites cannot act with your login. WatchYourLAN changes things with plain links (start a scan, probe a port, wake a host, add or delete a host). nginx refuses those requests when another web site's page sends them in your browser. It also refuses any settings change whose browser Origin is not this instance.
  • The scanner is not root. WatchYourLAN and the arp-scan it runs work as the unprivileged watchyourlan user with exactly one Linux capability, CAP_NET_RAW (raw sockets for ARP), and cannot gain more. arp-scan itself carries no setuid bit and no file capabilities.
  • No access to the instance metadata service. nginx and WatchYourLAN (and every scan it starts) are blocked at the kernel level from the EC2 instance metadata service (IPv4 and IPv6). WatchYourLAN's port checker reports the metadata address as closed.
  • No third-party downloads at run time. The web themes and icons are served from the instance, so the pages load nothing from a CDN.
  • Built from source, with current fixes. WatchYourLAN 2.1.4 is built from its official release source (checksum pinned) with Go 1.27.3. Two of the Go libraries it is built with received security fixes after 2.1.4 was released (golang.org/x/net and github.com/jackc/pgx/v5). The image uses the fixed releases, with no known reachable vulnerabilities at build time. There is no compiler on the image.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: WatchYourLAN 2.1.4 (/usr/local/bin/watchyourlan, with settings and the scan database in /var/lib/watchyourlan), arp-scan 1.10.0, nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.

Default user: ubuntu. Architecture: x86_64. Recommended instance type: m5.large.

Prerequisites

Before you launch the instance, make sure you have:

  • An AWS account subscribed to the listing, an EC2 key pair, and the VPC subnet you want to watch.
  • A security group that allows TCP 22 (SSH), TCP 443 (WatchYourLAN) and TCP 80 (redirects to HTTPS) from the networks your administrators work from. WatchYourLAN needs no other inbound port. Its ARP scan does not depend on security groups.
1

Launch the instance

In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick WatchYourLAN 2.1.4 on Ubuntu 24.04 as the software version, select your Region, and choose Launch through EC2.

Choose m5.large, your key pair, the subnet you want to watch and a security group as described above. WatchYourLAN itself needs very little, so a smaller instance also works. WatchYourLAN scans the subnet of the instance's primary network interface.

To launch with the AWS CLI instead, replace the values in angle brackets:

aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
  --instance-type m5.large --key-name <your-key-pair> \
  --security-group-ids <your-security-group> --subnet-id <your-subnet> \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=watchyourlan}]'
2

Connect to your instance

Version SSH user

WatchYourLAN 2.1.4 on Ubuntu 24.04 ubuntu

ssh -i <your-key.pem> ubuntu@<public-ip>
3

Check the services

First boot sets the host name, generates the certificate and the gate password, and writes WatchYourLAN's settings. Then WatchYourLAN and nginx start:

systemctl is-active watchyourlan-firstboot watchyourlan nginx
sudo test -f /var/lib/sac/data/watchyourlan-firstboot.done && echo FIRSTBOOT_DONE

All three units are active, and the first-boot marker is present:

active active active FIRSTBOOT_DONE

Only SSH and nginx listen on the network. WatchYourLAN listens on localhost only. Confirm this with the following commands:

sudo ss -lntpH | awk '{print $4, $6}' | sed -E 's/users:\(\("([^"]+)".*/\1/' | grep -v '127.0.0.5' | sort -u
0.0.0.0:22 sshd 0.0.0.0:443 nginx 0.0.0.0:80 nginx 127.0.0.1:8840 watchyourlan [::]:22 sshd [::]:443 nginx [::]:80 nginx
4

Get your URL and password

sudo cat /var/lib/sac/data/watchyourlan-credentials.txt

Only root can read the file. It holds the URL, user name and password for this instance:

# WatchYourLAN 2.1.4 - generated on first boot by watchyourlan-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret. WATCHYOURLAN_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ WATCHYOURLAN_USER=admin WATCHYOURLAN_PASSWORD=<WATCHYOURLAN_PASSWORD>
#
# Open WATCHYOURLAN_URL in a browser (self-signed certificate minted on this instance's first boot; port 80 redirects to # https) and pass the HTTP Basic Auth prompt with WATCHYOURLAN_USER / WATCHYOURLAN_PASSWORD. WatchYourLAN has no accounts # of its own: this gate is its login. It scans ens5 (this instance's subnet) every 2 minutes.
# Self-test:
sudo watchyourlan-selftest Change the served name:
sudo watchyourlan-set-hostname <your-domain>
# User guide: https://secureanycloud.com/stacks/watchyourlan-2-1-4/

The URL uses the instance's public DNS name from EC2 instance metadata. If you open https://<public-ip>/, nginx redirects you to that name.

The image includes a self test. Through nginx, it passes the gate and checks the pages, the scan, the scanner's privileges, the request guards and the metadata block:

sudo watchyourlan-selftest
SELFTEST-OK https 301 + healthz + gate 401 (anonymous and wrong password on 10 routes) / 200 + UI, local theme and icons, CSP + /api/version 2.1.4 + config loopback:8840 + watchyourlan uid watchyourlan, CapEff/Bnd/Amb = CAP_NET_RAW only, NoNewPrivs, listening 127.0.0.1:8840 only + scan lists gateway 172.31.80.1 (21 hosts) + 403 cross-site rescan + 403 cross-origin POST + 444 unknown host + metadata 000 inside watchyourlan and nginx, /api/port to metadata false (control 200 / true)
5

Your network in the browser

Open the WATCHYOURLAN_URL in your browser. The certificate is self-signed, so your browser asks you to confirm it the first time. Alternatively, install your own certificate (Step 9). The browser then asks for a user name and password. Enter WATCHYOURLAN_USER and WATCHYOURLAN_PASSWORD.

The home page lists every host that the scans have found. For each host it shows the name (reverse DNS), interface, IP address, MAC address, hardware vendor, when the host was last seen, whether you have marked it as known, and whether it answered the latest scan (green) or not (grey). You can filter by interface, known or online, search, and sort by any column.

Choose Edit to name hosts and switch Known on for the ones you recognise. WatchYourLAN alerts on the unknown ones.

Click an IP address to open the host's page. It shows the host's details, a rename box, the Known switch, a Port Scan that checks a range of TCP ports from the instance, Wake-on-LAN, Delete host and the host's online history for a day.

History shows each host's recent scans as a row of green (online) and grey (offline) marks, so hosts that come and go are easy to spot.

6

What WatchYourLAN scans

On AWS, arp-scan sends an ARP request to every address of the instance's subnet. The VPC answers for every network interface that holds one of those addresses, with that interface's own MAC address, whatever its security group allows.

Names come from reverse DNS (in a VPC, ip-a-b-c-d.ec2.internal or ip-a-b-c-d.<region>.compute.internal). The hardware vendor of a VPC interface shows as (Unknown: locally administered). The subnet's router (the first address, here 172.31.80.1) is always present.

The scan settings are on the Config page. WatchYourLAN stores them in /var/lib/watchyourlan/config_v2.yaml:

sudo grep -E '^(host|port|ifaces|timeout|trim_hist|use_db|arp_args):' /var/lib/watchyourlan/config_v2.yaml
host: 127.0.0.1 port: "8840" arp_args: "" ifaces: ens5 timeout: 120 trim_hist: 48 use_db: sqlite

When you save settings in the browser, WatchYourLAN rewrites the file with its keys in alphabetical order.

  • Interfaces is the network interface to scan. First boot sets the primary interface, ens5 on current instance types. To watch another subnet too, add a second network interface in that subnet and list both interfaces, separated by a space.
  • Timeout is the time between scans in seconds. Trim History is how many hours of online/offline history to keep.
  • Args for arp-scan and Arp Strings pass your own arp-scan options or target lists, for example a narrower range.

ARP does not cross a router. Subnets reached through a route (another subnet, a peered VPC or a VPN) need a network interface in that subnet. Only scan networks that you own or are authorised to scan.

7

Notifications, Prometheus and the API

The Shoutrrr URL on the Config page sends a message when a new unknown host appears. It takes any Shoutrrr service URL, for example smtp://user:password@smtp.example.com:587/?from=watchyourlan@example.com&to=you@example.com or a Slack, Discord, Telegram or Gotify URL. Select Test notification to send a test. The instance needs outbound access to that service.

The Host and Port boxes have no effect on this image. The service unit fixes WatchYourLAN to 127.0.0.1:8840, behind nginx, whatever is saved there. With Prometheus config enabled, /metrics serves the host list for Prometheus, behind the same password.

WatchYourLAN also has a small JSON API, behind the same password. It is documented at /swagger/index.html on your instance. For example, query the number of hosts found so far and the version:

H=$(sudo sed -n 's#^WATCHYOURLAN_URL=https://\([^/]*\)/$#\1#p' /var/lib/sac/data/watchyourlan-credentials.txt)
U=$(sudo sed -n 's/^WATCHYOURLAN_USER=//p' /var/lib/sac/data/watchyourlan-credentials.txt)
PW=$(sudo sed -n 's/^WATCHYOURLAN_PASSWORD=//p' /var/lib/sac/data/watchyourlan-credentials.txt)
curl -sk --resolve "$H:443:127.0.0.1" -K - "https://$H/api/all" <<<"user = \"$U:$PW\"" | python3 -c 'import json,sys; print(len(json.load(sys.stdin) or []), "hosts")'
curl -sk --resolve "$H:443:127.0.0.1" -K - "https://$H/api/version" <<<"user = \"$U:$PW\""; echo
21 hosts "2.1.4"

The curl -K - option reads the password from standard input, so it does not appear in the process list.

8

Data and backups

WatchYourLAN keeps all of its data in /var/lib/watchyourlan: config_v2.yaml (settings) and scan.db (the hosts and their history, in SQLite). To back it up, stop WatchYourLAN briefly:

sudo systemctl stop watchyourlan
sudo tar -C /var/lib -czf /root/watchyourlan-backup.tgz watchyourlan
sudo systemctl start watchyourlan

To restore on a new instance, stop WatchYourLAN, extract the archive over /var/lib/watchyourlan (owner watchyourlan, mode 700), and start WatchYourLAN again.

9

Use your own domain and certificate

  • In your DNS, point <your-domain> (an A record) at the instance's public IP address. An Elastic IP keeps that address stable.
  • Tell the instance to use the domain. This command sets the name that nginx accepts and the request guards, and generates a new self-signed certificate for the domain:
sudo watchyourlan-set-hostname <your-domain>
  • For a certificate that your browser trusts, put the certificate chain for <your-domain> in /etc/ssl/watchyourlan/watchyourlan.crt and its private key in /etc/ssl/watchyourlan/watchyourlan.key (root only, mode 600). Then run sudo systemctl reload nginx. Alternatively, put the instance behind an Application Load Balancer with an AWS Certificate Manager certificate that forwards to port 443 on the instance.
10

Security checks

Confirm that nginx and WatchYourLAN are blocked from the instance metadata service:

for u in nginx watchyourlan; do printf '%s ' "$u"; systemctl show -p IPAddressDeny --value "$u" | tr ' ' '\n' | sort | tr '\n' ' '; echo; done
nginx 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128 watchyourlan 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128

Confirm that WatchYourLAN runs as watchyourlan with only CAP_NET_RAW (bit 13, 0x2000) and cannot gain other privileges:

P=$(systemctl show -p MainPID --value watchyourlan) ps -o user= -p "$P" grep -E '^(CapEff|CapBnd|CapAmb|NoNewPrivs)' /proc/"$P"/status
watchyourlan CapEff: 0000000000002000 CapBnd: 0000000000002000 CapAmb: 0000000000002000 NoNewPrivs: 1

The gate answers before WatchYourLAN does. nginx refuses a scan or settings change that another web site's page sends, and a request for a host name that the instance does not serve gets no answer at all:

H=$(sudo sed -n 's#^WATCHYOURLAN_URL=https://\([^/]*\)/$#\1#p' /var/lib/sac/data/watchyourlan-credentials.txt)
curl -sk -o /dev/null -w 'no password: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/"
curl -sk -o /dev/null -w 'cross-site rescan: %{http_code}\n' --resolve "$H:443:127.0.0.1" -H 'Sec-Fetch-Site: cross-site' "https://$H/api/rescan"
curl -sk -o /dev/null -w 'cross-origin POST: %{http_code}\n' --resolve "$H:443:127.0.0.1" -X POST -H 'Origin: https://evil.example' --data 'theme=x' "https://$H/api/config/"
curl -sk -o /dev/null -w 'unknown host name: %{http_code}\n' --resolve evil.example:443:127.0.0.1 https://evil.example/ || true
no password: 401 cross-site rescan: 403 cross-origin POST: 403 unknown host name: 000

Only root can read the credentials, the gate's password hash and the TLS key. Only root and the watchyourlan service user can read WatchYourLAN's data:

sudo stat -c '%a %U:%G %n' /var/lib/sac/data/watchyourlan-credentials.txt /etc/nginx/watchyourlan.htpasswd /etc/ssl/watchyourlan/watchyourlan.key /var/lib/watchyourlan /var/lib/watchyourlan/config_v2.yaml
600 root:root /var/lib/sac/data/watchyourlan-credentials.txt 640 root:www-data /etc/nginx/watchyourlan.htpasswd 600 root:root /etc/ssl/watchyourlan/watchyourlan.key 700 watchyourlan:watchyourlan /var/lib/watchyourlan 600 watchyourlan:watchyourlan /var/lib/watchyourlan/config_v2.yaml

Other notes:

  • The password is a 24-character random string, stored as a SHA-512 crypt hash in /etc/nginx/watchyourlan.htpasswd. To change it, write a new hash there. The command printf '%s\n' '<new-password>' | openssl passwd -6 -stdin gives the hash, and the line is admin:<hash>. Then update the credentials file and run sudo systemctl reload nginx.
  • Who can reach it. Anyone with the password can see your subnet's hosts and start scans and port checks from the instance. Open ports 80 and 443 in the security group only to the networks that your administrators use.
  • The build. /usr/share/doc/sac-watchyourlan/BUILD-INFO.txt records the release, the Go toolchain and the two dependency updates. go.mod, go.sum and go-version-m.txt next to it list every library in the program.
  • Logs. nginx logs are in /var/log/nginx. WatchYourLAN logs to the journal (journalctl -u watchyourlan), including each unknown host it finds.
11

Keep it up to date

Ubuntu security updates install automatically. To apply all updates immediately, run:

sudo apt-get update && sudo apt-get upgrade -y

New WatchYourLAN releases arrive as new versions of this listing, built and checked the same way. To move to a new version, back up /var/lib/watchyourlan (Step 8), launch the new version and restore the backup. Read the WatchYourLAN release notes before you move.

Support and licensing

WatchYourLAN is open source under the MIT license (aceberg and contributors). The license text is in /usr/share/doc/sac-watchyourlan/, and the source code is at github.com/aceberg/WatchYourLAN. arp-scan is open source under the GPL 3.0 or later license. The Go libraries that WatchYourLAN is built with are open source under permissive licenses (MIT, BSD and Apache 2.0).

There is no per-user license fee. The AMI price covers SecureAnyCloud's build, hardening, first-boot setup and support.

  • Email: sales@secureanycloud.com
  • Website: https://secureanycloud.com
  • Support: 24/7, with a 24 hour response SLA

The other versions on this listing are covered in the network monitoring guide.

Deploy on AWS

Launch WatchYourLAN 2.1.4 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on AWS