Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 120 additions & 12 deletions kvmapp/system/init.d/S95nanokvm
Original file line number Diff line number Diff line change
@@ -1,5 +1,56 @@
#!/bin/sh
# nanokvm Rev3.1
# nanokvm Rev3.2

SWAPFILE="/data/swapfile"
SWAP_SIZE_MB=128

setup_swap() {
if [ -f "$SWAPFILE" ]; then
swapon "$SWAPFILE" 2>/dev/null
return
fi

echo "Creating ${SWAP_SIZE_MB}MB swap file..."
dd if=/dev/zero of="$SWAPFILE" bs=1M count=$SWAP_SIZE_MB 2>/dev/null
chmod 600 "$SWAPFILE"
mkswap "$SWAPFILE" >/dev/null 2>&1
swapon "$SWAPFILE" 2>/dev/null
echo "Swap enabled: $SWAPFILE"
}

stop_tailscale() {
if [ -x /etc/init.d/S98tailscaled ]; then
/etc/init.d/S98tailscaled stop >/dev/null 2>&1
fi
}

stop_netbird() {
if [ -x /etc/init.d/S99netbird ]; then
/etc/init.d/S99netbird stop >/dev/null 2>&1
fi
killall netbird 2>/dev/null
}

start_tailscale() {
if [ -x /usr/sbin/tailscaled ] && [ -x /usr/bin/tailscale ] && [ -f /kvmapp/system/init.d/S98tailscaled ]; then
cp -f /kvmapp/system/init.d/S98tailscaled /etc/init.d/S98tailscaled
chmod 755 /etc/init.d/S98tailscaled
/etc/init.d/S98tailscaled start >/dev/null 2>&1 &
fi
}

start_netbird() {
if [ -f /kvmapp/system/netbird/netbird ]; then
cp -f /kvmapp/system/netbird/netbird /usr/bin/netbird
chmod 755 /usr/bin/netbird
fi

if [ -x /usr/bin/netbird ] && [ -f /kvmapp/system/init.d/S99netbird ]; then
cp -f /kvmapp/system/init.d/S99netbird /etc/init.d/S99netbird
chmod 755 /etc/init.d/S99netbird
/etc/init.d/S99netbird start >/dev/null 2>&1 &
fi
}

case "$1" in
start)
Expand All @@ -16,6 +67,9 @@ case "$1" in
echo "$first_uint$second_uint" > /device_key
fi

# Enable swap before starting Go services
setup_swap

# Set iptables rules (skip if already present)
iptables -C INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT 2>/dev/null || \
iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
Expand All @@ -32,38 +86,92 @@ case "$1" in
iptables -C OUTPUT -o eth0 -p tcp --sport 8000 -m state --state ESTABLISHED -j DROP 2>/dev/null || \
iptables -A OUTPUT -o eth0 -p tcp --sport 8000 -m state --state ESTABLISHED -j DROP

# Start services
# Start services with GOMEMLIMIT
cp -r /kvmapp/kvm_system /tmp/
/tmp/kvm_system/kvm_system &

cp -r /kvmapp/server /tmp/
/tmp/server/NanoKVM-Server &
GOMEMLIMIT=20MiB /tmp/server/NanoKVM-Server &
SERVER_PID=$!

# Protect NanoKVM-Server from OOM killer
sleep 1
if [ -d "/proc/$SERVER_PID" ]; then
echo -800 > /proc/$SERVER_PID/oom_score_adj 2>/dev/null
fi

# Read VPN preference (default: tailscale)
VPN_PREF="tailscale"
if [ -f /etc/kvm/vpn ]; then
VPN_PREF=$(cat /etc/kvm/vpn)
fi

case "$VPN_PREF" in
netbird)
rm -f /etc/init.d/S98tailscaled
start_netbird
;;
*)
rm -f /etc/init.d/S99netbird
start_tailscale
;;
esac
;;

stop)
killall kvm_system
killall NanoKVM-Server
rm -r /tmp/kvm_system /tmp/server
stop_netbird
stop_tailscale
killall kvm_system 2>/dev/null
killall NanoKVM-Server 2>/dev/null
rm -rf /tmp/kvm_system /tmp/server
echo "OK"
;;

restart)
killall kvm_system
killall NanoKVM-Server
rm -r /tmp/kvm_system /tmp/server
stop_netbird
stop_tailscale
killall kvm_system 2>/dev/null
killall NanoKVM-Server 2>/dev/null
rm -rf /tmp/kvm_system /tmp/server

# Ensure swap is active
setup_swap

cp -r /kvmapp/kvm_system /tmp/
/tmp/kvm_system/kvm_system &

cp -r /kvmapp/server /tmp/
/tmp/server/NanoKVM-Server &
GOMEMLIMIT=20MiB /tmp/server/NanoKVM-Server &
SERVER_PID=$!

sleep 1
if [ -d "/proc/$SERVER_PID" ]; then
echo -800 > /proc/$SERVER_PID/oom_score_adj 2>/dev/null
fi

