Browse Source

Merge pull request #308 from gravitl/hotfix_v0.8.1_netclient

IsServer can be set, Checkin is configurable, Moved Config Files
Alex 3 years ago
parent
commit
fa2d6cfbde

+ 1 - 0
config/config.go

@@ -56,6 +56,7 @@ type ServerConfig struct {
 	SQLConn              string `yaml:"sqlconn"`
 	Platform              string `yaml:"platform"`
 	Database             string `yaml:database`
+	CheckinInterval      string `yaml:checkininterval`
 	DefaultNodeLimit     int32  `yaml:"defaultnodelimit"`
 	Verbosity            int32  `yaml:"verbosity"`
 }

+ 1 - 3
controllers/common.go

@@ -249,9 +249,7 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) {
 
 	node.Network = networkName
 	if node.Name == models.NODE_SERVER_NAME {
-		if node.CheckIsServer() {
-			node.IsServer = "yes"
-		}
+		node.IsServer = "yes"
 	}
 	if servercfg.IsDNSMode() && node.DNSOn == ""{
 		node.DNSOn = "yes"

+ 1 - 0
controllers/networkHttpController.go

@@ -473,6 +473,7 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models
 		GRPCHost:       s.GRPCHost,
 		GRPCPort:       s.GRPCPort,
 		GRPCSSL:        s.GRPCSSL,
+		CheckinInterval:        s.CheckinInterval,
 	}
 	accessToken.ServerConfig = servervals
 	accessToken.ClientConfig.Network = netID

+ 1 - 0
functions/helpers.go

@@ -106,6 +106,7 @@ func CreateServerToken(netID string) (string, error) {
 			APIConnString:  "127.0.0.1:" + servercfg.GetAPIPort(),
 			GRPCConnString: "127.0.0.1:" + servercfg.GetGRPCPort(),
 			GRPCSSL:        "off",
+			CheckinInterval: servercfg.GetCheckinInterval(),
 		}
 	}
 	log.Println("APIConnString:", servervals.APIConnString)

+ 1 - 0
models/accessToken.go

