소스 검색

nm-install initial functionality

Matthew R Kasun 1 년 전
부모
커밋
fd08554fb9

+ 71 - 0
pkg/nm-install/cmd/dependencies.go

@@ -0,0 +1,71 @@
+package cmd
+
+import (
+	"os"
+	"os/exec"
+)
+
+type dependecies struct {
+	wireguard      bool
+	wireguardTools bool
+	docker         bool
+	dockerCompose  bool
+	dependencies   []string
+	update         string
+	install        string
+}
+
+func installDependencies() {
+	dep := dependecies{}
+	if exists("/etc/debian_version") {
+		dep.dependencies = []string{"git", "wireguard", "wireguard-tools", "dnsutils",
+			"jq", "docker-io", "docker-compose", "grep", "awk"}
+		dep.update = "apt update"
+		dep.install = "apt-get install -y"
+	} else if exists("/etc/alpine-release") {
+		dep.dependencies = []string{"git wireguard jq docker.io docker-compose grep gawk"}
+		dep.update = "apk update"
+		dep.install = "apk --update add"
+	} else if exists("/etc/centos-release") {
+		dep.dependencies = []string{"git wireguard jq bind-utils docker.io docker-compose grep gawka"}
+		dep.update = "yum update"
+		dep.install = "yum install -y"
+	} else if exists("/etc/fedora-release") {
+		dep.dependencies = []string{"git wireguard bind-utils jq docker.io docker-compose grep gawk"}
+		dep.update = "dnf update"
+		dep.install = "dnf install -y"
+	} else if exists("/etc/redhat-release") {
+		dep.dependencies = []string{"git wireguard jq docker.io bind-utils docker-compose grep gawk"}
+		dep.update = "yum update"
+		dep.install = "yum install -y"
+	} else if exists("/etc/arch-release") {
+		dep.dependencies = []string{"git wireguard-tools dnsutils jq docker.io docker-compose grep gawk"}
+		dep.update = "pacman -Sy"
+		dep.install = "pacman -S --noconfirm"
+	} else {
+		dep.install = ""
+	}
+	//check if installed
+	_, err := exec.LookPath("wg")
+	if err != nil {
+		dep.wireguardTools = true
+		dep.dependencies = append(dep.dependencies, "wireguard-tools")
+	}
+	_, err = exec.LookPath("docker")
+	if err != nil {
+		dep.docker = true
+		dep.dependencies = append(dep.dependencies, "docker-ce")
+	}
+	_, err = exec.LookPath("docker-compose")
+	if err != nil {
+		dep.dockerCompose = true
+		dep.dependencies = append(dep.dependencies, "docker-compose")
+	}
+}
+
+func exists(file string) bool {
+	if _, err := os.Stat(file); err != nil {
+		return false
+	}
+	return true
+}

+ 55 - 0
pkg/nm-install/cmd/netclient.go

@@ -0,0 +1,55 @@
+package cmd
+
+import (
+	"os"
+	"runtime"
+	"strings"
+
+	"github.com/bitfield/script"
+	"github.com/pterm/pterm"
+	"github.com/spf13/viper"
+)
+
+func installNetclient() {
+	newInstall := false
+	existingVersion, _ := script.Exec("netclient version").String()
+	pterm.Println("checking for installed netclient ", "existing version", existingVersion, "latest", latest)
+	if strings.TrimSpace(existingVersion) == latest {
+		pterm.Println("latest version of netclient already installed, skipping...")
+		return
+	} else if strings.Contains(existingVersion, "file not found") {
+		newInstall = true
+	}
+	pterm.Println("netclient new install:", newInstall)
+	pterm.Println("retrieving the latest version of netclient")
+	arch := runtime.GOARCH
+	baseURL := "https://github.com/gravitl/netclient/releases/download/" + latest + "/netclient-linux-" + arch
+	getFile(baseURL, "", "/tmp/netclient")
+	os.Chmod("/tmp/netclient", 0700)
+	if _, err := script.Exec("/tmp/netclient install").Stdout(); err != nil {
+		panic(err)
+	}
+	if newInstall {
+		pterm.Println("latest version of netclient installed")
+	} else {
+		pterm.Println("netclient updated to latest version")
+		// since this was an update don't contine
+		return
+	}
+	pterm.Println("joining network with token", token)
+	if token != "" {
+		if _, err := script.Exec("netclient join -t " + token).Stdout(); err != nil {
+			panic(err)
+		}
+	} else {
+		pterm.Println("enrollment key not defined")
+	}
+	viper.SetConfigFile("/etc/netclient/nodes.yml")
+	viper.ReadInConfig()
+	nodeID := viper.GetString("netmaker.commonnode.id")
+	hostID := viper.GetString("netmaker.commonnode.id")
+	pterm.Println("setting default node")
+	script.Exec("/tmp/nmctl host update " + hostID + " --default").Stdout()
+	pterm.Println("creating ingress gateway")
+	script.Exec("/tmp/nmctl node create_ingress netmaker " + nodeID).Stdout()
+}

+ 117 - 0
pkg/nm-install/cmd/netmaker.go

@@ -0,0 +1,117 @@
+package cmd
+
+import (
+	"encoding/json"
+	"net/http"
+	"os"
+	"time"
+
+	"github.com/bitfield/script"
+	"github.com/joho/godotenv"
+	"github.com/pterm/pterm"
+)
+
+type Release struct {
+	Version string `json:"tag_name"`
+}
+
+func installNetmaker() {
+	var netEnv map[string]string
+	latest = getLatestRelease()
+	pterm.Println("installing netmaker version ", latest)
+	//get files
+	baseURL := "https://raw.github.com/gravitl/netmaker/" + latest
+	getFile(baseURL, "/compose/docker-compose.yml", "./docker-compose.yml")
+	getFile(baseURL, "/scripts/netmaker.default.env", "./netmaker.default.env")
+	getFile(baseURL, "/scripts/nm-certs.sh", "./nm-certs.sh")
+	getFile(baseURL, "/docker/mosquitto.conf", "./mosquitto.conf")
+	getFile(baseURL, "/docker/wait.sh", "./wait.sh")
+	if pro {
+		getFile(baseURL, "/compose/docker-compose.pro.yml", "./docker-compose.override.yml")
+		getFile(baseURL, "/docker/Caddyfile-pro", "./Caddyfile")
+	} else {
+		getFile(baseURL, "/docker/Caddyfile", "./Caddyfile")
+	}
+	os.Chmod("wait.sh", 0700)
+	os.Chmod("nm-certs.sh", 0700)
+	netEnv, err := godotenv.Read("./netmaker.default.env")
+	if err != nil {
+		panic(err)
+	}
+	netEnv["NM_EMAIL"] = email
+	netEnv["NM_DOMAIN"] = domain
+	netEnv["UI_IMAGE_TAG"] = latest
+	netEnv["SERVER_IMAGE_TAG"] = latest
+	netEnv["MASTER_KEY"] = masterkey
+	netEnv["MQ_USERNAME"] = mqUsername
+	netEnv["MQ_PASSWORD"] = mqPassword
+	netEnv["TURN_USERNAME"] = turnUsername
+	netEnv["TURN_PASSWORD"] = turnPassword
+	netEnv["INSTALL_TYPE"] = "ce"
+	if pro {
+		netEnv["INSTALL_TYPE"] = "pro"
+		netEnv["METRICS_EXPORTER"] = "on"
+		netEnv["PROMETHEUS"] = "on"
+		netEnv["NETMAKER_TENENT_ID"] = tenantID
+		netEnv["LICENSE_KEY"] = license
+		netEnv["SERVER_IMAGE_NAME"] = latest + "-ee"
+	}
+	if err := godotenv.Write(netEnv, "./netmaker.env"); err != nil {
+		panic(err)
+	}
+	os.Symlink("netmaker.env", ".env")
+	//Fetch/Update certs
+	pterm.Println("\nGetting certificates")
+	//fix nm-cert.sh  remove -it from docker run -it --rm .....
+	if _, err := script.File("./nm-certs.sh").Replace("-it", "").WriteFile("./certs.sh"); err != nil {
+		panic(err)
+	}
+	os.Chmod("./certs.sh", 0700)
+	if _, err := script.Exec("./certs.sh").Stdout(); err != nil {
+		panic(err)
+	}
+	pterm.Println("\nStarting containers...")
+	if _, err := script.Exec("docker-compose -f docker-compose.yml up -d --force-recreate").Stdout(); err != nil {
+		panic(err)
+	}
+	testConnection()
+}
+
+func getFile(baseURL, remote, local string) {
+	req, err := http.NewRequest(http.MethodGet, baseURL+remote, nil)
+	if err != nil {
+		panic(err)
+	}
+	if _, err := script.Do(req).WriteFile(local); err != nil {
+		panic(err)
+	}
+}
+
+func getLatestRelease() string {
+	request, err := http.NewRequest(http.MethodGet, "https://api.github.com/repos/gravitl/netmaker/releases/latest", nil)
+	if err != nil {
+		panic(err)
+	}
+	client := http.Client{
+		Timeout: time.Second * 10,
+	}
+	release := Release{}
+	resp, err := client.Do(request)
+	if err != nil {
+		panic(err)
+	}
+	if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
+		panic(err)
+	}
+	return release.Version
+}
+
+func testConnection() {
+	pterm.Println("\nTesting Server setup for https://api." + domain + "/api/server/status")
+
+	if _, err := script.Get("https://api." + domain + "/api/server/status").Stdout(); err != nil {
+		pterm.Println("unable to connect to server, please investigate")
+		pterm.Println("Exiting...")
+		os.Exit(1)
+	}
+}

+ 53 - 0
pkg/nm-install/cmd/nmctl.go

@@ -0,0 +1,53 @@
+package cmd
+
+import (
+	"net/http"
+	"os"
+	"runtime"
+
+	"github.com/bitfield/script"
+	"github.com/pterm/pterm"
+)
+
+func installNmctl() {
+	pterm.Println("installing nmctl")
+	arch := runtime.GOARCH
+	baseURL := "https://github.com/gravitl/netmaker/releases/download/" + latest + "/nmctl-linux-" + arch
+	getFile(baseURL, "", "/tmp/nmctl")
+	os.Chmod("/tmp/nmctl", 0700)
+	if _, err := script.Exec("/tmp/nmctl context set default --endpoint=https://api." + domain + " --master_key=" + masterkey).Stdout(); err != nil {
+		panic(err)
+	}
+	if _, err := script.Exec("/tmp/nmctl context use default").Stdout(); err != nil {
+		panic(err)
+	}
+	if _, err := script.Exec("/tmp/nmctl network list").Stdout(); err != nil {
+		panic(err)
+	}
+}
+
+func createNetwork() {
+	request, err := http.NewRequest(http.MethodGet, "https://api."+domain+"/api/networks", nil)
+	if err != nil {
+		panic(err)
+	}
+	request.Header.Set("Authorization", "Bearer "+masterkey)
+	resp, err := script.Do(request).String()
+	if err != nil {
+		panic(err)
+	}
+	if len(resp) > 5 {
+		pterm.Println("networks exist, skipping creation of new network")
+		return
+	}
+	pterm.Println("Creating netmaker network (10.101.0.0/16)")
+	if _, err := script.Exec("/tmp/nmctl network create --name netmaker --ipv4_addr 10.101.0.0/16").String(); err != nil {
+		panic(err)
+	}
+	pterm.Println("creating enrollmentkey")
+	token, err = script.Exec("/tmp/nmctl enrollment_key create --uses 1 --networks netmaker --tags netmaker").JQ(" .token").String()
+	if err != nil {
+		panic(err)
+	}
+	pterm.Println("enrollment token:", token)
+}

