Router Scripting

Merlin event hooks, practical boot-time and scheduled automation, and how to troubleshoot scripts that do not run.

Published September 28, 2024

Router Scripting

Merlin can run your own scripts at specific lifecycle events. This is the main reason it is useful in a homelab.

Event Hooks

All scripts live in /jffs/scripts/ and must be executable.

ScriptTrigger
services-startSystem boot (before services start)
firewall-startAfter the firewall loads
nat-startAfter NAT module loads
wan-eventWAN connection state changes
openvpn-eventVPN client/server state changes
post-mountUSB drive mounted
dnsmasq.postconfBefore dnsmasq starts
dhcpc-eventDHCP lease events

Custom Firewall Rules On Boot

/jffs/scripts/firewall-start

#!/bin/sh
 
# Block Telnet inbound
iptables -I INPUT -i eth0 -p tcp --dport 23 -j DROP
 
# Allow SSH from LAN only
iptables -I INPUT -i eth0 -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
iptables -I INPUT -i eth0 -p tcp --dport 22 -j DROP
 
logger "Custom firewall rules applied"
chmod +x /jffs/scripts/firewall-start

VPN Health Monitor

/jffs/scripts/vpn-health-check.sh

#!/bin/sh
 
# Reconnect VPN if tunnel goes down
if ! ping -c 1 10.8.0.1 >/dev/null 2>&1; then
  logger "VPN DOWN - reconnecting"
  nvram set vpn_client1_state=0
  sleep 5
  nvram set vpn_client1_state=2
fi

Schedule it every five minutes:

crontab -e
*/5 * * * * /jffs/scripts/vpn-health-check.sh

Daily Router Backup

/jffs/scripts/backup-daily.sh

#!/bin/sh
 
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/tmp/mnt/usb/backups"
 
mkdir -p $BACKUP_DIR
 
# Export all settings
nvram show > $BACKUP_DIR/nvram_$TIMESTAMP.txt
tar czf $BACKUP_DIR/config_$TIMESTAMP.tar.gz /etc/config/
 
# Sync to NAS
rsync -avz --delete $BACKUP_DIR/ user@192.168.1.30:/backups/router/
 
# Keep only last 30 days
find $BACKUP_DIR -type f -mtime +30 -delete
 
logger "Backup complete: $TIMESTAMP"

If that .30 target is the Proxmox-backed NAS tier rather than a separate box, keep the destination aligned with the share layout in TrueNAS Shares And Proxmox Integration instead of treating it like an unstructured dump path.

chmod +x /jffs/scripts/backup-daily.sh
crontab -e
0 2 * * * /jffs/scripts/backup-daily.sh

Troubleshooting Scripts

ssh admin@192.168.1.1
 
# JFFS must be enabled
nvram get jffs2_on
 
# Script must be executable
ls -la /jffs/scripts/firewall-start
 
# Fix permissions
chmod 755 /jffs/scripts/*
 
# Test syntax
sh -n /jffs/scripts/firewall-start
 
# Run manually
/jffs/scripts/firewall-start
echo $?

Comments

Sign in with GitHub to leave a comment or reaction.