@@ -21,6 +21,7 @@ type ServerConfig struct {
   GRPCHost   string `json:"grpchost"`
   GRPCPort   string `json:"grpcport"`
   GRPCSSL   string `json:"grpcssl"`
+  CheckinInterval   string `json:"checkininterval"`
 }
 
 type WG struct {

+ 2 - 0
models/network.go

@@ -37,6 +37,8 @@ type Network struct {
 	IsIPv6                 string      `json:"isipv6" bson:"isipv6" validate:"checkyesorno"`
 	IsGRPCHub              string      `json:"isgrpchub" bson:"isgrpchub" validate:"checkyesorno"`
 	LocalRange             string      `json:"localrange" bson:"localrange" validate:"omitempty,cidr"`
+	
+	// checkin interval is depreciated at the network level. Set on server with CHECKIN_INTERVAL
 	DefaultCheckInInterval int32       `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=2,max=100000"`
 	DefaultUDPHolePunch    string      `json:"defaultudpholepunch" bson:"defaultudpholepunch" validate:"checkyesorno"`
 	DefaultExtClientDNS    string      `json:"defaultextclientdns" bson:"defaultextclientdns"`

+ 4 - 1
models/node.go

@@ -49,6 +49,7 @@ type Node struct {
 	LastPeerUpdate      int64    `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
 	LastCheckIn         int64    `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
 	MacAddress          string   `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"required,mac,macaddress_unique"`
+	// checkin interval is depreciated at the network level. Set on server with CHECKIN_INTERVAL
 	CheckInInterval     int32    `json:"checkininterval" bson:"checkininterval" yaml:"checkininterval"`
 	Password            string   `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
 	Network             string   `json:"network" bson:"network" yaml:"network" validate:"network_exists"`
@@ -414,7 +415,9 @@ func (newNode *Node) Fill(currentNode *Node) {
 	if newNode.Action == "" {
 		newNode.Action = currentNode.Action
 	}
-	newNode.IsServer = currentNode.IsServer
+	if newNode.IsServer == "" {
+		newNode.IsServer = currentNode.IsServer
+	}
 	if newNode.IsServer == "yes" {
 		newNode.IsStatic = "yes"
 	}

+ 22 - 2
netclient/command/commands.go

@@ -5,7 +5,7 @@ import (
 	"os"
 	"strings"
 	"time"
-
+	"strconv"
 	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/netclient/config"
 	"github.com/gravitl/netmaker/netclient/daemon"
@@ -56,15 +56,35 @@ func Join(cfg config.ClientConfig, privateKey string) error {
 	return err
 }
 
+func getWindowsInterval() int {
+	interval := 15
+	networks, err := functions.GetNetworks()
+	if err != nil {
+		return interval
+	}
+	cfg, err := config.ReadConfig(networks[0])
+	if err != nil {
+		return interval
+	}
+	netint, err := strconv.Atoi(cfg.Server.CheckinInterval)
+	if err == nil && netint != 0  {
+		interval = netint
+	}
+	return interval
+}
+
 func RunUserspaceDaemon() {
+	
 	cfg := config.ClientConfig{
 		Network: "all",
 	}
+	interval := getWindowsInterval()
+	dur := time.Duration(interval) * time.Second
 	for {
 		if err := CheckIn(cfg); err != nil {
 			// pass
 		}
-		time.Sleep(15 * time.Second)
+		time.Sleep(dur)
 	}
 }
 

+ 15 - 4
netclient/config/config.go

@@ -35,6 +35,7 @@ type ServerConfig struct {
 	AccessKey     string `yaml:"accesskey"`
 	GRPCSSL       string `yaml:"grpcssl"`
 	GRPCWireGuard string `yaml:"grpcwg"`
+	CheckinInterval string `yaml:"checkininterval"`
 }
 
 //reading in the env file
@@ -43,9 +44,9 @@ func Write(config *ClientConfig, network string) error {
 		err := errors.New("no network provided - exiting")
 		return err
 	}
-	_, err := os.Stat(ncutils.GetNetclientPath())
+	_, err := os.Stat(ncutils.GetNetclientPath()+"/config")
 	if os.IsNotExist(err) {
-		os.Mkdir(ncutils.GetNetclientPath(), 0744)
+		os.MkdirAll(ncutils.GetNetclientPath()+"/config", 0744)
 	} else if err != nil {
 		return err
 	}
@@ -72,9 +73,9 @@ func WriteServer(server string, accesskey string, network string) error {
 	}
 	nofile := false
 	//home, err := homedir.Dir()
-	_, err := os.Stat(ncutils.GetNetclientPath())
+	_, err := os.Stat(ncutils.GetNetclientPath()+"/config")
 	if os.IsNotExist(err) {
-		os.Mkdir(ncutils.GetNetclientPath(), 0744)
+		os.MkdirAll(ncutils.GetNetclientPath()+"/config", 0744)
 	} else if err != nil {
 		fmt.Println("couldnt find or create", ncutils.GetNetclientPath())
 		return err
@@ -230,11 +231,13 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
 				cfg.Server.GRPCAddress = cfg.Server.GRPCAddress + ":" + accesstoken.ServerConfig.GRPCPort
 			}
 		}
+
 		cfg.Network = accesstoken.ClientConfig.Network
 		cfg.Node.Network = accesstoken.ClientConfig.Network
 		cfg.Server.AccessKey = accesstoken.ClientConfig.Key
 		cfg.Node.LocalRange = accesstoken.ClientConfig.LocalRange
 		cfg.Server.GRPCSSL = accesstoken.ServerConfig.GRPCSSL
+		cfg.Server.CheckinInterval = accesstoken.ServerConfig.CheckinInterval
 		cfg.Server.GRPCWireGuard = accesstoken.WG.GRPCWireGuard
 		cfg.Server.CoreDNSAddr = accesstoken.ServerConfig.CoreDNSAddr
 		if c.String("grpcserver") != "" {
@@ -262,6 +265,9 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
 		if c.String("grpcwg") != "" {
 			cfg.Server.GRPCWireGuard = c.String("grpcwg")
 		}
+		if c.String("checkininterval") != "" {
+			cfg.Server.CheckinInterval = c.String("checkininterval")
+		}
 
 	} else {
 		cfg.Server.GRPCAddress = c.String("grpcserver")
@@ -273,6 +279,7 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
 		cfg.Server.GRPCWireGuard = c.String("grpcwg")
 		cfg.Server.GRPCSSL = c.String("grpcssl")
 		cfg.Server.CoreDNSAddr = c.String("corednsaddr")
+		cfg.Server.CheckinInterval = c.String("checkininterval")
 	}
 	cfg.Node.Name = c.String("name")
 	cfg.Node.Interface = c.String("interface")
@@ -298,6 +305,10 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
 	cfg.Node.UDPHolePunch = c.String("udpholepunch")
 	cfg.Node.MTU = int32(c.Int("mtu"))
 
+	if cfg.Server.CheckinInterval == "" {
+		cfg.Server.CheckinInterval = "15"
+	}
+
 	return cfg, privateKey, nil
 }
 

+ 8 - 2
netclient/daemon/common.go

@@ -10,13 +10,19 @@ import (
 func InstallDaemon(cfg config.ClientConfig) error {
 	os := runtime.GOOS
 	var err error
+
+	interval := "15"
+	if cfg.Server.CheckinInterval != "" {
+		interval = cfg.Server.CheckinInterval
+	}
+
 	switch os {
 	case "windows":
 		err = SetupWindowsDaemon()
 	case "darwin":
-		err = SetupMacDaemon()
+		err = SetupMacDaemon(interval)
 	case "linux":
-		err = SetupSystemDDaemon(cfg.Network)
+		err = SetupSystemDDaemon(interval)
 	default:
 		err = errors.New("this os is not yet supported for daemon mode. Run join cmd with flag '--daemon off'")
 	}

+ 9 - 8
netclient/daemon/macos.go

@@ -4,13 +4,14 @@ import (
 	"io/ioutil"
 	"log"
 	"os"
+	"fmt"
 	"path/filepath"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 )
 
 const MAC_SERVICE_NAME = "com.gravitl.netclient"
 
-func SetupMacDaemon() error {
+func SetupMacDaemon(interval string) error {
 
 	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
 	if err != nil {
@@ -30,7 +31,7 @@ func SetupMacDaemon() error {
 	if os.IsNotExist(errN) {
 		os.Mkdir("~/Library/LaunchAgents", 0755)
 	}
-	err = CreateMacService(MAC_SERVICE_NAME)
+	err = CreateMacService(MAC_SERVICE_NAME, interval)
 	if err != nil {
 		return err
 	}
@@ -50,7 +51,7 @@ func CleanupMac() {
 	os.RemoveAll(ncutils.GetNetclientPath())
 }
 
-func CreateMacService(servicename string) error {
+func CreateMacService(servicename string, interval string) error {
 	_, err := os.Stat("/Library/LaunchDaemons")
 	if os.IsNotExist(err) {
 		os.Mkdir("/Library/LaunchDaemons", 0755)
@@ -58,7 +59,7 @@ func CreateMacService(servicename string) error {
 		log.Println("couldnt find or create /Library/LaunchDaemons")
 		return err
 	}
-	daemonstring := MacDaemonString()
+	daemonstring := MacDaemonString(interval)
 	daemonbytes := []byte(daemonstring)
 
 	if !ncutils.FileExists("/Library/LaunchDaemons/com.gravitl.netclient.plist") {
@@ -67,8 +68,8 @@ func CreateMacService(servicename string) error {
 	return err
 }
 
-func MacDaemonString() string {
-	return `<?xml version='1.0' encoding='UTF-8'?>
+func MacDaemonString(interval string) string {
+	return fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8'?>
 <!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\" >
 <plist version='1.0'>
 <dict>
@@ -84,7 +85,7 @@ func MacDaemonString() string {
 	<key>StandardErrorPath</key><string>/etc/netclient/com.gravitl.netclient.log</string>
 	<key>AbandonProcessGroup</key><true/>
 	<key>StartInterval</key>
-	    <integer>15</integer>
+	    <integer>%s</integer>
 	<key>EnvironmentVariables</key>
 		<dict>
 			<key>PATH</key>
@@ -92,7 +93,7 @@ func MacDaemonString() string {
 		</dict>
 </dict>
 </plist>
-`
+`,interval)
 }
 
 type MacTemplateData struct {

+ 24 - 28
netclient/daemon/systemd.go

@@ -11,7 +11,8 @@ import (
 	"github.com/gravitl/netmaker/netclient/ncutils"
 )
 
-func SetupSystemDDaemon(network string) error {
+func SetupSystemDDaemon(interval string) error {
+	
 	if ncutils.IsWindows() {
 		return nil
 	}
@@ -21,9 +22,9 @@ func SetupSystemDDaemon(network string) error {
 	}
 	binarypath := dir + "/netclient"
 
-	_, err = os.Stat("/etc/netclient")
+	_, err = os.Stat("/etc/netclient/config")
 	if os.IsNotExist(err) {
-		os.Mkdir("/etc/netclient", 744)
+		os.MkdirAll("/etc/netclient/config", 0744)
 	} else if err != nil {
 		log.Println("couldnt find or create /etc/netclient")
 		return err
@@ -46,7 +47,7 @@ Wants=netclient.timer
 
 [Service]
 Type=simple
-ExecStart=/etc/netclient/netclient checkin -n %i
+ExecStart=/etc/netclient/netclient checkin -n all
 
 [Install]
 WantedBy=multi-user.target
@@ -54,23 +55,17 @@ WantedBy=multi-user.target
 
 	systemtimer := `[Unit]
 Description=Calls the Netmaker Mesh Client Service
-
-`
-	systemtimer = systemtimer + "Requires=netclient@" + network + ".service"
-
-	systemtimer = systemtimer +
-		`
+Requires=netclient.service
 
 [Timer]
+Unit=netclient.service
 
 `
-	systemtimer = systemtimer + "Unit=netclient@" + network + ".service"
+	systemtimer = systemtimer + "OnCalendar=*:*:0/" + interval
 
 	systemtimer = systemtimer +
 		`
 
-OnCalendar=*:*:0/15
-
 [Install]
 WantedBy=timers.target
 `
@@ -78,26 +73,26 @@ WantedBy=timers.target
 	servicebytes := []byte(systemservice)
 	timerbytes := []byte(systemtimer)
 
-	if !ncutils.FileExists("/etc/systemd/system/netclient@.service") {
-		err = ioutil.WriteFile("/etc/systemd/system/netclient@.service", servicebytes, 0644)
+	if !ncutils.FileExists("/etc/systemd/system/netclient.service") {
+		err = ioutil.WriteFile("/etc/systemd/system/netclient.service", servicebytes, 0644)
 		if err != nil {
 			log.Println(err)
 			return err
 		}
 	}
 
-	if !ncutils.FileExists("/etc/systemd/system/netclient-" + network + ".timer") {
-		err = ioutil.WriteFile("/etc/systemd/system/netclient-"+network+".timer", timerbytes, 0644)
+	if !ncutils.FileExists("/etc/systemd/system/netclient.timer") {
+		err = ioutil.WriteFile("/etc/systemd/system/netclient.timer", timerbytes, 0644)
 		if err != nil {
 			log.Println(err)
 			return err
 		}
 	}
 
-	_, _ = ncutils.RunCmd("systemctl enable netclient@.service", true)
+	_, _ = ncutils.RunCmd("systemctl enable netclient.service", true)
 	_, _ = ncutils.RunCmd("systemctl daemon-reload", true)
-	_, _ = ncutils.RunCmd("systemctl enable netclient-"+network+".timer", true)
-	_, _ = ncutils.RunCmd("systemctl start netclient-"+network+".timer", true)
+	_, _ = ncutils.RunCmd("systemctl enable netclient.timer", true)
+	_, _ = ncutils.RunCmd("systemctl start netclient.timer", true)
 	return nil
 }
 
@@ -110,20 +105,20 @@ func RemoveSystemDServices(network string) error {
 		}
 
 		if fullremove {
-			_, err = ncutils.RunCmd("systemctl disable netclient@.service", true)
+			_, err = ncutils.RunCmd("systemctl disable netclient.service", true)
 		}
 		_, _ = ncutils.RunCmd("systemctl daemon-reload", true)
 
-		if ncutils.FileExists("/etc/systemd/system/netclient-" + network + ".timer") {
-			_, _ = ncutils.RunCmd("systemctl disable netclient-"+network+".timer", true)
+		if ncutils.FileExists("/etc/systemd/system/netclient.timer") {
+			_, _ = ncutils.RunCmd("systemctl disable netclient.timer", true)
 		}
 		if fullremove {
-			if ncutils.FileExists("/etc/systemd/system/netclient@.service") {
-				err = os.Remove("/etc/systemd/system/netclient@.service")
+			if ncutils.FileExists("/etc/systemd/system/netclient.service") {
+				err = os.Remove("/etc/systemd/system/netclient.service")
 			}
 		}
-		if ncutils.FileExists("/etc/systemd/system/netclient-" + network + ".timer") {
-			err = os.Remove("/etc/systemd/system/netclient-" + network + ".timer")
+		if ncutils.FileExists("/etc/systemd/system/netclient.timer") {
+			err = os.Remove("/etc/systemd/system/netclient.timer")
 		}
 		if err != nil {
 			log.Println("Error removing file. Please investigate.")
@@ -135,9 +130,10 @@ func RemoveSystemDServices(network string) error {
 	return nil
 }
 
+
 func isOnlyService(network string) (bool, error) {
 	isonly := false
-	files, err := filepath.Glob("/etc/netclient/netconfig-*")
+	files, err := filepath.Glob("/etc/netclient/config/netconfig-*")
 	if err != nil {
 		return isonly, err
 	}

+ 1 - 1
netclient/functions/common.go

@@ -269,7 +269,7 @@ func List() error {
 
 func GetNetworks() ([]string, error) {
 	var networks []string
-	files, err := ioutil.ReadDir(ncutils.GetNetclientPath())
+	files, err := ioutil.ReadDir(ncutils.GetNetclientPathSpecific())
 	if err != nil {
 		return networks, err
 	}

+ 0 - 5
netclient/local/local.go

@@ -91,10 +91,5 @@ func GetMacIface(ipstring string) (string, error) {
 }
 
 func HasNetwork(network string) bool {
-
-	if ncutils.IsWindows() {
 		return ncutils.FileExists(ncutils.GetNetclientPathSpecific() + "netconfig-" + network)
-	}
-	return ncutils.FileExists("/etc/systemd/system/netclient-"+network+".timer") ||
-		ncutils.FileExists(ncutils.GetNetclientPathSpecific()+"netconfig-"+network)
 }

+ 1 - 0
netclient/main.go

@@ -358,6 +358,7 @@ func main() {
 		}
 	}
 	if len(os.Args) == 1 && ncutils.IsWindows() {
+
 		c := make(chan os.Signal)
 		signal.Notify(c, os.Interrupt, syscall.SIGTERM)
 		go func() {

+ 2 - 2
netclient/ncutils/netclientutils.go

@@ -284,9 +284,9 @@ func GetNetclientPathSpecific() string {
 	if IsWindows() {
 		return WINDOWS_APP_DATA_PATH + "\\"
 	} else if IsMac() {
-		return "/etc/netclient/"
+		return "/etc/netclient/config/"
 	} else {
-		return LINUX_APP_DATA_PATH + "/"
+		return LINUX_APP_DATA_PATH + "/config/"
 	}
 }
 

+ 11 - 0
servercfg/serverconf.go

@@ -31,6 +31,7 @@ func GetServerConfig() config.ServerConfig {
 	cfg.AllowedOrigin = GetAllowedOrigin()
 	cfg.RestBackend = "off"
 	cfg.Verbosity = GetVerbose()
+	cfg.CheckinInterval = GetCheckinInterval()
 	if IsRestBackend() {
 		cfg.RestBackend = "on"
 	}
@@ -122,6 +123,16 @@ func GetAPIPort() string {
 	return apiport
 }
 
+func GetCheckinInterval() string {
+	seconds := "15"
+	if os.Getenv("CHECKIN_INTERVAL") != "" {
+		seconds = os.Getenv("CHECKIN_INTERVAL")
+	} else if config.Config.Server.CheckinInterval != "" {
+		seconds = config.Config.Server.CheckinInterval
+	}
+	return seconds
+}
+
 func GetDefaultNodeLimit() int32 {
 	var limit int32
 	limit = 999999999

+ 17 - 18
serverctl/serverctl.go

@@ -32,16 +32,16 @@ func GetServerWGConf() (models.IntClient, error) {
 
 func InstallNetclient() error {
 
-	netclientPath := ncutils.GetNetclientPathSpecific()
+	netclientPath := ncutils.GetNetclientPath()
 	if !FileExists(netclientPath + "netclient") {
 		var err error
 		if ncutils.IsWindows() {
-			_, err = copy(".\\netclient\\netclient", netclientPath+"netclient")
+			_, err = copy(".\\netclient\\netclient", netclientPath+"\\netclient")
 		} else {
-			_, err = copy("./netclient/netclient", netclientPath+"netclient")
+			_, err = copy("./netclient/netclient", netclientPath+"/netclient")
 		}
 		if err != nil {
-			log.Println("could not create " + netclientPath + "netclient")
+			log.Println("could not create " + netclientPath + "/netclient")
 			return err
 		}
 	}
@@ -86,13 +86,13 @@ func copy(src, dst string) (int64, error) {
 }
 
 func RemoveNetwork(network string) (bool, error) {
-	netclientPath := ncutils.GetNetclientPathSpecific()
-	_, err := os.Stat(netclientPath + "netclient")
+	netclientPath := ncutils.GetNetclientPath()
+	_, err := os.Stat(netclientPath + "/netclient")
 	if err != nil {
-		log.Println("could not find " + netclientPath + "netclient")
+		log.Println("could not find " + netclientPath + "/netclient")
 		return false, err
 	}
-	_, err = ncutils.RunCmd(netclientPath+"netclient leave -n "+network, true)
+	_, err = ncutils.RunCmd(netclientPath+"/netclient leave -n "+network, true)
 	if err == nil {
 		log.Println("Server removed from network " + network)
 	}
@@ -102,22 +102,21 @@ func RemoveNetwork(network string) (bool, error) {
 
 func InitServerNetclient() error {
 	netclientDir := ncutils.GetNetclientPath()
-	netclientPath := ncutils.GetNetclientPathSpecific()
-	_, err := os.Stat(netclientDir)
+	_, err := os.Stat(netclientDir+"/config")
 	if os.IsNotExist(err) {
-		os.Mkdir(netclientDir, 744)
+		os.MkdirAll(netclientDir+"/config", 744)
 	} else if err != nil {
 		log.Println("could not find or create", netclientDir)
 		return err
 	}
-	_, err = os.Stat(netclientPath + "netclient")
+	_, err = os.Stat(netclientDir + "/netclient")
 	if os.IsNotExist(err) {
 		err = InstallNetclient()
 		if err != nil {
 			return err
 		}
 	}
-	err = os.Chmod(netclientPath+"netclient", 0755)
+	err = os.Chmod(netclientDir+"/netclient", 0755)
 	if err != nil {
 		log.Println("could not change netclient binary permissions")
 		return err
@@ -128,8 +127,8 @@ func InitServerNetclient() error {
 func HandleContainedClient() error {
 	log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
 
-	netclientPath := ncutils.GetNetclientPathSpecific()
-	checkinCMD := exec.Command(netclientPath+"netclient", "checkin", "-n", "all")
+	netclientPath := ncutils.GetNetclientPath()
+	checkinCMD := exec.Command(netclientPath+"/netclient", "checkin", "-n", "all")
 	if servercfg.GetVerbose() >= 2 {
 		checkinCMD.Stdout = os.Stdout
 	}
@@ -158,7 +157,7 @@ func AddNetwork(network string) (bool, error) {
 		log.Println("could not get public IP.")
 		return false, err
 	}
-	netclientPath := ncutils.GetNetclientPathSpecific()
+	netclientPath := ncutils.GetNetclientPath()
 
 	token, err := functions.CreateServerToken(network)
 	if err != nil {
@@ -169,9 +168,9 @@ func AddNetwork(network string) (bool, error) {
 	functions.PrintUserLog(models.NODE_SERVER_NAME, "executing network join: "+netclientPath+"netclient "+"join "+"-t "+token+" -name "+models.NODE_SERVER_NAME+" -endpoint "+pubip, 0)
 	var joinCMD *exec.Cmd
 	if servercfg.IsClientMode() == "contained" {
-		joinCMD = exec.Command(netclientPath+"netclient", "join", "-t", token, "-name", models.NODE_SERVER_NAME, "-endpoint", pubip, "-daemon", "off", "-dnson", "no")
+		joinCMD = exec.Command(netclientPath+"/netclient", "join", "-t", token, "-name", models.NODE_SERVER_NAME, "-endpoint", pubip, "-daemon", "off", "-dnson", "no")
 	} else {
-		joinCMD = exec.Command(netclientPath+"netclient", "join", "-t", token, "-name", models.NODE_SERVER_NAME, "-endpoint", pubip)
+		joinCMD = exec.Command(netclientPath+"/netclient", "join", "-t", token, "-name", models.NODE_SERVER_NAME, "-endpoint", pubip)
 	}
 	joinCMD.Stdout = os.Stdout
 	joinCMD.Stderr = os.Stderr