+ 128 - 0
pkg/nm-install/cmd/root.go

@@ -0,0 +1,128 @@
+/*
+Copyright © 2023 Netmaker Team
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package cmd
+
+import (
+	"fmt"
+	"math/rand"
+	"os"
+
+	"github.com/pterm/pterm"
+	"github.com/pterm/pterm/putils"
+	"github.com/spf13/cobra"
+	"github.com/spf13/viper"
+)
+
+var (
+	pro          bool
+	domain       string
+	masterkey    string
+	license      string
+	tenantID     string
+	email        string
+	mqUsername   string
+	mqPassword   string
+	turnUsername string
+	turnPassword string
+	latest       string
+	token        string
+)
+
+// rootCmd represents the base command when called without any subcommands
+var rootCmd = &cobra.Command{
+	Use:   "nm-install",
+	Short: "A brief description of your application",
+	Long: `A longer description that spans multiple lines and likely contains
+examples and usage of using your application. For example:
+
+Cobra is a CLI library for Go that empowers applications.
+This application is a tool to generate the needed files
+to quickly create a Cobra application.`,
+	// Uncomment the following line if your bare application
+	// has an action associated with it:
+	Run: func(cmd *cobra.Command, args []string) {
+		fmt.Print("\n\n")
+		pterm.DefaultBigText.WithLetters(
+			putils.LettersFromStringWithStyle("NETMAKER", pterm.FgCyan.ToStyle())).Render()
+		getBuildType(&pro)
+		installDependencies()
+		setInstallVars()
+		installNetmaker()
+		installNmctl()
+		createNetwork()
+		installNetclient()
+		pterm.Println("\nNetmaker setup is now complete. You are ready to begin using Netmaker")
+		pterm.Println("Visit https://dashboard." + domain + " to log in")
+	},
+}
+
+// Execute adds all child commands to the root command and sets flags appropriately.
+// This is called by main.main(). It only needs to happen once to the rootCmd.
+func Execute() {
+	err := rootCmd.Execute()
+	if err != nil {
+		os.Exit(1)
+	}
+}
+
+func init() {
+	cobra.OnInitialize(initConfig)
+
+	// Here you will define your flags and configuration settings.
+	// Cobra supports persistent flags, which, if defined here,
+	// will be global for your application.
+
+	rootCmd.PersistentFlags().BoolVarP(&pro, "pro", "p", false, "install pro version")
+	rootCmd.PersistentFlags().StringVarP(&domain, "domain", "d", "", "custom domain to use")
+
+	// Cobra also supports local flags, which will only run
+	// when this action is called directly.
+	rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
+
+// initConfig reads in config file and ENV variables if set.
+func initConfig() {
+	viper.BindPFlags(rootCmd.Flags())
+	viper.AutomaticEnv() // read in environment variables that match
+}
+
+func getBuildType(pro *bool) {
+	if !*pro {
+		pterm.Println("Would you like to install Netmaker Community Edition (CE), or Netmaker Enterprise Edition(pro)")
+		pterm.Print("\nPro will require you to create an account at https://app.netmaker.io\n\n")
+		selection := getInput([]string{"Community Edition", "Enterprise Edition (pro)"})
+		if selection == "Enterprise Edition (pro)" {
+			*pro = true
+		}
+	}
+}
+
+func getInput(options []string) string {
+	selected, err := pterm.DefaultInteractiveSelect.WithOptions(options).Show()
+	if err != nil {
+		panic(err)
+	}
+	return selected
+}
+
+func randomString(n int) string {
+	const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
+	result := make([]byte, n)
+	for i := 0; i < n; i++ {
+		result[i] = letters[rand.Intn(len(letters))]
+	}
+	return string(result)
+}

+ 86 - 0
pkg/nm-install/cmd/variables.go

@@ -0,0 +1,86 @@
+package cmd
+
+import (
+	"os"
+	"strings"
+
+	"github.com/bitfield/script"
+	"github.com/pterm/pterm"
+	"github.com/rdegges/go-ipify"
+)
+
+func setInstallVars() {
+	askDomain := false
+	ip, err := ipify.GetIp()
+	if err != nil {
+		panic(err)
+	}
+	ipDash := strings.ReplaceAll(ip, ".", "-")
+	if domain == "" {
+		domain = "nm." + ipDash + ".nip.io"
+		askDomain = true
+	}
+	if masterkey == "" {
+		masterkey = randomString(32)
+	}
+	pterm.Println("masterkey set: ", masterkey)
+	mqUsername = "netmaker"
+	mqPassword = randomString(32)
+	pterm.Println("mq creditials:", mqUsername, mqPassword)
+	turnUsername = "netmaker"
+	turnPassword = randomString(32)
+	pterm.Println("turn creditials:", turnUsername, turnPassword)
+	if askDomain {
+		pterm.Println("\nWould you like to use your own domain for netmaker, or an auto-generated domain?")
+		pterm.Println("\nTo use your own domain, add a Wildcard DNS record (e.x: *.netmaker.example.com) pointing to", ip)
+		pterm.Print("\nIMPORTANT: Due to the high volume of requests, the auto-generated domain has been rate-limited by the certificate provider.")
+		pterm.Print("For this reason, we ", pterm.LightMagenta("STRONGLY RECOMMEND"), " using your own domain. Using the auto-generated domain may lead to a failed installation due to rate limiting.\n\n")
+		domainType := getInput([]string{"Auto Generated " + domain, "Custom Domain (e.g. netmaker.example.com)"})
+		if strings.Contains(domainType, "Custom") {
+			script.Echo("Enter Custom Domain (ensure *.domain points to " + ip).Stdout()
+			domain, err = pterm.DefaultInteractiveTextInput.WithMultiLine(false).Show()
+			if err != nil {
+				panic(err)
+			}
+		}
+	}
+	pterm.Print("\nThe following subdomains will be used:\n\n")
+	pterm.Printf("dashboard.%s\n", domain)
+	pterm.Printf("api.%s\n", domain)
+	pterm.Printf("broker.%s\n", domain)
+	pterm.Printf("turn.%s\n", domain)
+	pterm.Printf("turnapi.%s\n", domain)
+	if pro {
+		pterm.Printf("prometheus.%s\n", domain)
+		pterm.Printf("netmaker-exporter.%s\n", domain)
+		pterm.Printf("grafana.%s\n", domain)
+	}
+	pterm.Print("\n\n")
+	ok, err := pterm.DefaultInteractiveConfirm.WithDefaultValue(true).Show()
+	if err != nil {
+		panic(err)
+	}
+	if !ok {
+		os.Exit(1)
+	}
+	pterm.Print("\nEnter email address for certificate registration\n\n")
+	email, err = pterm.DefaultInteractiveTextInput.WithMultiLine(false).Show()
+	if err != nil {
+		panic(err)
+	}
+	if pro {
+		pterm.Println("\nProvide Details for Pro installation")
+		pterm.Println("\t1. Log into https://app.netmaker.io")
+		pterm.Println("\t2. follow instructions to get a license at: https://docs.netmaker.io/ee/ee-setup.html")
+		pterm.Println("\t3. Retrieve License and Tenant ID")
+		pterm.Println("\t4. note email address")
+		license, err = pterm.DefaultInteractiveTextInput.WithMultiLine(false).WithDefaultText("Licence Key").Show()
+		if err != nil {
+			panic(err)
+		}
+		tenantID, err = pterm.DefaultInteractiveTextInput.WithMultiLine(false).WithDefaultText("Tenant ID").Show()
+		if err != nil {
+			panic(err)
+		}
+	}
+}

+ 58 - 0
pkg/nm-install/cmd/version.go

@@ -0,0 +1,58 @@
+/*
+Copyright © 2023 Netmaker Team
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package cmd
+
+import (
+	"fmt"
+	"runtime/debug"
+
+	"github.com/kr/pretty"
+	"github.com/spf13/cobra"
+)
+
+// versionCmd represents the version command
+var versionCmd = &cobra.Command{
+	Use:   "version",
+	Short: "A brief description of your command",
+	Long: `A longer description that spans multiple lines and likely contains examples
+and usage of using your command. For example:
+
+Cobra is a CLI library for Go that empowers applications.
+This application is a tool to generate the needed files
+to quickly create a Cobra application.`,
+	Run: func(cmd *cobra.Command, args []string) {
+		long, _ := cmd.Flags().GetBool("long")
+		if long {
+			info, _ := debug.ReadBuildInfo()
+			pretty.Println(info.Settings)
+		}
+		fmt.Println("\nnm-install v1.0.0")
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(versionCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// versionCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	versionCmd.Flags().BoolP("long", "l", false, "additional details")
+}

+ 3 - 0
pkg/nm-install/go.mod

@@ -0,0 +1,3 @@
+module github.com/gravitl/netclient/pkg/nm-install
+
+go 1.21.1

+ 22 - 0
pkg/nm-install/main.go

@@ -0,0 +1,22 @@
+/*
+Copyright © 2023 Netmaker Team
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package main
+
+import "github.com/gravitl/netmaker/pkg/nm-install/cmd"
+
+func main() {
+	cmd.Execute()
+}

+ 0 - 941
scripts/nm-quick.sh

@@ -1,941 +0,0 @@
-#!/bin/bash
-
-CONFIG_FILE=netmaker.env
-# location of nm-quick.sh (usually `/root`)
-SCRIPT_DIR=$(dirname "$(realpath "$0")")
-CONFIG_PATH="$SCRIPT_DIR/$CONFIG_FILE"
-NM_QUICK_VERSION="0.1.1"
-LATEST=$(curl -s https://api.github.com/repos/gravitl/netmaker/releases/latest | grep "tag_name" | cut -d : -f 2,3 | tr -d [:space:],\")
-
-if [ $(id -u) -ne 0 ]; then
-	echo "This script must be run as root"
-	exit 1
-fi
-
-unset INSTALL_TYPE
-unset BUILD_TYPE
-unset BUILD_TAG
-unset IMAGE_TAG
-unset AUTO_BUILD
-unset NETMAKER_BASE_DOMAIN
-
-# usage - displays usage instructions
-usage() {
-	echo "nm-quick.sh v$NM_QUICK_VERSION"
-	echo "usage: ./nm-quick.sh [-e] [-b buildtype] [-t tag] [-a auto] [-d domain]"
-	echo "  -e      if specified, will install netmaker pro"
-	echo "  -b      type of build; options:"
-	echo "          \"version\" - will install a specific version of Netmaker using remote git and dockerhub"
-	echo "          \"local\": - will install by cloning repo and building images from git"
-	echo "          \"branch\": - will install a specific branch using remote git and dockerhub"
-	echo "  -t      tag of build; if buildtype=version, tag=version. If builtype=branch or builtype=local, tag=branch"
-	echo "  -a      auto-build; skip prompts and use defaults, if none provided"
-	echo "  -d      domain; if specified, will use this domain instead of auto-generating one"
-	echo "examples:"
-	echo "          nm-quick.sh -e -b version -t $LATEST"
-	echo "          nm-quick.sh -e -b local -t feature_v0.17.2_newfeature"
-	echo "          nm-quick.sh -e -b branch -t develop"
-	echo "          nm-quick.sh -e -b version -t $LATEST -a -d example.com"
-	exit 1
-}
-
-while getopts evab:d:t: flag; do
-	case "${flag}" in
-	e)
-		INSTALL_TYPE="pro"
-		UPGRADE_FLAG="yes"
-		;;
-	v)
-		usage
-		exit 0
-		;;
-	a)
-		AUTO_BUILD="on"
-		;;
-	b)
-		BUILD_TYPE=${OPTARG}
-		if [[ ! "$BUILD_TYPE" =~ ^(version|local|branch)$ ]]; then
-			echo "error: $BUILD_TYPE is invalid"
-			echo "valid options: version, local, branch"
-			usage
-			exit 1
-		fi
-		;;
-	t)
-		BUILD_TAG=${OPTARG}
-		;;
-	d)
-		NETMAKER_BASE_DOMAIN=${OPTARG}
-		;;
-	esac
-done
-
-# print_logo - prints the netmaker logo
-print_logo() {
-	cat <<"EOF"
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-                                                                                         
- __   __     ______     ______   __    __     ______     __  __     ______     ______    
-/\ "-.\ \   /\  ___\   /\__  _\ /\ "-./  \   /\  __ \   /\ \/ /    /\  ___\   /\  == \   
-\ \ \-.  \  \ \  __\   \/_/\ \/ \ \ \-./\ \  \ \  __ \  \ \  _"-.  \ \  __\   \ \  __<   
- \ \_\\"\_\  \ \_____\    \ \_\  \ \_\ \ \_\  \ \_\ \_\  \ \_\ \_\  \ \_____\  \ \_\ \_\ 
-  \/_/ \/_/   \/_____/     \/_/   \/_/  \/_/   \/_/\/_/   \/_/\/_/   \/_____/   \/_/ /_/ 
-                                                                                                                                                                                                 
-
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-EOF
-}
-
-# set_buildinfo - sets the information based on script input for how the installation should be run
-set_buildinfo() {
-
-	if [ -z "$BUILD_TYPE" ]; then
-		BUILD_TYPE="version"
-		BUILD_TAG=$LATEST
-	fi
-
-	if [ -z "$BUILD_TAG" ] && [ "$BUILD_TYPE" = "version" ]; then
-		BUILD_TAG=$LATEST
-	fi
-
-	if [ -z "$BUILD_TAG" ] && [ ! -z "$BUILD_TYPE" ]; then
-		echo "error: must specify build tag when build type \"$BUILD_TYPE\" is specified"
-		usage
-		exit 1
-	fi
-
-	IMAGE_TAG=$(sed 's/\//-/g' <<<"$BUILD_TAG")
-
-	if [ "$1" = "ce" ]; then
-		INSTALL_TYPE="ce"
-	elif [ "$1" = "pro" ]; then
-		INSTALL_TYPE="pro"
-	fi
-
-	if [ "$AUTO_BUILD" = "on" ] && [ -z "$INSTALL_TYPE" ]; then
-		INSTALL_TYPE="ce"
-	elif [ -z "$INSTALL_TYPE" ]; then
-		echo "-----------------------------------------------------"
-		echo "Would you like to install Netmaker Community Edition (CE), or Netmaker Enterprise Edition (pro)?"
-		echo "pro will require you to create an account at https://app.netmaker.io"
-		echo "-----------------------------------------------------"
-		select install_option in "Community Edition" "Enterprise Edition"; do
-			case $REPLY in
-			1)
-				echo "installing Netmaker CE"
-				INSTALL_TYPE="ce"
-				break
-				;;
-			2)
-				echo "installing Netmaker pro"
-				INSTALL_TYPE="pro"
-				break
-				;;
-			*) echo "invalid option $REPLY" ;;
-			esac
-		done
-	fi
-	echo "-----------Build Options-----------------------------"
-	echo "   Pro or CE: $INSTALL_TYPE"
-	echo "  Build Type: $BUILD_TYPE"
-	echo "   Build Tag: $BUILD_TAG"
-	echo "   Image Tag: $IMAGE_TAG"
-	echo "   Installer: v$NM_QUICK_VERSION"
-	echo "-----------------------------------------------------"
-
-}
-
-# install_yq - install yq if not present
-install_yq() {
-	if ! command -v yq &>/dev/null; then
-		wget -qO /usr/bin/yq https://github.com/mikefarah/yq/releases/download/v4.31.1/yq_linux_$(dpkg --print-architecture)
-		chmod +x /usr/bin/yq
-	fi
-	set +e
-	if ! command -v yq &>/dev/null; then
-		set -e
-		wget -qO /usr/bin/yq https://github.com/mikefarah/yq/releases/download/v4.31.1/yq_linux_amd64
-		chmod +x /usr/bin/yq
-	fi
-	set -e
-	if ! command -v yq &>/dev/null; then
-		echo "failed to install yq. Please install yq and try again."
-		echo "https://github.com/mikefarah/yq/#install"
-		exit 1
-	fi
-}
-
-# setup_netclient - adds netclient to docker-compose
-setup_netclient() {
-
-	set +e
-	netclient uninstall
-	set -e
-
-	wget -qO netclient https://github.com/gravitl/netclient/releases/download/$LATEST/netclient-linux-$ARCH
-	chmod +x netclient
-	./netclient install
-	echo "Register token: $TOKEN"
-	netclient register -t $TOKEN
-
-	echo "waiting for netclient to become available"
-	local found=false
-	local file=/etc/netclient/nodes.yml
-	for ((a = 1; a <= 90; a++)); do
-		if [ -f "$file" ]; then
-			found=true
-			break
-		fi
-		sleep 1
-	done
-
-	if [ "$found" = false ]; then
-		echo "Error - $file not present"
-		exit 1
-	fi
-}
-
-# configure_netclient - configures server's netclient as a default host and an ingress gateway
-configure_netclient() {
-
-	NODE_ID=$(sudo cat /etc/netclient/nodes.yml | yq -r .netmaker.commonnode.id)
-	if [ "$NODE_ID" = "" ] || [ "$NODE_ID" = "null" ]; then
-		echo "Error obtaining NODE_ID for the new network"
-		exit 1
-	fi
-	echo "register complete. New node ID: $NODE_ID"
-	HOST_ID=$(sudo cat /etc/netclient/netclient.yml | yq -r .host.id)
-	if [ "$HOST_ID" = "" ] || [ "$HOST_ID" = "null" ]; then
-		echo "Error obtaining HOST_ID for the new network"
-		exit 1
-	fi
-	echo "making host a default"
-	echo "Host ID: $HOST_ID"
-	# set as a default host
-	set +e
-	nmctl host update $HOST_ID --default
-	sleep 5
-	nmctl node create_ingress netmaker $NODE_ID
-	set -e
-}
-
-# setup_nmctl - pulls nmctl and makes it executable
-setup_nmctl() {
-
-	local URL="https://github.com/gravitl/netmaker/releases/download/$LATEST/nmctl-linux-$ARCH"
-	echo "Downloading nmctl..."
-	wget -qO /usr/bin/nmctl "$URL"
-
-	if [ ! -f /usr/bin/nmctl ]; then
-		echo "Error downloading nmctl from '$URL'"
-		exit 1
-	fi
-
-	chmod +x /usr/bin/nmctl
-	echo "using server api.$NETMAKER_BASE_DOMAIN"
-	echo "using master key $MASTER_KEY"
-	nmctl context set default --endpoint="https://api.$NETMAKER_BASE_DOMAIN" --master_key="$MASTER_KEY"
-	nmctl context use default
-	RESP=$(nmctl network list)
-	if [[ $RESP == *"unauthorized"* ]]; then
-		echo "Unable to properly configure NMCTL, exiting..."
-		exit 1
-	fi
-}
-
-# wait_seconds - wait for the specified period of time
-wait_seconds() { (
-	for ((a = 1; a <= $1; a++)); do
-		echo ". . ."
-		sleep 1
-	done
-); }
-
-# confirm - get user input to confirm that they want to perform the next step
-confirm() { (
-	if [ "$AUTO_BUILD" = "on" ]; then
-		return 0
-	fi
-	while true; do
-		read -p 'Does everything look right? [y/n]: ' yn
-		case $yn in
-		[Yy]*)
-			override="true"
-			break
-			;;
-		[Nn]*)
-			echo "exiting..."
-			exit 1
-			# TODO start from the beginning instead
-			;;
-		*) echo "Please answer yes or no." ;;
-		esac
-	done
-) }
-
-save_config() { (
-	echo "Saving the config to $CONFIG_PATH"
-	touch "$CONFIG_PATH"
-	save_config_item NM_EMAIL "$EMAIL"
-	save_config_item NM_DOMAIN "$NETMAKER_BASE_DOMAIN"
-	save_config_item UI_IMAGE_TAG "$IMAGE_TAG"
-	if [ "$BUILD_TYPE" = "local" ]; then
-		save_config_item UI_IMAGE_TAG "$LATEST"
-	else
-		save_config_item UI_IMAGE_TAG "$IMAGE_TAG"
-	fi
-	# version-specific entries
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-		save_config_item NETMAKER_TENANT_ID "$TENANT_ID"
-		save_config_item LICENSE_KEY "$LICENSE_KEY"
-		save_config_item METRICS_EXPORTER "on"
-		save_config_item PROMETHEUS "on"
-		if [ "$BUILD_TYPE" = "version" ]; then
-			save_config_item SERVER_IMAGE_TAG "$IMAGE_TAG-ee"
-		else
-			save_config_item SERVER_IMAGE_TAG "$IMAGE_TAG"
-		fi
-	else
-		save_config_item METRICS_EXPORTER "off"
-		save_config_item PROMETHEUS "off"
-		save_config_item SERVER_IMAGE_TAG "$IMAGE_TAG"
-	fi
-	# copy entries from the previous config
-	local toCopy=("SERVER_HOST" "MASTER_KEY" "TURN_USERNAME" "TURN_PASSWORD" "MQ_USERNAME" "MQ_PASSWORD"
-		"INSTALL_TYPE" "NODE_ID" "DNS_MODE" "NETCLIENT_AUTO_UPDATE" "API_PORT"
-		"CORS_ALLOWED_ORIGIN" "DISPLAY_KEYS" "DATABASE" "SERVER_BROKER_ENDPOINT" "STUN_PORT" "VERBOSITY"
-		"TURN_PORT" "USE_TURN" "DEBUG_MODE" "TURN_API_PORT" "REST_BACKEND"
-		"DISABLE_REMOTE_IP_CHECK" "NETCLIENT_ENDPOINT_DETECTION" "TELEMETRY" "AUTH_PROVIDER" "CLIENT_ID" "CLIENT_SECRET"
-		"FRONTEND_URL" "AZURE_TENANT" "OIDC_ISSUER" "EXPORTER_API_PORT")
-	for name in "${toCopy[@]}"; do
-		save_config_item $name "${!name}"
-	done
-	# preserve debug entries
-	if test -n "$NM_SKIP_BUILD"; then
-		save_config_item NM_SKIP_BUILD "$NM_SKIP_BUILD"
-	fi
-	if test -n "$NM_SKIP_CLONE"; then
-		save_config_item NM_SKIP_CLONE "$NM_SKIP_CLONE"
-	fi
-	if test -n "$NM_SKIP_DEPS"; then
-		save_config_item NM_SKIP_DEPS "$NM_SKIP_DEPS"
-	fi
-); }
-
-save_config_item() { (
-	local NAME="$1"
-	local VALUE="$2"
-	#echo "$NAME=$VALUE"
-	if test -z "$VALUE"; then
-		# load the default for empty values
-		VALUE=$(awk -F'=' "/^$NAME/ { print \$2}"  "$SCRIPT_DIR/netmaker.default.env")
-		# trim quotes for docker
-		VALUE=$(echo "$VALUE" | sed -E "s|^(['\"])(.*)\1$|\2|g")
-		#echo "Default for $NAME=$VALUE"
-	fi
-	# TODO single quote passwords
-	if grep -q "^$NAME=" "$CONFIG_PATH"; then
-		# TODO escape | in the value
-		sed -i "s|$NAME=.*|$NAME=$VALUE|" "$CONFIG_PATH"
-	else
-		echo "$NAME=$VALUE" >>"$CONFIG_PATH"
-	fi
-); }
-
-# local_install_setup - builds artifacts based on specified branch locally to use in install
-local_install_setup() { (
-	if test -z "$NM_SKIP_CLONE"; then
-		rm -rf netmaker-tmp
-		mkdir netmaker-tmp
-		cd netmaker-tmp
-		git clone --single-branch --depth=1 --branch=$BUILD_TAG https://www.github.com/gravitl/netmaker
-	else
-		cd netmaker-tmp
-		echo "Skipping git clone on NM_SKIP_CLONE"
-	fi
-	cd netmaker
-	if test -z "$NM_SKIP_BUILD"; then
-		docker build --no-cache --build-arg version=$IMAGE_TAG -t gravitl/netmaker:$IMAGE_TAG .
-	else
-		echo "Skipping build on NM_SKIP_BUILD"
-	fi
-	cp compose/docker-compose.yml "$SCRIPT_DIR/docker-compose.yml"
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-		cp compose/docker-compose.ee.yml "$SCRIPT_DIR/docker-compose.override.yml"
-		cp docker/Caddyfile-pro "$SCRIPT_DIR/Caddyfile"
-	else
-		cp docker/Caddyfile "$SCRIPT_DIR/Caddyfile"
-	fi
-	cp scripts/nm-certs.sh "$SCRIPT_DIR/nm-certs.sh"
-	cp scripts/netmaker.default.env "$SCRIPT_DIR/netmaker.default.env"
-	cp docker/mosquitto.conf "$SCRIPT_DIR/mosquitto.conf"
-	cp docker/wait.sh "$SCRIPT_DIR/wait.sh"
-	cd ../../
-	if test -z "$NM_SKIP_CLONE"; then
-		rm -rf netmaker-tmp
-	fi
-); }
-
-# install_dependencies - install necessary packages to run netmaker
-install_dependencies() {
-
-	if test -n "$NM_SKIP_DEPS"; then
-		return
-	fi
-
-	echo "checking dependencies..."
-
-	OS=$(uname)
-	if [ -f /etc/debian_version ]; then
-		dependencies="git wireguard wireguard-tools dnsutils jq docker.io docker-compose grep gawk"
-		update_cmd='apt update'
-		install_cmd='apt-get install -y'
-	elif [ -f /etc/alpine-release ]; then
-		dependencies="git wireguard jq docker.io docker-compose grep gawk"
-		update_cmd='apk update'
-		install_cmd='apk --update add'
-	elif [ -f /etc/centos-release ]; then
-		dependencies="git wireguard jq bind-utils docker.io docker-compose grep gawk"
-		update_cmd='yum update'
-		install_cmd='yum install -y'
-	elif [ -f /etc/fedora-release ]; then
-		dependencies="git wireguard bind-utils jq docker.io docker-compose grep gawk"
-		update_cmd='dnf update'
-		install_cmd='dnf install -y'
-	elif [ -f /etc/redhat-release ]; then
-		dependencies="git wireguard jq docker.io bind-utils docker-compose grep gawk"
-		update_cmd='yum update'
-		install_cmd='yum install -y'
-	elif [ -f /etc/arch-release ]; then
-		dependencies="git wireguard-tools dnsutils jq docker.io docker-compose grep gawk"
-		update_cmd='pacman -Sy'
-		install_cmd='pacman -S --noconfirm'
-	elif [ "${OS}" = "FreeBSD" ]; then
-		dependencies="git wireguard wget jq docker.io docker-compose grep gawk"
-		update_cmd='pkg update'
-		install_cmd='pkg install -y'
-	else
-		install_cmd=''
-	fi
-
-	if [ -z "${install_cmd}" ]; then
-		echo "OS unsupported for automatic dependency install"
-		# TODO shouldnt exit, check if deps available, if not
-		#  ask the user to install manually and continue when ready
-		exit 1
-	fi
-	# TODO add other supported architectures
-	ARCH=$(uname -m)
-    if [ "$ARCH" = "x86_64" ]; then
-    	ARCH=amd64
-    elif [ "$ARCH" = "aarch64" ]; then
-    	ARCH=arm64
-    else
-    	echo "Unsupported architechure"
-    	# exit 1
-    fi
-	set -- $dependencies
-
-	${update_cmd}
-
-	while [ -n "$1" ]; do
-		if [ "${OS}" = "FreeBSD" ]; then
-			is_installed=$(pkg check -d $1 | grep "Checking" | grep "done")
-			if [ "$is_installed" != "" ]; then
-				echo "  " $1 is installed
-			else
-				echo "  " $1 is not installed. Attempting install.
-				${install_cmd} $1
-				sleep 5
-				is_installed=$(pkg check -d $1 | grep "Checking" | grep "done")
-				if [ "$is_installed" != "" ]; then
-					echo "  " $1 is installed
-				elif [ -x "$(command -v $1)" ]; then
-					echo "  " $1 is installed
-				else
-					echo "  " FAILED TO INSTALL $1
-					echo "  " This may break functionality.
-				fi
-			fi
-		else
-			if [ "${OS}" = "OpenWRT" ] || [ "${OS}" = "TurrisOS" ]; then
-				is_installed=$(opkg list-installed $1 | grep $1)
-			else
-				is_installed=$(dpkg-query -W --showformat='${Status}\n' $1 | grep "install ok installed")
-			fi
-			if [ "${is_installed}" != "" ]; then
-				echo "    " $1 is installed
-			else
-				echo "    " $1 is not installed. Attempting install.
-				${install_cmd} $1
-				sleep 5
-				if [ "${OS}" = "OpenWRT" ] || [ "${OS}" = "TurrisOS" ]; then
-					is_installed=$(opkg list-installed $1 | grep $1)
-				else
-					is_installed=$(dpkg-query -W --showformat='${Status}\n' $1 | grep "install ok installed")
-				fi
-				if [ "${is_installed}" != "" ]; then
-					echo "    " $1 is installed
-				elif [ -x "$(command -v $1)" ]; then
-					echo "  " $1 is installed
-				else
-					echo "  " FAILED TO INSTALL $1
-					echo "  " This may break functionality.
-				fi
-			fi
-		fi
-		shift
-	done
-
-	echo "-----------------------------------------------------"
-	echo "dependency check complete"
-	echo "-----------------------------------------------------"
-}
-set -e
-
-# set_install_vars - sets the variables that will be used throughout installation
-set_install_vars() {
-
-	IP_ADDR=$(dig -4 myip.opendns.com @resolver1.opendns.com +short)
-	if [ "$IP_ADDR" = "" ]; then
-		IP_ADDR=$(curl -s ifconfig.me)
-	fi
-	if [ "$NETMAKER_BASE_DOMAIN" = "" ]; then
-		NETMAKER_BASE_DOMAIN=nm.$(echo $IP_ADDR | tr . -).nip.io
-	fi
-	SERVER_HOST=$IP_ADDR
-	if test -z "$MASTER_KEY"; then
-		MASTER_KEY=$(
-			tr -dc A-Za-z0-9 </dev/urandom | head -c 30
-			echo ''
-		)
-	fi
-	DOMAIN_TYPE=""
-	echo "-----------------------------------------------------"
-	echo "Would you like to use your own domain for netmaker, or an auto-generated domain?"
-	echo "To use your own domain, add a Wildcard DNS record (e.x: *.netmaker.example.com) pointing to $SERVER_HOST"
-	echo "IMPORTANT: Due to the high volume of requests, the auto-generated domain has been rate-limited by the certificate provider."
-	echo "For this reason, we STRONGLY RECOMMEND using your own domain. Using the auto-generated domain may lead to a failed installation due to rate limiting."
-	echo "-----------------------------------------------------"
-
-	if [ "$AUTO_BUILD" = "on" ]; then
-		DOMAIN_TYPE="auto"
-	else
-		select domain_option in "Auto Generated ($NETMAKER_BASE_DOMAIN)" "Custom Domain (e.x: netmaker.example.com)"; do
-			case $REPLY in
-			1)
-				echo "using $NETMAKER_BASE_DOMAIN for base domain"
-				DOMAIN_TYPE="auto"
-				break
-				;;
-			2)
-				read -p "Enter Custom Domain (make sure  *.domain points to $SERVER_HOST first): " domain
-				NETMAKER_BASE_DOMAIN=$domain
-				echo "using $NETMAKER_BASE_DOMAIN"
-				DOMAIN_TYPE="custom"
-				break
-				;;
-			*) echo "invalid option $REPLY" ;;
-			esac
-		done
-	fi
-
-	wait_seconds 2
-
-	echo "-----------------------------------------------------"
-	echo "The following subdomains will be used:"
-	echo "          dashboard.$NETMAKER_BASE_DOMAIN"
-	echo "                api.$NETMAKER_BASE_DOMAIN"
-	echo "             broker.$NETMAKER_BASE_DOMAIN"
-	echo "               turn.$NETMAKER_BASE_DOMAIN"
-	echo "            turnapi.$NETMAKER_BASE_DOMAIN"
-
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-		echo "         prometheus.$NETMAKER_BASE_DOMAIN"
-		echo "  netmaker-exporter.$NETMAKER_BASE_DOMAIN"
-		echo "            grafana.$NETMAKER_BASE_DOMAIN"
-	fi
-
-	echo "-----------------------------------------------------"
-
-	if [[ "$DOMAIN_TYPE" == "custom" ]]; then
-		echo "before continuing, confirm DNS is configured correctly, with records pointing to $SERVER_HOST"
-		confirm
-	fi
-
-	wait_seconds 1
-
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-
-		echo "-----------------------------------------------------"
-		echo "Provide Details for pro installation:"
-		echo "    1. Log into https://app.netmaker.io"
-		echo "    2. follow instructions to get a license at: https://docs.netmaker.io/ee/ee-setup.html"
-		echo "    3. Retrieve License and Tenant ID"
-		echo "    4. note email address"
-		echo "-----------------------------------------------------"
-		unset LICENSE_KEY
-		while [ -z "$LICENSE_KEY" ]; do
-			read -p "License Key: " LICENSE_KEY
-		done
-		unset TENANT_ID
-		while [ -z ${TENANT_ID} ]; do
-			read -p "Tenant ID: " TENANT_ID
-		done
-	fi
-
-	unset GET_EMAIL
-	unset RAND_EMAIL
-	RAND_EMAIL="$(echo $RANDOM | md5sum | head -c 16)@email.com"
-	# suggest the prev email or a random one
-	EMAIL_SUGGESTED=${NM_EMAIL:-$RAND_EMAIL}
-	if [ -z $AUTO_BUILD ]; then
-		read -p "Email Address for Domain Registration (click 'enter' to use $EMAIL_SUGGESTED): " GET_EMAIL
-	fi
-	if [ -z "$GET_EMAIL" ]; then
-		EMAIL="$EMAIL_SUGGESTED"
-		if [ "$EMAIL" = "$NM_EMAIL" ]; then
-			echo "using config email"
-		else
-			echo "using rand email"
-		fi
-	else
-		EMAIL="$GET_EMAIL"
-	fi
-
-	wait_seconds 1
-
-	unset GET_MQ_USERNAME
-	unset GET_MQ_PASSWORD
-	unset CONFIRM_MQ_PASSWORD
-	echo "Enter Credentials For MQ..."
-	if [ -z $AUTO_BUILD ]; then
-		read -p "MQ Username (click 'enter' to use 'netmaker'): " GET_MQ_USERNAME
-	fi
-	if [ -z "$GET_MQ_USERNAME" ]; then
-		echo "using default username for mq"
-		MQ_USERNAME="netmaker"
-	else
-		MQ_USERNAME="$GET_MQ_USERNAME"
-	fi
-
-	if test -z "$MQ_PASSWORD"; then
-		MQ_PASSWORD=$(
-			tr -dc A-Za-z0-9 </dev/urandom | head -c 30
-			echo ''
-		)
-	fi
-
-	if [ -z $AUTO_BUILD ]; then
-		select domain_option in "Auto Generated / Config Password" "Input Your Own Password"; do
-			case $REPLY in
-			1)
-				echo "using random password for mq"
-				break
-				;;
-			2)
-				while true; do
-					echo "Enter your Password For MQ: "
-					read -s GET_MQ_PASSWORD
-					echo "Enter your password again to confirm: "
-					read -s CONFIRM_MQ_PASSWORD
-					if [ ${GET_MQ_PASSWORD} != ${CONFIRM_MQ_PASSWORD} ]; then
-						echo "wrong password entered, try again..."
-						continue
-					fi
-					MQ_PASSWORD="$GET_MQ_PASSWORD"
-					echo "MQ Password Saved Successfully!!"
-					break
-				done
-				break
-				;;
-			*) echo "invalid option $REPLY" ;;
-			esac
-		done
-	fi
-
-	unset GET_TURN_USERNAME
-	unset GET_TURN_PASSWORD
-	unset CONFIRM_TURN_PASSWORD
-	echo "Enter Credentials For TURN..."
-	if [ -z $AUTO_BUILD ]; then
-		read -p "TURN Username (click 'enter' to use 'netmaker'): " GET_TURN_USERNAME
-	fi
-	if [ -z "$GET_TURN_USERNAME" ]; then
-		echo "using default username for TURN"
-		TURN_USERNAME="netmaker"
-	else
-		TURN_USERNAME="$GET_TURN_USERNAME"
-	fi
-
-	if test -z "$TURN_PASSWORD"; then
-		TURN_PASSWORD=$(
-			tr -dc A-Za-z0-9 </dev/urandom | head -c 30
-			echo ''
-		)
-	fi
-
-	if [ -z $AUTO_BUILD ]; then
-		select domain_option in "Auto Generated / Config Password" "Input Your Own Password"; do
-			case $REPLY in
-			1)
-				echo "using random password for turn"
-				break
-				;;
-			2)
-				while true; do
-					echo "Enter your Password For TURN: "
-					read -s GET_TURN_PASSWORD
-					echo "Enter your password again to confirm: "
-					read -s CONFIRM_TURN_PASSWORD
-					if [ ${GET_TURN_PASSWORD} != ${CONFIRM_TURN_PASSWORD} ]; then
-						echo "wrong password entered, try again..."
-						continue
-					fi
-					TURN_PASSWORD="$GET_TURN_PASSWORD"
-					echo "TURN Password Saved Successfully!!"
-					break
-				done
-				break
-				;;
-			*) echo "invalid option $REPLY" ;;
-			esac
-		done
-	fi
-
-	wait_seconds 2
-
-	echo "-----------------------------------------------------------------"
-	echo "                SETUP ARGUMENTS"
-	echo "-----------------------------------------------------------------"
-	echo "        domain: $NETMAKER_BASE_DOMAIN"
-	echo "         email: $EMAIL"
-	echo "     public ip: $SERVER_HOST"
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-		echo "       license: $LICENSE_KEY"
-		echo "    account id: $TENANT_ID"
-	fi
-	echo "-----------------------------------------------------------------"
-	echo "Confirm Settings for Installation"
-	echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
-
-	if [ ! "$BUILD_TYPE" = "local" ]; then
-		IMAGE_TAG="$LATEST"
-	fi
-
-	confirm
-}
-
-# install_netmaker - sets the config files and starts docker-compose
-install_netmaker() {
-
-	echo "-----------------------------------------------------------------"
-	echo "Beginning installation..."
-	echo "-----------------------------------------------------------------"
-
-	wait_seconds 3
-
-	echo "Pulling config files..."
-
-	if [ "$BUILD_TYPE" = "local" ]; then
-		local_install_setup
-	else
-		local BASE_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG"
-
-		local COMPOSE_URL="$BASE_URL/compose/docker-compose.yml"
-		local CADDY_URL="$BASE_URL/docker/Caddyfile"
-		if [ "$INSTALL_TYPE" = "pro" ]; then
-			local COMPOSE_OVERRIDE_URL="$BASE_URL/compose/docker-compose.pro.yml"
-			local CADDY_URL="$BASE_URL/docker/Caddyfile-pro"
-		fi
-		wget -qO "$SCRIPT_DIR"/docker-compose.yml $COMPOSE_URL
-		if test -n "$COMPOSE_OVERRIDE_URL"; then
-			wget -qO "$SCRIPT_DIR"/docker-compose.override.yml $COMPOSE_OVERRIDE_URL
-		fi
-		wget -qO "$SCRIPT_DIR"/Caddyfile "$CADDY_URL"
-		wget -qO "$SCRIPT_DIR"/netmaker.default.env "$BASE_URL/scripts/netmaker.default.env"
-		wget -qO "$SCRIPT_DIR"/mosquitto.conf "$BASE_URL/docker/mosquitto.conf"
-		wget -qO "$SCRIPT_DIR"/nm-certs.sh "$BASE_URL/scripts/nm-certs.sh"
-		wget -qO "$SCRIPT_DIR"/wait.sh "$BASE_URL/docker/wait.sh"
-	fi
-
-	chmod +x "$SCRIPT_DIR"/wait.sh
-	mkdir -p /etc/netmaker
-
-	# link .env to the user config
-	ln -fs "$SCRIPT_DIR/netmaker.env" "$SCRIPT_DIR/.env"
-	save_config
-
-	# Fetch / update certs using certbot
-	chmod +x "$SCRIPT_DIR"/nm-certs.sh
-	"$SCRIPT_DIR"/nm-certs.sh
-
-	echo "Starting containers..."
-
-	# increase the timeouts
-	export DOCKER_CLIENT_TIMEOUT=120
-	export COMPOSE_HTTP_TIMEOUT=120
-
-	# start docker and rebuild containers / networks
-	docker-compose -f "$SCRIPT_DIR"/docker-compose.yml up -d --force-recreate
-
-	wait_seconds 2
-
-}
-
-# test_connection - tests to make sure Caddy has proper SSL certs
-test_connection() {
-
-	echo "Testing Caddy setup (please be patient, this may take 1-2 minutes)"
-	for i in 1 2 3 4 5 6 7 8; do
-		curlresponse=$(curl -vIs https://api.${NETMAKER_BASE_DOMAIN} 2>&1)
-
-		if [[ "$i" == 8 ]]; then
-			echo "    Caddy is having an issue setting up certificates, please investigate (docker logs caddy)"
-			echo "    Exiting..."
-			exit 1
-		elif [[ "$curlresponse" == *"failed to verify the legitimacy of the server"* ]]; then
-			echo "    Certificates not yet configured, retrying..."
-
-		elif [[ "$curlresponse" == *"left intact"* ]]; then
-			echo "    Certificates ok"
-			break
-		else
-			secs=$(($i * 5 + 10))
-			echo "    Issue establishing connection...retrying in $secs seconds..."
-		fi
-		sleep $secs
-	done
-
-}
-
-# setup_mesh - sets up a default mesh network on the server
-setup_mesh() {
-
-	wait_seconds 5
-
-	local networkCount=$(nmctl network list -o json | jq '. | length')
-
-	# add a network if none present
-	if [ "$networkCount" -lt 1 ]; then
-		echo "Creating netmaker network (10.101.0.0/16)"
-
-		# TODO causes "Error Status: 400 Response: {"Code":400,"Message":"could not find any records"}"
-		nmctl network create --name netmaker --ipv4_addr 10.101.0.0/16
-
-		wait_seconds 5
-	fi
-
-	echo "Obtaining a netmaker enrollment key..."
-
-	local tokenJson=$(nmctl enrollment_key create --unlimited --networks netmaker)
-	TOKEN=$(jq -r '.token' <<<${tokenJson})
-	if test -z "$TOKEN"; then
-		echo "Error creating an enrollment key"
-		exit 1
-	else
-		echo "Enrollment key ready"
-	fi
-
-	wait_seconds 3
-
-}
-
-# print_success - prints a success message upon completion
-print_success() {
-	echo "-----------------------------------------------------------------"
-	echo "-----------------------------------------------------------------"
-	echo "Netmaker setup is now complete. You are ready to begin using Netmaker."
-	echo "Visit dashboard.$NETMAKER_BASE_DOMAIN to log in"
-	echo "-----------------------------------------------------------------"
-	echo "-----------------------------------------------------------------"
-}
-
-cleanup() {
-	# remove the existing netclient's instance from the existing network
-	if command -v nmctl >/dev/null 2>&1; then
-		local node_id=$(netclient list | jq '.[0].node_id' 2>/dev/null)
-		# trim doublequotes
-		node_id="${node_id//\"/}"
-		if test -n "$node_id"; then
-			echo "De-registering the existing netclient..."
-			nmctl node delete netmaker $node_id >/dev/null 2>&1
-		fi
-	fi
-
-	echo "Stopping all containers..."
-	local containers=("mq" "netmaker-ui" "coredns" "turn" "caddy" "netmaker" "netmaker-exporter" "prometheus" "grafana")
-	for name in "${containers[@]}"; do
-		local running=$(docker ps | grep -w "$name")
-		local exists=$(docker ps -a | grep -w "$name")
-		if test -n "$running"; then
-			docker stop "$name" 1>/dev/null
-		fi
-		if test -n "$exists"; then
-			docker rm "$name" 1>/dev/null
-		fi
-	done
-}
-
-# 1. print netmaker logo
-print_logo
-
-# read the config
-if [ -f "$CONFIG_PATH" ]; then
-	echo "Using config: $CONFIG_PATH"
-	source "$CONFIG_PATH"
-	if [ "$UPGRADE_FLAG" = "yes" ]; then
-		INSTALL_TYPE="pro"
-	fi
-fi
-
-# 2. setup the build instructions
-set_buildinfo
-
-set +e
-
-# 3. install necessary packages
-install_dependencies
-
-# 4. install yq if necessary
-install_yq
-
-set -e
-
-# 6. get user input for variables
-set_install_vars
-
-set +e
-cleanup
-set -e
-
-# 7. get and set config files, startup docker-compose
-install_netmaker
-
-set +e
-
-# 8. make sure Caddy certs are working
-test_connection
-
-# 9. install the netmaker CLI
-setup_nmctl
-
-# 10. create a default mesh network for netmaker
-setup_mesh
-
-set -e
-
-# 11. add netclient to docker-compose and start it up
-setup_netclient
-
-# 12. make the netclient a default host and ingress gw
-configure_netclient
-
-# 13. print success message
-print_success
-
-# cp -f /etc/skel/.bashrc /root/.bashrc

+ 0 - 796
scripts/nm-upgrade-0-17-1-to-0-19-0.sh

@@ -1,796 +0,0 @@
-#!/bin/bash
-
-LATEST="v0.21.1"
-INSTALL_PATH="/root"
-
-trap restore_old_netmaker_instructions
-
-# check_version - make sure current version is 0.17.1 before continuing
-check_version() {
-  IMG_TAG=$(yq -r '.services.netmaker.image' docker-compose.yml)
-
-  if [[ "$IMG_TAG" == *"v0.17.1"* ]]; then
-      echo "version is $IMG_TAG"
-  else
-      echo "error, current version is $IMG_TAG"
-      echo "please upgrade to v0.17.1 in order to use the upgrade script"
-      exit 1
-  fi
-}
-
-backup_v17_files() {
-  mkdir $INSTALL_PATH/netmaker_0.17.1_backup
-  cp $INSTALL_PATH/docker-compose.yml  $INSTALL_PATH/netmaker_0.17.1_backup/docker-compose.yml
-  cp $INSTALL_PATH/Caddyfile $INSTALL_PATH/netmaker_0.17.1_backup/Caddyfile
-  cp $INSTALL_PATH/mosquitto.conf $INSTALL_PATH/netmaker_0.17.1_backup/mosquitto.conf
-  cp $INSTALL_PATH/wait.sh $INSTALL_PATH/netmaker_0.17.1_backup/wait.sh
-}
-
-backup_volumes() {
-  # TODO backup to /root/nm-backup
-  cp -r /var/lib/docker/volumes/root_caddy_conf/ /var/lib/docker/volumes/root_caddy_conf-backup/
-  cp -r /var/lib/docker/volumes/root_caddy_data/ /var/lib/docker/volumes/root_caddy_data-backup/
-  cp -r /var/lib/docker/volumes/root_dnsconfig/ /var/lib/docker/volumes/root_dnsconfig-backup/
-  cp -r /var/lib/docker/volumes/root_mosquitto_data/ /var/lib/docker/volumes/root_mosquitto_data-backup/
-  cp -r /var/lib/docker/volumes/root_mosquitto_logs/ /var/lib/docker/volumes/root_mosquitto_logs-backup/
-  cp -r /var/lib/docker/volumes/root_sqldata/ /var/lib/docker/volumes/root_sqldata-backup/
-}
-
-restore_old_netmaker_instructions() {
-  echo "There was a problem with the installation. Your config files and volumes have been backed up."
-  echo "To restore Netmaker back to v0.17.1, copy all the netmaker volume backups (caddy_conf-backup, caddy_data-backup, dnsconfig-backup, mosquitto_data-backup, mosquitto_logs-backup, and sqldata-backup) back to their regular names with out the -backup."
-  echo "Your config files should be located in ${INSTALL_PATH}/netmaker_0.17.1_backup. Simply run cp ${INSTALL_PATH}/netmaker_0.17.1_backup/* . (include the .) and run docker-compose up -d."
-  echo "Your netmaker should be back to v0.17.1"
-}
-
-get_install_path() {
-  echo "-----------------------------------------------------"
-  echo "Is your docker-compose located in $INSTALL_PATH ?"
-  echo "-----------------------------------------------------"
-  select install_option in "yes" "no (enter manually)"; do
-    case $REPLY in
-      1)
-        echo "using $INSTALL_PATH for an installation path."
-      break
-        ;;      
-      2)
-        read -p "Enter path where your docker-compose is located: " install_path
-        SERVER_HTTP_HOST=$install_path
-        echo "using $INSTALL_PATH"
-        break
-        ;;
-      *) echo "invalid option $REPLY";;
-    esac
-  done
-}
-
-# wait_seconds - wait a number of seconds, print a log
-wait_seconds() {
-  for ((a=1; a <= $1; a++))
-  do
-    echo ". . ."
-    sleep 1
-  done
-}
-
-# confirm - confirm a choice, or exit script
-confirm() {
-  while true; do
-      read -p 'Does everything look right? [y/n]: ' yn
-      case $yn in
-          [Yy]* ) override="true"; break;;
-          [Nn]* ) echo "exiting..."; exit 1;;
-          * ) echo "Please answer yes or no.";;
-      esac
-  done
-}
-
-# install_dependencies - install system dependencies necessary for script to run
-install_dependencies() {
-  OS=$(uname)
-  if [ -f /etc/debian_version ]; then
-    dependencies="jq wireguard jq dnsutils docker-compose"
-    update_cmd='apt update'
-    install_cmd='apt install -y'
-  elif [ -f /etc/centos-release ]; then
-    dependencies="wireguard jq bind-utils docker-compose"
-    update_cmd='yum update'
-    install_cmd='yum install -y'
-  elif [ -f /etc/fedora-release ]; then
-    dependencies="wireguard jq bind-utils docker-compose"
-    update_cmd='dnf update'
-    install_cmd='dnf install -y'
-  elif [ -f /etc/redhat-release ]; then
-    dependencies="wireguard jq bind-utils docker-compose"
-    update_cmd='yum update'
-    install_cmd='yum install -y'
-  elif [ -f /etc/arch-release ]; then
-        dependencies="wireguard-tools jq dnsutils docker-compose netclient"
-    update_cmd='pacman -Sy'
-    install_cmd='pacman -S --noconfirm'
-  else
-    echo "OS not supported for automatic install"
-      exit 1
-  fi
-
-  set -- $dependencies
-
-  if command -v docker >/dev/null 2>&1 ; then
-    echo "Docker found"
-    echo "version: $(docker version)"
-  else
-    echo "Docker not found. adding to dependencies"
-    dependencies+=" docker.io"
-  fi
-
-  ${update_cmd}
-
-  set +e
-  while [ -n "$1" ]; do
-      is_installed=$(dpkg-query -W --showformat='${Status}\n' $1 | grep "install ok installed")
-      if [ "${is_installed}" != "" ]; then
-          echo "    " $1 is installed
-      else
-          echo "    " $1 is not installed. Attempting install.
-          ${install_cmd} $1
-          sleep 5
-          if [ "${OS}" = "OpenWRT" ] || [ "${OS}" = "TurrisOS" ]; then
-              is_installed=$(opkg list-installed $1 | grep $1)
-          else
-              is_installed=$(dpkg-query -W --showformat='${Status}\n' $1 | grep "install ok installed")
-          fi
-          if [ "${is_installed}" != "" ]; then
-              echo "    " $1 is installed
-          elif [ -x "$(command -v $1)" ]; then
-              echo "  " $1 is installed
-          else
-              echo "  " FAILED TO INSTALL $1
-              echo "  " This may break functionality.
-          fi
-      fi
-    shift
-  done
-  set -e
-  
-  echo "-----------------------------------------------------"
-  echo "dependency install complete"
-  echo "-----------------------------------------------------"
-}
-
-# install_yq - install yq if not present
-install_yq() {
-	if ! command -v yq &> /dev/null; then
-		wget -O /usr/bin/yq https://github.com/mikefarah/yq/releases/download/v4.31.1/yq_linux_$(dpkg --print-architecture)
-		chmod +x /usr/bin/yq
-	fi
-	set +e
-	if ! command -v yq &> /dev/null; then
-		set -e
-		wget -O /usr/bin/yq https://github.com/mikefarah/yq/releases/download/v4.31.1/yq_linux_amd64
-		chmod +x /usr/bin/yq
-	fi
-	set -e
-	if ! command -v yq &> /dev/null; then
-		echo "failed to install yq. Please install yq and try again."
-		echo "https://github.com/mikefarah/yq/#install"
-		exit 1
-	fi	
-}
-
-# collect_server_settings - retrieve server settings from existing compose file
-collect_server_settings() {
-  MASTER_KEY=$(yq -r .services.netmaker.environment.MASTER_KEY docker-compose.yml)
-  echo "-----------------------------------------------------"
-  echo "Is $MASTER_KEY the correct master key for your Netmaker installation?"
-  echo "-----------------------------------------------------"
-  select mkey_option in "yes" "no (enter manually)"; do
-    case $REPLY in
-      1)
-        echo "using $MASTER_KEY for master key"
-      break
-        ;;      
-      2)
-        read -p "Enter Master Key: " mkey
-        MASTER_KEY=$mkey
-        echo "using $MASTER_KEY"
-        break
-        ;;
-      *) echo "invalid option $REPLY, choose 1 or 2";;
-    esac
-  done
-
-  SERVER_HTTP_HOST=$(yq -r .services.netmaker.environment.SERVER_HTTP_HOST docker-compose.yml)
-  echo "-----------------------------------------------------"
-  echo "Is $SERVER_HTTP_HOST the correct api endpoint for your Netmaker installation?"
-  echo "-----------------------------------------------------"
-  select endpoint_option in "yes" "no (enter manually)"; do
-    case $REPLY in
-      1)
-        echo "using $SERVER_HTTP_HOST for api endpoint"
-      break
-        ;;      
-      2)
-        read -p "Enter API Endpoint: " endpoint
-        SERVER_HTTP_HOST=$endpoint
-        echo "using $SERVER_HTTP_HOST"
-        break
-        ;;
-      *) echo "invalid option $REPLY";;
-    esac
-  done
-
-  BROKER_NAME=$(yq -r .services.netmaker.environment.SERVER_NAME docker-compose.yml)
-  echo "-----------------------------------------------------"
-  echo "Is $BROKER_NAME the correct domain for your MQ broker?"
-  echo "-----------------------------------------------------"
-  select broker_option in "yes" "no (enter manually)"; do
-    case $REPLY in
-      1)
-        echo "using $BROKER_NAME for endpoint"
-      break
-        ;;      
-      2)
-        read -p "Enter Broker Domain: " broker
-        BROKER_NAME=$broker
-        echo "using $BROKER_NAME"
-        break
-        ;;
-      *) echo "invalid option $REPLY";;
-    esac
-  done
-
-  SERVER_NAME=${BROKER_NAME#"broker."}
-  echo "-----------------------------------------------------"
-  echo "Is $SERVER_NAME the correct base domain for your installation?"
-  echo "-----------------------------------------------------"
-  select domain_option in "yes" "no (enter manually)"; do
-    case $REPLY in
-      1)
-        echo "using $SERVER_NAME for domain"
-      break
-        ;;      
-      2)
-        read -p "Enter Server Domain: " broker
-        SERVER_NAME=$server
-        echo "using $SERVER_NAME"
-        break
-        ;;
-      *) echo "invalid option $REPLY";;
-    esac
-  done
-
-  TURN_DOMAIN="turn.$SERVER_NAME"
-  TURNAPI_DOMAIN="turnapi.$SERVER_NAME"
-  echo "-----------------------------------------------------"
-  echo "Netmaker v0.19 requires new DNS entries for $STUN_DOMAIN, $TURN_DOMAIN, and $TURNAPI_DOMAIN."
-  echo "Please confirm this is added to your DNS provider before continuing."
-  echo "You can skip this step if using a wildcard DNS entry (e.g. *.$SERVER_NAME) or a nip.io address."
-  echo "-----------------------------------------------------"
-  confirm
-}
-
-# collect_node_settings - get existing server node configuration
-collect_node_settings() {
-  curl -s -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://$SERVER_HTTP_HOST/api/nodes | jq -c '[ .[] | select(.isserver=="yes") ]' > nodejson.tmp
-  NODE_LEN=$(jq length nodejson.tmp)
-  HAS_INGRESS="no"
-  HAS_RELAY="no"
-  if [ "$NODE_LEN" -gt 0 ]; then
-      echo "===SERVER NODES==="
-      for i in $(seq 1 $NODE_LEN); do
-          NUM=$(($i-1))
-          echo "  SERVER NODE $NUM:"
-          echo "    network: $(jq -r ".[$NUM].network" ./nodejson.tmp)"
-          echo "      name: $(jq -r ".[$NUM].name" ./nodejson.tmp)"
-          echo "      private ipv4: $(jq -r ".[$NUM].address" ./nodejson.tmp)"
-          echo "      private ipv6: $(jq -r ".[$NUM].address6" ./nodejson.tmp)"
-          echo "      is egress: $(jq -r ".[$NUM].isegressgateway" ./nodejson.tmp)"
-          if [[ $(jq -r ".[$NUM].isegressgateway" ./nodejson.tmp) == "yes" ]]; then
-              echo "          egress range: $(jq -r ".[$NUM].egressgatewayranges" ./nodejson.tmp)"
-          fi
-          echo "      is ingress: $(jq -r ".[$NUM].isingressgateway" ./nodejson.tmp)"
-          if [[ $(jq -r ".[$NUM].isingressgateway" ./nodejson.tmp) == "yes" ]]; then
-              HAS_INGRESS="yes"
-          fi
-          echo "      is relay: $(jq -r ".[$NUM].isrelay" ./nodejson.tmp)"
-          if [[ $(jq -r ".[$NUM].isrelay" ./nodejson.tmp) == "yes" ]]; then
-              HAS_RELAY="yes"
-              echo "          relay addrs: $(jq -r ".[$NUM].relayaddrs" ./nodejson.tmp | tr -d '[]\n"[:space:]')"
-          fi
-          echo "      is failover: $(jq -r ".[$NUM].failover" ./nodejson.tmp)"
-          echo "  ------------"
-      done
-      echo "=================="
-  else
-      echo "no nodes to parse"
-  fi
-
-  echo "Please confirm that the above output matches the server nodes in your Netmaker server."
-  confirm
-
-  if [[ $HAS_INGRESS == "yes" ]]; then
-      echo "WARNING: Your server contains an Ingress Gateway. After upgrading, existing Ext Clients will be lost and must be recreated. Please confirm that you would like to continue."
-      confirm
-  fi
-  if [[ $HAS_RELAY == "yes" ]]; then
-      echo "WARNING: Your server contains a Relay. After upgrading, relay will be unset. Relay functionality has been moved to the 'host' level, and must be reconfigured once all machines are upgraded."
-      confirm
-  fi
-
-}
-
-# setup_caddy - updates Caddy with new info
-setup_caddy() {
-
-  echo "backing up Caddyfile to ${INSTALL_PATH}/Caddyfile.backup"
-  cp $INSTALL_PATH/Caddyfile $INSTALL_PATH/Caddyfile.backup
-
-  if grep -wq "acme.zerossl.com/v2/DV90" Caddyfile; then 
-      echo "zerossl already set, continuing" 
-  else 
-    echo "editing Caddyfile"
-    sed -i '0,/email/{s~email~acme_ca https://acme.zerossl.com/v2/DV90\n\t&~}' $INSTALL_PATH/Caddyfile
-  fi
-
-cat <<EOT >> $INSTALL_PATH/Caddyfile
-
-# STUN
-https://$STUN_DOMAIN {
-  reverse_proxy netmaker:3478
-}
-
-# TURN
-https://$TURN_DOMAIN {
-  reverse_proxy netmaker:3479
-}
-
-#TURN API
-https://turnapi.$TURNAPI_DOMAIN {
-        reverse_proxy http://host.docker.internal:8089
-}
-EOT
-
-}
-
-# set_mq_credentials - sets mq credentials
-set_mq_credentials() {
-
-  unset GET_MQ_USERNAME
-  unset GET_MQ_PASSWORD
-  unset CONFIRM_MQ_PASSWORD
-  echo "Enter Credentials For MQ..."
-  read -p "MQ Username (click 'enter' to use 'netmaker'): " GET_MQ_USERNAME
-  if [ -z "$GET_MQ_USERNAME" ]; then
-    echo "using default username for mq"
-    MQ_USERNAME="netmaker"
-  else
-    MQ_USERNAME="$GET_MQ_USERNAME"
-  fi
-
-  select domain_option in "Auto Generated Password" "Input Your Own Password"; do
-    case $REPLY in
-    1)
-    echo "generating random password for mq"
-    MQ_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 30 ; echo '')
-    break
-    ;;      
-      2)
-    while true
-      do
-          echo "Enter your Password For MQ: " 
-          read -s GET_MQ_PASSWORD
-          echo "Enter your password again to confirm: "
-          read -s CONFIRM_MQ_PASSWORD
-          if [ ${GET_MQ_PASSWORD} != ${CONFIRM_MQ_PASSWORD} ]; then
-              echo "wrong password entered, try again..."
-              continue
-          fi
-      MQ_PASSWORD="$GET_MQ_PASSWORD"
-          echo "MQ Password Saved Successfully!!"
-          break
-      done
-        break
-        ;;
-      *) echo "invalid option $REPLY";;
-    esac
-  done
-}
-
-# set_turn_credentials - sets mq credentials
-set_turn_credentials() {
-
-  unset GET_TURN_USERNAME
-  unset GET_TURN_PASSWORD
-  unset CONFIRM_TURN_PASSWORD
-  echo "Enter Credentials For TURN..."
-  read -p "TURN Username (click 'enter' to use 'netmaker'): " GET_TURN_USERNAME
-  if [ -z "$GET_TURN_USERNAME" ]; then
-    echo "using default username for turn"
-    TURN_USERNAME="netmaker"
-  else
-    TURN_USERNAME="$GET_TURN_USERNAME"
-  fi
-
-  select domain_option in "Auto Generated Password" "Input Your Own Password"; do
-    case $REPLY in
-    1)
-    echo "generating random password for TURN"
-    TURN_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 30 ; echo '')
-    break
-    ;;      
-      2)
-    while true
-      do
-          echo "Enter your Password For TURN: " 
-          read -s GET_TURN_PASSWORD
-          echo "Enter your password again to confirm: "
-          read -s CONFIRM_TURN_PASSWORD
-          if [ ${GET_TURN_PASSWORD} != ${CONFIRM_TURN_PASSWORD} ]; then
-              echo "wrong password entered, try again..."
-              continue
-          fi
-      TURN_PASSWORD="$GET_TURN_PASSWORD"
-          echo "TURN Password Saved Successfully!!"
-          break
-      done
-        break
-        ;;
-      *) echo "invalid option $REPLY";;
-    esac
-  done
-}
-
-# set_compose - set compose file with proper values
-set_compose() {
-
-  set_mq_credentials
-  set_turn_credentials
-
-  echo "retrieving updated wait script and mosquitto conf"  
-  rm $INSTALL_PATH/wait.sh
-  rm $INSTALL_PATH/mosquitto.conf
-
-  wget -O $INSTALL_PATH/wait.sh https://raw.githubusercontent.com/gravitl/netmaker/master/docker/wait.sh
-
-  chmod +x $INSTALL_PATH/wait.sh
-
-  wget -O $INSTALL_PATH/mosquitto.conf https://raw.githubusercontent.com/gravitl/netmaker/master/docker/mosquitto.conf
-
-  chmod +x $INSTALL_PATH/mosquitto.conf
-
-  # DEV_TEMP
-  sed -i "s/v0.17.1/$LATEST/g" $INSTALL_PATH/docker-compose.yml
-
-  STUN_PORT=3478
-
-  yq ".services.netmaker.environment.SERVER_NAME = \"$SERVER_NAME\"" -i $INSTALL_PATH/docker-compose.yml
-  yq ".services.netmaker.environment += {\"BROKER_ENDPOINT\": \"wss://$BROKER_NAME\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"SERVER_BROKER_ENDPOINT\": \"ws://mq:1883\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"STUN_LIST\": \"$STUN_DOMAIN:$STUN_PORT,stun1.netmaker.io:3478,stun2.netmaker.io:3478,stun1.l.google.com:19302,stun2.l.google.com:19302\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"MQ_USERNAME\": \"$MQ_USERNAME\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"MQ_PASSWORD\": \"$MQ_PASSWORD\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"TURN_SERVER_HOST\": \"turn.$SERVER_NAME\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"TURN_SERVER_API_HOST\": \"turnapi.$SERVER_NAME\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"TURN_USERNAME\": \"$TURN_USERNAME\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"TURN_PASSWORD\": \"$TURN_PASSWORD\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"STUN_PORT\": \"$STUN_PORT\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"TURN_PORT\": \"3479\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.environment += {\"USE_TURN\": \"true\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.netmaker.ports += \"3478:3478/udp\"" -i $INSTALL_PATH/docker-compose.yml
-
-  yq ".services.mq.environment += {\"MQ_USERNAME\": \"$MQ_USERNAME\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.mq.environment += {\"MQ_PASSWORD\": \"$MQ_PASSWORD\"}" -i $INSTALL_PATH/docker-compose.yml  
-
-  yq ".services.turn += {\"container_name\": \"turn\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn += {\"image\": \"gravitl/turnserver:v1.0.0\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn += {\"network_mode\": \"host\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn.volumes += {\"turn_server:/etc/config\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn.environment += {\"DEBUG_MODE\": \"off\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn.environment += {\"VERBOSITY\": \"1\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn.environment += {\"TURN_PORT\": \"3479\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn.environment += {\"TURN_API_PORT\": \"8089\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn.environment += {\"CORS_ALLOWED_ORIGIN\": \"*\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn.environment += {\"TURN_SERVER_HOST\": \"$TURN_DOMAIN\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn.environment += {\"TURN_USERNAME\": \"$TURN_USERNAME\"}" -i $INSTALL_PATH/docker-compose.yml  
-  yq ".services.turn.environment += {\"TURN_PASSWORD\": \"$TURN_PASSWORD\"}" -i $INSTALL_PATH/docker-compose.yml  
-
-  yq ".services.volumes += {\".turn_server\": \"{}\"}" -i $INSTALL_PATH/docker-compose.yml  
-
-  #remove unnecessary ports
-  yq eval 'del( .services.netmaker.ports[] | select(. == "51821*") )' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del( .services.mq.ports[] | select(. == "8883*") )' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del( .services.mq.ports[] | select(. == "1883*") )' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del( .services.mq.expose[] | select(. == "8883*") )' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del( .services.mq.expose[] | select(. == "1883*") )' -i $INSTALL_PATH/docker-compose.yml
-
-  # delete unnecessary compose sections
-  yq eval 'del(.services.netmaker.cap_add)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del(.services.netmaker.sysctls)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del(.services.netmaker.environment.MQ_ADMIN_PASSWORD)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del(.services.netmaker.environment.MQ_HOST)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del(.services.netmaker.environment.MQ_PORT)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del(.services.netmaker.environment.MQ_SERVER_PORT)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del(.services.netmaker.environment.PORT_FORWARD_SERVICES)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del(.services.netmaker.environment.CLIENT_MODE)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del(.services.netmaker.environment.HOST_NETWORK)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del(.services.mq.environment.NETMAKER_SERVER_HOST)' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del( .services.netmaker.volumes[] | select(. == "mosquitto_data*") )' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del( .services.mq.volumes[] | select(. == "mosquitto_data*") )' -i $INSTALL_PATH/docker-compose.yml
-  yq eval 'del( .volumes.mosquitto_data )' -i $INSTALL_PATH/docker-compose.yml
-
-}
-
-# start_containers - run docker-compose up -d
-start_containers() {
-  docker-compose -f $INSTALL_PATH/docker-compose.yml up -d
-}
-
-# test_caddy - make sure caddy is working
-test_caddy() {
-  echo "Testing Caddy setup (please be patient, this may take 1-2 minutes)"
-  for i in 1 2 3 4 5 6 7 8
-  do
-  curlresponse=$(curl -vIs https://${SERVER_HTTP_HOST} 2>&1)
-
-  if [[ "$i" == 8 ]]; then
-    echo "    Caddy is having an issue setting up certificates, please investigate (docker logs caddy)"
-    echo "    Exiting..."
-    exit 1
-  elif [[ "$curlresponse" == *"failed to verify the legitimacy of the server"* ]]; then
-    echo "    Certificates not yet configured, retrying..."
-
-  elif [[ "$curlresponse" == *"left intact"* ]]; then
-    echo "    Certificates ok"
-    break
-  else
-    secs=$(($i*5+10))
-    echo "    Issue establishing connection...retrying in $secs seconds..."       
-  fi
-  sleep $secs
-  done
-}
-
-# setup_netclient - adds netclient to docker-compose
-setup_netclient() {
-
-	set +e
-	netclient uninstall
-	HAS_APT=false
-  set -e
-  if command -v apt >/dev/null; then
-    HAS_APT=true
-  fi
-  set +e
-
-  if  [ "$HAS_APT" = "true" ]; then
-    curl -sL 'https://apt.netmaker.org/gpg.key' | sudo tee /etc/apt/trusted.gpg.d/netclient.asc
-    curl -sL 'https://apt.netmaker.org/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/netclient.list
-    sudo apt update
-    sudo apt install netclient
-  else
-     wget -O /tmp/netclient https://github.com/gravitl/netclient/releases/download/$LATEST/netclient_linux_amd64 
-
-	  chmod +x /tmp/netclient
-	  /tmp/netclient install
-  fi
-
-	netclient register -t $KEY
-
-	echo "waiting for client to become available"
-	wait_seconds 10 
-
-}
-
-# setup_nmctl - pulls nmctl and makes it executable
-setup_nmctl() {
-
-    wget -O nmctl https://github.com/gravitl/netmaker/releases/download/$LATEST/nmctl-linux-amd64
-  
-    chmod +x nmctl
-    echo "using server $SERVER_HTTP_HOST"
-    echo "using master key $MASTER_KEY"
-    ./nmctl context set default --endpoint="https://$SERVER_HTTP_HOST" --master_key="$MASTER_KEY"
-    ./nmctl context use default
-    RESP=$(./nmctl network list)
-    if [[ $RESP == *"unauthorized"* ]]; then
-        echo "Unable to properly configure NMCTL, exiting..."
-        exit 1
-    fi
-}
-
-# join_networks - joins netclient into the networks using old settings
-join_networks() {
-  NODE_LEN=$(jq length nodejson.tmp)  
-  if [ "$NODE_LEN" -gt 0 ]; then
-      for i in $(seq 1 $NODE_LEN); do
-          HAS_INGRESS="no"
-          HAS_EGRESS="no"
-          EGRESS_RANGES=""
-          HAS_RELAY="no"
-          RELAY_ADDRS=""
-          HAS_FAILOVER="no"
-
-          NUM=$(($i-1))
-          NETWORK=$(jq -r ".[$NUM].network" ./nodejson.tmp)
-          echo "  joining network $NETWORK with following settings. Please confirm:"
-          echo "         network: $(jq -r ".[$NUM].network" ./nodejson.tmp)"
-          echo "            name: $(jq -r ".[$NUM].name" ./nodejson.tmp)"
-          echo "    private ipv4: $(jq -r ".[$NUM].address" ./nodejson.tmp)"
-          echo "    private ipv6: $(jq -r ".[$NUM].address6" ./nodejson.tmp)"
-          echo "       is egress: $(jq -r ".[$NUM].isegressgateway" ./nodejson.tmp)"
-          if [[ $(jq -r ".[$NUM].isegressgateway" ./nodejson.tmp) == "yes" ]]; then
-              HAS_EGRESS="yes"
-              echo "          egress ranges: $(jq -r ".[$NUM].egressgatewayranges" ./nodejson.tmp | tr -d '[]\n"[:space:]')"
-              EGRESS_RANGES=$(jq -r ".[$NUM].egressgatewayranges" ./nodejson.tmp | tr -d '[]\n"[:space:]')
-              EGRESS_RANGES=${EGRESS_RANGES//0.0.0.0\/0/0.0.0.0\/5,8.0.0.0\/7,11.0.0.0\/8,12.0.0.0\/6,16.0.0.0\/4,32.0.0.0\/3,64.0.0.0\/2,128.0.0.0\/3,160.0.0.0\/5,168.0.0.0\/6,172.0.0.0\/12,172.32.0.0\/11,172.64.0.0\/10,172.128.0.0\/9,173.0.0.0\/8,174.0.0.0\/7,176.0.0.0\/4,192.0.0.0\/9,192.128.0.0\/11,192.160.0.0\/13,192.169.0.0\/16,192.170.0.0\/15,192.172.0.0\/14,192.176.0.0\/12,192.192.0.0\/10,193.0.0.0\/8,194.0.0.0\/7,196.0.0.0\/6,200.0.0.0\/5,208.0.0.0\/4}
-              EGRESS_RANGES=${EGRESS_RANGES//0::\/0/}
-              EGRESS_RANGES=${EGRESS_RANGES//,,/,}
-              EGRESS_RANGES=`echo $EGRESS_RANGES | sed 's/,*$//g'`
-              EGRESS_RANGES=`echo $EGRESS_RANGES | sed 's/^,*//g'`
-
-          fi
-          echo "      is ingress: $(jq -r ".[$NUM].isingressgateway" ./nodejson.tmp)"
-          if [[ $(jq -r ".[$NUM].isingressgateway" ./nodejson.tmp) == "yes" ]]; then
-              HAS_INGRESS="yes"
-          fi
-          echo "        is relay: $(jq -r ".[$NUM].isrelay" ./nodejson.tmp)"
-          if [[ $(jq -r ".[$NUM].isrelay" ./nodejson.tmp) == "yes" ]]; then
-              HAS_RELAY="yes"
-              RELAY_ADDRS=$(jq -r ".[$NUM].relayaddrs" ./nodejson.tmp | tr -d '[]\n"[:space:]')
-          fi
-          echo "     is failover: $(jq -r ".[$NUM].failover" ./nodejson.tmp)"
-          if [[ $(jq -r ".[$NUM].failover" ./nodejson.tmp) == "yes" ]]; then
-              HAS_FAILOVER="yes"
-          fi
-          echo "  ------------"
-
-          confirm
-
-          if [[ $NUM -eq 0 ]]; then 
-            echo "running command: ./nmctl enrollment_key create --uses 1 --networks $NETWORK"
-          	KEY_JSON=$(./nmctl enrollment_key create --uses 1 --networks $NETWORK)
-          	KEY=$(jq -r '.token' <<< ${KEY_JSON})
-
-            echo "enrollment key created: $KEY"
-
-            setup_netclient
-          else
-            HOST_ID=$(sudo cat /etc/netclient/netclient.yml | yq -r .host.id)
-            ./nmctl host add_network $HOST_ID $NETWORK
-          fi
-          NAME=$(jq -r ".[$NUM].name" ./nodejson.tmp)
-          ADDRESS=$(jq -r ".[$NUM].address" ./nodejson.tmp)
-          ADDRESS6=$(jq -r ".[$NUM].address6" ./nodejson.tmp)
-
-          echo "wait 10 seconds for netclient to be ready"
-          sleep 10
-
-          NODE_ID=$(sudo cat /etc/netclient/nodes.yml | yq -r .$NETWORK.commonnode.id)
-          echo "join complete. New node ID: $NODE_ID"
-          if [[ $NUM -eq 0 ]]; then
-            HOST_ID=$(sudo cat /etc/netclient/netclient.yml | yq -r .host.id)
-            echo "For first join, making host a default"
-            echo "Host ID: $HOST_ID"
-            # set as a default host
-            set +e
-            ./nmctl host update $HOST_ID --default
-            sleep 2
-            set -e            
-          fi
-
-          # create an egress if necessary
-          if [[ $HAS_EGRESS == "yes" ]]; then
-            echo "creating egress"            
-            ./nmctl node create_egress $NETWORK $NODE_ID $EGRESS_RANGES
-            sleep 2
-          fi
-
-          echo "HAS INGRESS: $HAS_INGRESS"
-          # create an ingress if necessary
-          if [[ $HAS_INGRESS == "yes" ]]; then
-            if [[ $HAS_FAILOVER == "yes" ]]; then
-              echo "creating ingress and failover..."
-              ./nmctl node create_ingress $NETWORK $NODE_ID --failover
-              sleep 2
-            else
-              echo "creating ingress..."
-              ./nmctl node create_ingress $NETWORK $NODE_ID
-              sleep 2
-            fi
-          fi
-
-          # relay
-          if [[ $HAS_RELAY == "yes" ]]; then
-            echo "cannot recreate relay; relay functionality moved to host"
-            # ./nmctl node create_relay $NETWORK $NODE_ID $RELAY_ADDRS
-            # sleep 2
-          fi
-
-      done
-      echo "=================="
-  else
-      echo "no networks to join"
-  fi
-}
-
-cat << "EOF"
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
-The Netmaker Upgrade Script: Upgrading to v0.18 so you don't have to!
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
-EOF
-
-set -e 
-
-if [ $(id -u) -ne 0 ]; then
-   echo "This script must be run as root"
-   exit 1
-fi
-
-set +e
-
-#backup volumes and v0.17.1 configs in case of failure.
-backup_volumes
-backup_v17_files
-
-# get the installation path for docker-compose.yml and other config files
-get_install_path
-
-echo "...installing dependencies for script"
-install_dependencies
-
-echo "...installing yq if necessary"
-install_yq
-
-set -e
-
-echo "...confirming version is correct"
-check_version
-
-echo "...collecting necessary server settings"
-collect_server_settings
-
-echo "...setup nmctl"
-setup_nmctl
-
-echo "...retrieving current server node settings"
-collect_node_settings
-
-echo "...backing up docker compose to docker-compose.yml.backup"
-cp $INSTALL_PATH/docker-compose.yml $INSTALL_PATH/docker-compose.yml.backup
-
-echo "...setting Caddyfile values"
-setup_caddy
-
-echo "...setting docker-compose values"
-set_compose
-
-echo "...starting containers"
-start_containers
-
-echo "...remove old mosquitto data"
-# TODO - yq is not removing volume from docker compose
-# docker volume rm root_mosquitto_data
-
-wait_seconds 3
-
-echo "..testing Caddy proxy"
-test_caddy
-
-echo "..testing Netmaker health"
-# TODO, implement health check
-# netmaker_health_check
-# wait_seconds 2
-
-wait_seconds 2
-
-echo "...setup netclient"
-join_networks
-
-echo "-----------------------------------------------------------------"
-echo "-----------------------------------------------------------------"
-echo "Netmaker setup is now complete. You are ready to begin using Netmaker."
-echo "Visit dashboard.$SERVER_NAME to log in"
-echo "-----------------------------------------------------------------"
-echo "-----------------------------------------------------------------"