# Read VPN preference (default: tailscale)
VPN_PREF="tailscale"
if [ -f /etc/kvm/vpn ]; then
VPN_PREF=$(cat /etc/kvm/vpn)
fi

case "$VPN_PREF" in
netbird)
rm -f /etc/init.d/S98tailscaled
start_netbird
;;
*)
rm -f /etc/init.d/S99netbird
start_tailscale
;;
esac

sync
echo "OK"
;;

*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
esac
80 changes: 80 additions & 0 deletions kvmapp/system/init.d/S99netbird
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/bin/sh

DAEMON="netbird"
DAEMON_PATH="/usr/bin/netbird"
PIDFILE="/var/run/$DAEMON.pid"
LOGDIR="/var/log/netbird"
LOGFILE="$LOGDIR/netbird.log"

ensure_tun() {
[ -d /dev/net ] || mkdir -p /dev/net
if [ ! -c /dev/net/tun ]; then
[ -x /sbin/modprobe ] && modprobe tun 2>/dev/null || true
[ -f /lib/modules/tun.ko ] && insmod /lib/modules/tun.ko 2>/dev/null || true
mknod /dev/net/tun c 10 200 2>/dev/null || true
chmod 0755 /dev/net/tun 2>/dev/null || true
fi
}

is_running() {
[ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null
}

case "$1" in
start)
[ -x "$DAEMON_PATH" ] || {
echo "$DAEMON_PATH not found"
exit 1
}

if is_running; then
echo "$DAEMON already running"
exit 0
fi

mkdir -p /var/run "$LOGDIR"
ensure_tun

export GOMEMLIMIT=30MiB

printf "Starting %s (GOMEMLIMIT=%s): " "$DAEMON" "$GOMEMLIMIT"
start-stop-daemon -S -bmq -p "$PIDFILE" -x "$DAEMON_PATH" -- service run >>"$LOGFILE" 2>&1
if [ $? = 0 ]; then
echo "OK"
else
echo "FAIL"
exit 1
fi
;;

stop)
printf "Stopping %s: " "$DAEMON"
if [ -f "$PIDFILE" ]; then
start-stop-daemon -K -p "$PIDFILE" >/dev/null 2>&1
[ $? = 0 ] && (echo "OK"; rm -f "$PIDFILE") || (echo "FAIL"; exit 1)
else
echo "not running"
fi
;;

restart)
"$0" stop
"$0" start
;;

status)
if is_running; then
echo "$DAEMON is running"
exit 0
fi
echo "$DAEMON is not running"
exit 1
;;

*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac

exit 0
22 changes: 22 additions & 0 deletions server/proto/netbird.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package proto

type NetbirdState string

const (
NetbirdNotInstall NetbirdState = "notInstall"
NetbirdNotRunning NetbirdState = "notRunning"
NetbirdNotLogin NetbirdState = "notLogin"
NetbirdStopped NetbirdState = "stopped"
NetbirdRunning NetbirdState = "running"
)

type GetNetbirdStatusRsp struct {
State NetbirdState `json:"state"`
Name string `json:"name"`
IP string `json:"ip"`
Version string `json:"version"`
}

type LoginNetbirdRsp struct {
Url string `json:"url"`
}
9 changes: 9 additions & 0 deletions server/proto/vpn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package proto

type GetVPNPreferenceRsp struct {
VPN string `json:"vpn"` // "tailscale" or "netbird"
}

type SetVPNPreferenceReq struct {
VPN string `json:"vpn" form:"vpn" validate:"required"`
}
17 changes: 17 additions & 0 deletions server/router/extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package router

import (
"NanoKVM-Server/middleware"
"NanoKVM-Server/service/extensions/netbird"
"NanoKVM-Server/service/extensions/tailscale"
vpnService "NanoKVM-Server/service/extensions/vpn"

"github.com/gin-gonic/gin"
)
Expand All @@ -22,4 +24,19 @@ func extensionsRouter(r *gin.Engine) {
api.POST("/tailscale/start", ts.Start) // tailscale start
api.POST("/tailscale/stop", ts.Stop) // tailscale stop
api.POST("/tailscale/restart", ts.Restart) // tailscale restart

nb := netbird.NewService()

api.POST("/netbird/install", nb.Install) // install netbird
api.POST("/netbird/uninstall", nb.Uninstall) // uninstall netbird
api.GET("/netbird/status", nb.GetStatus) // get netbird status
api.POST("/netbird/down", nb.Down) // run netbird down
api.POST("/netbird/login", nb.Login) // netbird login
api.POST("/netbird/start", nb.Start) // netbird start
api.POST("/netbird/stop", nb.Stop) // netbird stop
api.POST("/netbird/restart", nb.Restart) // netbird restart

vpn := vpnService.NewService()
api.GET("/vpn/preference", vpn.GetPreference) // get VPN autostart preference
api.POST("/vpn/preference", vpn.SetPreference) // set VPN autostart preference
}
Loading