OPNsense WAN Watchdog with Cooldown, Log Rotation & Cron Integration. PART 1
The following guide is for OPNsense 25.7.7_4
In part 1 we will explore the creation of a cron activated recovery script.
A complete guide to automatically recover DHCP outages
Some home internet providers modem-mode DHCP server sometimes stops responding to DHCPREQUEST renewals.
OPNsense keeps the WAN “up”, but the actual connection silently dies until reboot.
This tutorial shows how to build a robust WAN watchdog that:
- Monitors internet connectivity
- Logs successes and failures
- Automatically reconfigures the WAN interface
- Reboots as last resort
- Enforces a 30-minute cooldown to avoid reboot loops
- Integrates cleanly with configd
- Schedules via GUI cron
- Rotates logs automatically at midnight
1. Create the Watchdog Script
Create the script:
nano /root/gw_watchdog.sh
Paste this full version (with cooldown protection):
#!/bin/sh
# OPNsense WAN watchdog (multi-host)
# Consider WAN "up" if ANY host responds.
WAN_IF="igb0" # << your WAN interface
HOSTS="1.1.1.1 8.8.8.8" # << add/remove as you like
LOG_OK="/var/log/gw_watchdog.log"
LOG_FAIL="/var/log/gw_watchdog.fail.log"
PING="/sbin/ping" # FreeBSD/OPNsense ping path
# ===========================
# COOLDOWN PROTECTION (NEW)
# ===========================
LOCK="/var/run/gwwatchdog.lock"
# >>> Change this value to adjust cooldown period <<<
COOLDOWN_SECONDS=1800 # 1800 seconds = 30 minutes
# ===========================
# END COOLDOWN SECTION
# ===========================
log_ok() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_OK"
}
log_fail() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FAIL"
}
check_any_host() {
for H in $HOSTS; do
$PING -c 1 -W 2000 "$H" >/dev/null 2>&1
if [ $? -eq 0 ]; then
log_ok "✔️ Reachable: $H"
return 0
fi
done
return 1
}
# ---- MAIN FLOW ----
# If WAN is working: normal log, exit
if check_any_host; then
exit 0
fi
# ===========================
# COOLDOWN CHECK
# ===========================
if [ -f "$LOCK" ]; then
LAST_TS=$(cat "$LOCK" 2>/dev/null || echo 0)
NOW_TS=$(date +%s)
DIFF=$((NOW_TS - LAST_TS))
if [ "$DIFF" -lt "$COOLDOWN_SECONDS" ]; then
log_fail "⏳ Cooldown active (${DIFF}s since last action, threshold ${COOLDOWN_SECONDS}s). Skipping WAN recovery."
exit 0
fi
fi
# ===========================
# END COOLDOWN CHECK
# ===========================
log_fail "⚠️ All probes failed ($HOSTS). Attempting WAN reconfigure on $WAN_IF..."
# Record that we attempted recovery
date +%s > "$LOCK"
/usr/local/sbin/configctl interface reconfigure wan >/dev/null 2>&1
sleep 20
# Check connectivity again
if check_any_host; then
log_fail "✅ Internet restored after WAN reconfigure."
exit 0
fi
# Still no internet — last resort
log_fail "❌ Still no connectivity after WAN reconfigure. Rebooting firewall..."
/sbin/shutdown -r now
Make it executable:
chmod +x /root/gw_watchdog.sh
2. Create a configd Action for GUI/Cron Use
Create a configd action so OPNsense can run the script:
nano /usr/local/opnsense/service/conf/actions.d/actions_gwwatchdog.conf
Paste:
[run]
command:/root/gw_watchdog.sh
type:script
message:running WAN watchdog script
description:Run WAN watchdog scriptCode language: JavaScript (javascript)
Restart configd:
service configd restart
Test:
configctl gwwatchdog run
Check log:
cat /var/log/gw_watchdog.logCode language: JavaScript (javascript)
3. Add Cron Job via OPNsense GUI
Go to:
System → Settings → Cron → +
Create:
- Command: “Run WAN watchdog script” (the new configd action)
- Minutes:
*/5 - Hours:
* - Days:
* - Months:
* - Weekdays:
*
Save & Apply.
Cron now runs the script every 5 minutes.
Your user-generated cron file will appear at:
/var/cron/tabs/nobodyCode language: JavaScript (javascript)
With a line similar to:
*/5 * * * * /usr/local/sbin/configctl -d -- 'gwwatchdog run'Code language: JavaScript (javascript)
4. Enable Automatic Log Rotation
Create:
nano /etc/newsyslog.conf.d/gw_watchdog.conf
Paste:
/var/log/gw_watchdog.log root:wheel 600 7 * @T00 Z
/var/log/gw_watchdog.fail.log root:wheel 600 30 * @T00 ZCode language: JavaScript (javascript)
Test rotation rules:
newsyslog -n -F
This will show what would happen at midnight.
5. Verifying Everything Works
Check OK log
tail -n 20 /var/log/gw_watchdog.logCode language: JavaScript (javascript)
Should show:
✔️ Reachable: 1.1.1.1Code language: CSS (css)
every 5 minutes.
Check failure log
tail -n 20 /var/log/gw_watchdog.fail.logCode language: JavaScript (javascript)
Shows only events like:
⚠️ All probes failed (1.1.1.1 8.8.8.8). Attempting WAN reconfigure...
⏳ Cooldown active (300s since last action, threshold 1800s). Skipping.
❌ Still no connectivity. Rebooting firewall...Code language: CSS (css)
Check lock file
cat /var/run/gwwatchdog.lockCode language: JavaScript (javascript)
Should show a recent UNIX timestamp only when action was taken.
6. Notes & Best Practices
- Cooldown prevents repeated WAN resets during full ISP outages
LOG_OKgrows slowly (1 line / 5 min)LOG_FAILstays empty unless something breaks- Midnight rotation keeps logs tidy
- Script is safe even if cron runs during reconfigure
- WAN reconfigure fixes most ISP DHCP stalls
