- gatus: status/uptime monitoring page with hot-reloaded config - mail-archiver: IMAP email archive and full-text search (postgres backend) - rustdesk: self-hosted remote desktop relay, cross-VLAN/FQDN docs - unifi: UniFi Network Application with MongoDB init via Docker configs - vaultwarden: Bitwarden-compatible password manager with SMTP prompts - watchyourlan: network device tracker (host networking for ARP scanning) All follow caddy_net container-routing pattern except rustdesk (raw TCP/UDP) and watchyourlan (network_mode: host, incompatible with caddy_net). README.md services table updated with all 6 new entries. https://claude.ai/code/session_01UZus2Q9gNTfUdqSMrhuX29
138 lines
5.0 KiB
Bash
138 lines
5.0 KiB
Bash
#!/bin/bash
|
|
# services/watchyourlan.sh — WatchYourLAN network device tracker.
|
|
# Part of the modular post-install system (sourced by setup.sh).
|
|
#
|
|
# Continuously scans the network for connected devices, tracks history,
|
|
# and can alert on new/unknown devices. Uses network_mode: host so it
|
|
# can see the physical network directly (required for ARP scanning).
|
|
|
|
register_service watchyourlan utilities "Network device tracker (WatchYourLAN)" 8840
|
|
|
|
install_watchyourlan() {
|
|
require_docker || return 1
|
|
log_info "Installing WatchYourLAN..."
|
|
local WYL_DIR="$DOCKER_DIR/watchyourlan"
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
echo "[DRY-RUN] Would create $WYL_DIR (watchyourlan_data/)"
|
|
echo "[DRY-RUN] Would deploy aceberg/watchyourlan:latest (network_mode: host)"
|
|
echo "[DRY-RUN] Port 8840 on host, needs network interface name"
|
|
return 0
|
|
fi
|
|
|
|
mkdir -p "$WYL_DIR/watchyourlan_data"
|
|
ensure_docker_dir_ownership "$WYL_DIR"
|
|
cd "$WYL_DIR" || return 1
|
|
|
|
local TZ_VAL="${SITE_TZ:-$(cat /etc/timezone 2>/dev/null || echo UTC)}"
|
|
|
|
# Auto-detect primary network interface
|
|
local DEFAULT_IFACE
|
|
DEFAULT_IFACE=$(ip route show default 2>/dev/null | awk '/default/ {print $5; exit}')
|
|
[ -z "$DEFAULT_IFACE" ] && DEFAULT_IFACE="eth0"
|
|
|
|
echo ""
|
|
echo " WatchYourLAN needs to know which network interface to scan."
|
|
echo " Your detected primary interface: $DEFAULT_IFACE"
|
|
echo ""
|
|
ip link show 2>/dev/null | awk -F: '/^[0-9]+: / && !/lo/ {gsub(/ /,"",$2); print " •", $2}' || true
|
|
echo ""
|
|
local SCAN_IFACE=""
|
|
prompt_text "Network interface to scan:" "$DEFAULT_IFACE" SCAN_IFACE
|
|
[ -z "$SCAN_IFACE" ] && SCAN_IFACE="$DEFAULT_IFACE"
|
|
|
|
local GUI_PORT="8840"
|
|
prompt_text "GUI port [8840]:" "8840" GUI_PORT
|
|
[ -z "$GUI_PORT" ] && GUI_PORT="8840"
|
|
|
|
cat > docker-compose.yml << 'WYL_COMPOSE'
|
|
name: watchyourlan
|
|
|
|
services:
|
|
watchyourlan:
|
|
image: aceberg/watchyourlan:latest
|
|
container_name: watchyourlan
|
|
hostname: watchyourlan
|
|
restart: unless-stopped
|
|
network_mode: host
|
|
env_file: .env
|
|
volumes:
|
|
- ./watchyourlan_data:/data
|
|
WYL_COMPOSE
|
|
|
|
cat > .env << WYL_ENV
|
|
# ── General ───────────────────────────────────────────────────────────────────
|
|
TZ=$TZ_VAL
|
|
|
|
# ── WatchYourLAN ──────────────────────────────────────────────────────────────
|
|
# Network interface to scan (ARP scanning requires the physical interface)
|
|
IFACE=$SCAN_IFACE
|
|
|
|
# GUI bind address and port (network_mode: host — binds directly to the host)
|
|
GUIIP=0.0.0.0
|
|
GUIPORT=$GUI_PORT
|
|
|
|
# Web UI theme (darkly, cosmo, lumen, sandstone, etc.)
|
|
THEME=darkly
|
|
WYL_ENV
|
|
|
|
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$WYL_DIR"
|
|
log_success "WatchYourLAN configured at $WYL_DIR"
|
|
|
|
# WatchYourLAN uses network_mode: host, so Caddy container-name routing
|
|
# can't reach it via caddy_net. Access is directly on host port $GUI_PORT.
|
|
# If behind Caddy on the same host, configure manually with host IP:PORT.
|
|
if [ -d "$DOCKER_DIR/caddy" ]; then
|
|
echo ""
|
|
log_info "Note: WatchYourLAN uses host networking (needed for ARP scanning)."
|
|
log_info "It cannot join caddy_net. To put it behind Caddy, add this block manually:"
|
|
echo ""
|
|
echo " yourdomain.com {"
|
|
echo " reverse_proxy <HOST_IP>:$GUI_PORT"
|
|
echo " }"
|
|
echo ""
|
|
echo " where HOST_IP is this server's IP on the Docker bridge (usually 172.17.0.1)."
|
|
fi
|
|
|
|
write_readme "$WYL_DIR" << MD
|
|
# WatchYourLAN — network device tracker
|
|
|
|
Scans the network continuously for connected devices, tracks history,
|
|
and alerts on new or unknown devices joining the network.
|
|
|
|
## Access
|
|
- URL: http://localhost:$GUI_PORT (or http://<server-ip>:$GUI_PORT from LAN)
|
|
|
|
## Scanning interface
|
|
Configured to scan: **$SCAN_IFACE**
|
|
Change \`IFACE\` in .env and restart if you need to scan a different interface.
|
|
|
|
## Network mode note
|
|
WatchYourLAN uses \`network_mode: host\` to see real ARP traffic.
|
|
This means it cannot be added to caddy_net for reverse proxy via container name.
|
|
To put it behind Caddy, use the host's IP directly in the Caddyfile:
|
|
\`reverse_proxy 172.17.0.1:$GUI_PORT\` (adjust IP to your Docker bridge gateway).
|
|
|
|
## Manage
|
|
\`\`\`bash
|
|
cd $WYL_DIR
|
|
docker compose up -d # start
|
|
docker compose down # stop
|
|
docker compose logs -f # logs
|
|
docker compose pull && docker compose up -d # update
|
|
\`\`\`
|
|
MD
|
|
|
|
local START_WYL=""
|
|
prompt_yn "Start WatchYourLAN now? (y/n):" "y" START_WYL
|
|
if [ "$START_WYL" = "y" ] || [ "$START_WYL" = "Y" ]; then
|
|
docker compose up -d \
|
|
&& log_success "WatchYourLAN started" \
|
|
|| log_warning "Failed to start — check: docker compose logs"
|
|
fi
|
|
|
|
echo " Access at: http://localhost:$GUI_PORT"
|
|
echo " Scanning: interface $SCAN_IFACE"
|
|
echo ""
|
|
}
|