Sipeed NanoKVM
The Sipeed NanoKVM is a great little IP KVM with HDMI pass-through (although I have not tested the limits of the HDMI bandwidth to see if 5K or 4K 240Hz and/or VRR modes are supported)…
Wireguard
Although Tailscale is natively supported out of the box with a UI to go, Wireguard is purely a shell-based set-up… To boot, the iptables_raw module is not available in the application version 1.2.14 (current as of publication), so wg-quick will fail, and no combination of update-alternatives will save you.
/usr/local/sbin/wg0.sh- adapting an
init.dstart up script for thesystemd-based NanoKVM, taking into consideration this unit’s limitations:
- adapting an
#!/bin/sh
wait_for_wireguard() {
echo "Waiting for WireGuard module to load..."
MAX_ATTEMPTS=30
DELAY_SECONDS=2
ATTEMPTS=0
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
# Check if module is already loaded
if lsmod | grep -q wireguard; then
echo "WireGuard module detected!"
return 0
fi
# Attempt manual loading if the file exists
if [ -f /kvmcomm/ko/wireguard.ko ]; then
insmod /kvmcomm/ko/wireguard.ko 2>/dev/null
else
modprobe wireguard 2>/dev/null
fi
ATTEMPTS=$((ATTEMPTS + 1))
sleep $DELAY_SECONDS
done
echo "Error: WireGuard module failed to load after $((MAX_ATTEMPTS * DELAY_SECONDS)) seconds."
return 1
}
wait_for_internet() {
echo "Waiting for network connectivity..."
PEER_IP="<PEER IP>"
MAX_RETRIES=60
WAIT_SEC=2
COUNT=0
# Loop until we can ping the public internet (8.8.8.8) or our peer
# -c 1 (one packet), -W 1 (1 second timeout)
while ! ping -q -c 1 -W 1 "$PEER_IP" >/dev/null 2>&1; do
if [ $COUNT -ge $MAX_RETRIES ]; then
echo "Network timeout reached. WireGuard will not start."
return 1
fi
echo "Network not ready yet... (Attempt $COUNT/$MAX_RETRIES)"
sleep $WAIT_SEC
COUNT=$((COUNT + 1))
done
return 0
}
ENDPOINT_IP=$(ping -c 1 <PEER IP> | head -n 1 | awk -F'(' '{print $2}' | awk -F')' '{print $1}')
case "$1" in
start)
# Loop until WireGuard module is loaded & ping to WireGuard peer is successful
if wait_for_wireguard && wait_for_internet; then
# Start WireGuard
#wg-quick up wg0 # DOESN'T WORK ON SIPEED NANOKVM - USE FOLLOWING COMMANDS IN REPLACEMENT
ip link add dev wg0 type wireguard >>/var/log/wireguard.log 2>&1
ip link set dev wg0 mtu 1360 >>/var/log/wireguard.log 2>&1
ip address add <LOCAL WIREGUARD IP>/32 dev wg0 >>/var/log/wireguard.log 2>&1
wg setconf wg0 /etc/wireguard/wg0.conf >>/var/log/wireguard.log 2>&1
ip link set up dev wg0 >>/var/log/wireguard.log 2>&1
# Prevents the encrypted tunnel traffic from looping back into the tunnel
ip route add $ENDPOINT_IP via $(ip route show default | awk '/default/ {print $3}') dev eth0
# Alternative to usurping default route and breaking Internet
ip route add 0.0.0.0/1 dev wg0
ip route add 128.0.0.0/1 dev wg0
fi
;;
stop)
echo "Stopping WireGuard..."
#wg-quick down wg0 # DOESN'T WORK ON SIPEED NANOKVM - USE FOLLOWING COMMANDS IN REPLACEMENT
ip link set down dev wg0
ip address delete <LOCAL WIREGUARD IP>/32 dev wg0
ip link delete dev wg0
ip route delete $ENDPOINT_IP
ip route delete 0.0.0.0/1
ip route delete 128.0.0.0/1
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
-
/etc/systemd/system/wireguard.service- create
systemdservice
- create
[Unit] Description=Auto-retry WireGuard Tunnel for NanoKVM After=network-online.target Wants=network-online.target [Service] Type=oneshot RemainAfterExit=yes # This loops every 2 seconds (up to 30 times) waiting for the kernel module ExecStartPre=/bin/sh -c 'for i in $(seq 1 30); do if lsmod | grep -q wireguard; then exit 0; fi; insmod /kvmcomm/ko/wireguard.ko 2>/dev/null || modprobe wireguard 2>/dev/null; sleep 2; done; exit 1' # Starts WireGuard once the module is confirmed active ExecStart=/usr/local/sbin/wg0.sh start ExecStop=/usr/local/sbin/wg0.sh stop [Install] WantedBy=multi-user.target
-
- update then enable this new service
systemctl daemon-reloadsystemctl enable wireguard.service
- update then enable this new service
/etc/wireguard/wg0.conf- since we are not using
wg-quickbut justwg setconf, we have to strip any commands recognised only bywg-quick.
- since we are not using
[Interface] PrivateKey = <PRIVATE KEY> [Peer] PublicKey = <PEER PUBLIC KEY> PresharedKey = <PRESHARED KEY> Endpoint = <PEER IP OR FQDN>:<PORT> AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 5
