Monitoring JetKVM availability
JetKVM is a compact IP-KVM device based on the Rockchip RV1106 (ARM Cortex-A7).
For embedded devices like JetKVM, tracking their health is critical. Heartbeat monitoring lets you receive notifications if the device loses internet connectivity or stops responding.
This guide explains how to set up JetKVM availability monitoring. If you also need remote access to the device over the internet, see the tunnel setup guide.
Preparation
What you need
- JetKVM with system version v0.2.7 or newer
- Developer Mode enabled and SSH access configured (see the tunnels guide)
- An account at tuna.am
Installing tuna on JetKVM (optional)
Heartbeat notifications can also be sent with wget — installing the tuna CLI is not mandatory, but if you also use tunnels for remote access, it makes sense to use the same client for Heartbeat notifications too.
Connect to JetKVM over SSH:
ssh root@<JetKVM-IP-address>
Install tuna with the script, specifying /userdata/tuna as the install directory:
mkdir -p /userdata/tuna
INSECURE=true INSTALL_DIR=/userdata/tuna sh -c "$(wget -qO- http://releases.tuna.am/tuna/get.sh)"
The /userdata partition is preserved across OTA updates, so tuna won't need to be reinstalled.
Creating a Heartbeat monitor
- Go to the dashboard → Monitors
- Click "Create monitor"
- Choose the Heartbeat type
- Set the parameters:
- Description: JetKVM availability
- Interval: 5 minutes (the minimum on the free plan is 30 minutes)
- Grace Period: 1 minute (delay before the alert fires)
- Configure notification channels
- Save the monitor and copy the MONITOR_ID
More on Heartbeat monitors: Heartbeat documentation
Creating a monitoring init script
Starting with version 0.31, the tuna client ships with built-in CA certificates and does not depend on system ones. JetKVM has no root CA certificates, so wget can only work with --no-check-certificate, and the monitor.tuna.am API may be unreachable over HTTP. We recommend using the tuna CLI for monitoring — it is guaranteed to work over HTTPS.
Create the init script /userdata/init.d/S97tuna-heartbeat:
- tuna CLI (recommended)
- wget
cat << 'INITEOF' > /userdata/init.d/S97tuna-heartbeat
#!/bin/sh
PIDFILE=/tmp/tuna-heartbeat.pid
wait_network() {
i=0
while ! ip route | grep -q default; do
sleep 1
i=$((i + 1))
if [ "$i" -ge 60 ]; then
return 1
fi
done
return 0
}
start() {
(
wait_network || exit 1
while true; do
/userdata/tuna/tuna monitor ping --host=jetkvm YOUR_MONITOR_ID
# Interval between pings (30 minutes = 1800 seconds)
sleep 1800
done
) &
echo $! > "$PIDFILE"
}
stop() {
if [ -f "$PIDFILE" ]; then
kill "$(cat "$PIDFILE")" 2>/dev/null
rm -f "$PIDFILE"
fi
}
case "$1" in
start) start ;;
stop) stop ;;
restart) stop; sleep 1; start ;;
*) echo "Usage: $0 {start|stop|restart}" ;;
esac
INITEOF
chmod +x /userdata/init.d/S97tuna-heartbeat
cat << 'INITEOF' > /userdata/init.d/S97tuna-heartbeat
#!/bin/sh
PIDFILE=/tmp/tuna-heartbeat.pid
wait_network() {
i=0
while ! ip route | grep -q default; do
sleep 1
i=$((i + 1))
if [ "$i" -ge 60 ]; then
return 1
fi
done
return 0
}
start() {
(
wait_network || exit 1
while true; do
wget -q -T 5 --no-check-certificate -O /dev/null "https://monitor.tuna.am/YOUR_MONITOR_ID/jetkvm"
# Interval between pings (30 minutes = 1800 seconds)
sleep 1800
done
) &
echo $! > "$PIDFILE"
}
stop() {
if [ -f "$PIDFILE" ]; then
kill "$(cat "$PIDFILE")" 2>/dev/null
rm -f "$PIDFILE"
fi
}
case "$1" in
start) start ;;
stop) stop ;;
restart) stop; sleep 1; start ;;
*) echo "Usage: $0 {start|stop|restart}" ;;
esac
INITEOF
chmod +x /userdata/init.d/S97tuna-heartbeat
Replace YOUR_MONITOR_ID with the real monitor ID from your dashboard.
Parameter explanation:
| Parameter | Description |
|---|---|
YOUR_MONITOR_ID | Monitor ID from the dashboard (required) |
--host=jetkvm | Device identifier in monitoring logs (optional) |
sleep 1800 | Interval between signals in seconds (must match the monitor's setting) |
The script uses the same format as the tunnel scripts: #!/bin/sh, handling of start/stop arguments, background launch. For more on init script requirements see the tunnels guide.
Verifying it works
Run the script manually:
/userdata/init.d/S97tuna-heartbeat start
Make sure the process is running:
ps | grep heartbeat
Check the monitor's status in the dashboard — within 1-2 minutes the status should change from "New" to "Up".
Managing monitoring
Stop monitoring:
/userdata/init.d/S97tuna-heartbeat stop
Start monitoring:
/userdata/init.d/S97tuna-heartbeat start
Fully disable autostart:
mv /userdata/init.d/S97tuna-heartbeat /userdata/init.d/disabled-tuna-heartbeat
Re-enable:
mv /userdata/init.d/disabled-tuna-heartbeat /userdata/init.d/S97tuna-heartbeat
Recovery after an OTA update
The script and binary are stored in /userdata/, which is preserved across OTA updates. After a firmware update monitoring will continue to work without any extra steps.
After a full reflash (when /userdata was cleared) you will need to reinstall the binary and recreate the init script.
Troubleshooting
The heartbeat process does not start
Check that the process is in the list:
ps | grep heartbeat
If the process is missing — check that the script exists and is executable:
ls -la /userdata/init.d/S97*heartbeat*
Run the script manually for diagnostics:
/userdata/init.d/S97tuna-heartbeat start
The monitor shows "Down"
Reasons:
- Wrong MONITOR_ID
- No internet connection
- The interval in the script does not match the monitor's settings
Checks:
# Check that an IP address is assigned
ip addr
# Check the default route
ip route
# Check internet access
ping -c 3 8.8.8.8
After a firmware update heartbeat stopped working
Check that the script is still in place:
ls -la /userdata/init.d/S97*heartbeat*
If the script is missing — it may have been removed by a full reflash. Recreate it using the instructions above.