Bladeren bron

Merge branch 'develop' into NET-63x

Matthew R Kasun 2 jaren geleden
bovenliggende
commit
b2f779bd71

+ 2 - 2
.github/workflows/deletedroplets.yml

@@ -23,7 +23,7 @@ jobs:
           webhook_token: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
           color: "#42f545"
           username: "GitHub Bot"
-          message: "${{ github.respository }}: ${{ github.event.workflow_run.name }} was successful"
+          message: "${{ github.repository }}: ${{ github.event.workflow_run.name }} was successful"
           file: ./results/results.log
       - name: discord server message
         uses: appleboy/discord-action@master
@@ -62,7 +62,7 @@ jobs:
           webhook_token: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
           color: "#990000"
           username: "GitHub Bot"
-          message: "${{ github.respository }}: ${{ github.event.workflow_run.name }} failed"
+          message: "${{ github.repository }}: ${{ github.event.workflow_run.name }} failed"
           file: ./results/results.log
       - name: discord server message
         uses: appleboy/discord-action@master

+ 0 - 46
.github/workflows/packages.yml

@@ -1,46 +0,0 @@
-name: Build linux packages
-on:
-  workflow_call:
-    inputs:
-      version:
-        required: true
-        type: string
-  workflow_dispatch:
-    inputs:
-      version:
-        description: "netmaker version"
-        required: true
-  release:
-    types: [released]
-
-jobs:
-
-  packages:
-    runs-on: ubuntu-latest
-    steps:
-      - name: setup ssh
-        run: |
-          mkdir -p ~/.ssh/
-          echo "$SSH_KEY" > ~/.ssh/id_devops
-          chmod 600 ~/.ssh/id_devops
-          cat >>~/.ssh/config <<END
-          Host *.clustercat.com
-            User root
-            IdentityFile ~/.ssh/id_devops
-            StrictHostKeyChecking no
-          END
-        env:
-          SSH_KEY: ${{ secrets.TESTING_SSH_KEY }}
-      - name: set version
-        run: |
-          if [[ -n "${{ github.event.inputs.version }}" ]]; then
-            # remove everything but digits and . for package (deb, rpm, etc) versions
-            VERSION=$(echo ${{ github.event.inputs.version }} | tr -cd '[:digit:].')
-          else
-            VERSION=$(echo ${{ github.ref.name }} | tr -cd '[:digit:].')
-          fi
-            echo "VERSION=${VERSION}" >> $GITHUB_ENV
-            echo ${VERSION}
-      - name: apt/rpm
-        run: |
-          ssh fileserver.clustercat.com "cd packages/nmcli; export VERSION=${{ ENV.version }}; export REVISION=0; ./buildall.sh "

+ 19 - 0
.github/workflows/pre-release.yml

@@ -0,0 +1,19 @@
+# creates a release from develop
+# creates release branch, generates release assets, publishes docker image and copies release.md to release
+# linux packages are generated and a PR from release branch to master is created 
+name: Release
+
+on:
+  workflow_dispatch:
+    inputs:
+      version:
+        description: "new version number"
+        required: true
+
+jobs:
+
+  release:
+    uses: gravitl/devops/.github/workflows/netmakerPrerelease.yml@master
+    with:
+      version: ${{ inputs.version }}
+    secrets: inherit

+ 0 - 32
.github/workflows/pull-request.yml

@@ -1,32 +0,0 @@
-# creates a PR from release branch to master
-name: Create Release PR to master
-on:
-  workflow_call:
-    inputs:
-      version:
-        required: true
-        type: string
-  workflow_dispatch:
-    inputs:
-      version:
-        description: "netmaker version"
-        required: true
-  release:
-    types: [released]
-
-jobs:
-  pr-to-main:
-    runs-on: ubuntu-latest
-    steps:
-      - name: create pr
-        env:
-          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        run: |
-          gh api --method POST \
-          -H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28'  \
-          /repos/${{ github.repository }}/pulls \
-          -f title='${{ github.event.inputs.version }}' \
-          -f head='release_${{ github.event.inputs.version }}' \
-          -f base="master"
-
-

+ 0 - 50
.github/workflows/release-assets.yml

@@ -1,50 +0,0 @@
-# generates release assets and uploads to release 
-name: Upload Release Assets
-on:
-  workflow_call:
-    inputs:
-      version:
-        required: true
-        type: string
-      prerelease:
-        required: true
-        type: boolean
-  workflow_dispatch:
-    inputs:
-      version:
-        description: "netmaker version"
-        required: true
-      prerelease:
-        required: true
-        type: boolean
-        description: "prerelease"
-jobs:
-  release-assets:
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v3
-        with:
-          ref: release_${{ github.event.inputs.version}}
-          fetch-depth: 0
-      - name: Get Tags
-        run: |
-          git fetch --force --tags
-      - name: Setup go
-        uses: actions/setup-go@v4
-        with:
-          go-version: 1.19
-      - name: GoReleaser (full release)
-        if: ${{ github.event.inputs.prerelease == 'false'}}
-        uses: goreleaser/goreleaser-action@v4
-        with:
-          args: release --clean --release-notes release.md
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      - name: GoReleaser (prerelease)
-        if: ${{ github.event.inputs.prerelease == 'false'}}
-        uses: goreleaser/goreleaser-action@v4
-        with:
-          args: release --clean --release-notes release.md -f .goreleaser.prerelease.yaml
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

+ 0 - 39
.github/workflows/release-branch.yml

@@ -1,39 +0,0 @@
-# creates new branch (release_{{ version }} with tag {{ version }} from develop 
-# will fail if branch or tag already exists on github
-name: Create Release Branch
-on:
-  workflow_call:
-    inputs:
-      version:
-        required: true
-        type: string
-  workflow_dispatch:
-    inputs:
-      version:
-        description: "netmaker version"
-        required: true
-jobs:
-  release-branch:
-    runs-on: ubuntu-latest
-    steps:
-      - name: checkout develop
-        uses: actions/checkout@v3
-        with:
-          ref: develop
-      - name: setup go
-        uses: actions/setup-go@v4
-        with:
-          go-version: 1.19
-      - name: setup git
-        run: |
-          git config user.name "Github Actions"
-          git config user.emaail "[email protected]"
-      - name: create release Branch
-        run: |
-          git switch -c release_${{ github.event.inputs.version }}
-          git tag -f ${{ github.event.inputs.version }}
-          #push branch
-          git push origin release_${{ github.event.inputs.version }}
-          #push tag
-          git push origin ${{ github.event.inputs.version }}
-  

+ 4 - 40
.github/workflows/release.yml

@@ -1,6 +1,6 @@
 # creates a release from develop
 # creates release branch, generates release assets, publishes docker image and copies release.md to release
-# if formal release, linux packages are generated and a PR from release branch to master is created 
+# linux packages are generated and a PR from release branch to master is created 
 name: Release
 
 on:
@@ -9,47 +9,11 @@ on:
       version:
         description: "new version number"
         required: true
-      prerelease:
-        required: true
-        type: boolean
-        description: Is this a pre-release
 
 jobs:
 
-  release-branch:
-    uses: ./.github/workflows/release-branch.yml
-    with:
-      version: ${{ github.event.inputs.version }}
-    secrets: inherit
-
-  
-  release-assets:
-    needs: release-branch
-    uses: ./.github/workflows/release-assets.yml
-    with:
-      version: ${{ github.event.inputs.version }}
-      prerelease: ${{ github.event.inputs.prerelease == 'true' }}
-    secrets: inherit
-
-  docker:
-    needs: release-branch
-    uses: ./.github/workflows/publish-docker.yml
-    with:
-      tag: ${{ github.event.inputs.version }}
-    secrets: inherit
-
-  packages:
-    if: ${{ github.event.inputs.prerelease == 'false' }}
-    needs: release-branch
-    uses: ./.github/workflows/packages.yml
-    with:
-      version: ${{ github.event.inputs.version }}
-    secrets: inherit
-
-  pull-request:
-    if: ${{ github.event.inputs.prerelease == 'false' }}
-    needs: release-branch
-    uses: ./.github/workflows/pull-request.yml
+  release:
+    uses: gravitl/devops/.github/workflows/netmakerRelease.yml@master
     with:
-      version: ${{ github.event.inputs.version }}
+      version: ${{ inputs.version }}
     secrets: inherit

+ 0 - 41
.github/workflows/upgraderelease.yml

@@ -1,41 +0,0 @@
-name: UpgradeRelease
-
-on:
-  workflow_dispatch:
-    inputs:
-      version:
-        description: "release/version to update"
-        required: true
-
-jobs:
-
-  update:
-    runs-on: ubuntu-latest
-    steps:
-      - name: checkout
-        uses: actions/checkout@v3
-        with:
-          ref: release_${{ github.event.inputs.version }}
-          fetch-depth: 0
-      - run: |
-          git fetch --force --tags
-      - name: Setup go
-        uses: actions/setup-go@v4
-        with:
-          go-version: 1.19
-      - name: goreleaser
-        uses: goreleaser/goreleaser-action@v4
-        with:
-          args: release --clean --release-notes release.md -f .goreleaser.update.yaml
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN  }}
-
-  packages:
-    uses: ./.github/workflows/packages.yml
-    with:
-      version: ${{ github.event.inputs.version }}
-
-  pull-request:
-    uses: ./.github/workflows/pull-request.yml
-    with:
-      version: ${{ github.event.inputs.version }}

+ 1 - 0
compose/docker-compose-emqx.yml

@@ -50,6 +50,7 @@ services:
     restart: unless-stopped
     volumes:
       - /root/Caddyfile:/etc/caddy/Caddyfile
+      - /root/certs:/root/certs
       - caddy_data:/data
       - caddy_conf:/config
     ports:

+ 4 - 1
compose/docker-compose.ee.yml

@@ -57,6 +57,7 @@ services:
     restart: unless-stopped
     volumes:
       - /root/Caddyfile:/etc/caddy/Caddyfile
+      - /root/certs:/root/certs
       - caddy_data:/data
       - caddy_conf:/config
     ports:
@@ -118,7 +119,9 @@ services:
     depends_on:
       - netmaker
     environment:
-      SERVER_BROKER_ENDPOINT: "ws://mq:1883"
+      MQ_PASSWORD: "REPLACE_MQ_PASSWORD"
+      MQ_USERNAME: "REPLACE_MQ_USERNAME"
+      MQ_URL: "ws://mq:1883"
       BROKER_ENDPOINT: "wss://broker.NETMAKER_BASE_DOMAIN"
       PROMETHEUS: "on"
       VERBOSITY: "1"

+ 1 - 0
compose/docker-compose.reference.yml

@@ -64,6 +64,7 @@ services:
     restart: unless-stopped
     volumes:
       - /root/Caddyfile:/etc/caddy/Caddyfile # Config file for Caddy
+      - /root/certs:/root/certs
       - caddy_data:/data
       - caddy_conf:/config
     ports:

+ 1 - 0
compose/docker-compose.yml

@@ -56,6 +56,7 @@ services:
       - "host.docker.internal:host-gateway"
     volumes:
       - /root/Caddyfile:/etc/caddy/Caddyfile
+      - /root/certs:/root/certs
       - caddy_data:/data
       - caddy_conf:/config
     ports:

+ 15 - 1
controllers/relay.go

@@ -167,7 +167,7 @@ func deleteHostRelay(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")
 	var params = mux.Vars(r)
 	hostid := params["hostid"]
-	relayHost, _, err := logic.DeleteHostRelay(hostid)
+	relayHost, relayed, err := logic.DeleteHostRelay(hostid)
 	if err != nil {
 		logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
@@ -178,6 +178,20 @@ func deleteHostRelay(w http.ResponseWriter, r *http.Request) {
 		if err := mq.PublishPeerUpdate(); err != nil {
 			logger.Log(0, "fail to publish peer update: ", err.Error())
 		}
+		if err := mq.HostUpdate(&models.HostUpdate{
+			Action: models.UpdateHost,
+			Host:   *relayHost,
+		}); err != nil {
+			logger.Log(0, "failed to send host update: ", relayHost.Name, err.Error())
+		}
+		for _, relayedHost := range relayed {
+			if err := mq.HostUpdate(&models.HostUpdate{
+				Action: models.UpdateHost,
+				Host:   relayedHost,
+			}); err != nil {
+				logger.Log(0, "failed to send host update: ", relayedHost.Name, err.Error())
+			}
+		}
 	}()
 	apiHostData := relayHost.ConvertNMHostToAPI()
 	w.WriteHeader(http.StatusOK)

+ 26 - 26
docker/Caddyfile

@@ -1,51 +1,51 @@
-{
-        # ZeroSSL account
-        # acme_ca https://acme.zerossl.com/v2/DV90
-        email YOUR_EMAIL
-}
-
 # Dashboard
 https://dashboard.NETMAKER_BASE_DOMAIN {
-        # Apply basic security headers
-        header {
-                # Enable cross origin access to *.NETMAKER_BASE_DOMAIN
-                Access-Control-Allow-Origin *.NETMAKER_BASE_DOMAIN
-                # Enable HTTP Strict Transport Security (HSTS)
-                Strict-Transport-Security "max-age=31536000;"
-                # Enable cross-site filter (XSS) and tell browser to block detected attacks
-                X-XSS-Protection "1; mode=block"
-                # Disallow the site to be rendered within a frame on a foreign domain (clickjacking protection)
-                X-Frame-Options "SAMEORIGIN"
-                # Prevent search engines from indexing
-                X-Robots-Tag "none"
-                # Remove the server name
-                -Server
-        }
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	# Apply basic security headers
+	header {
+		# Enable cross origin access to *.NETMAKER_BASE_DOMAIN
+		Access-Control-Allow-Origin *.NETMAKER_BASE_DOMAIN
+		# Enable HTTP Strict Transport Security (HSTS)
+		Strict-Transport-Security "max-age=31536000;"
+		# Enable cross-site filter (XSS) and tell browser to block detected attacks
+		X-XSS-Protection "1; mode=block"
+		# Disallow the site to be rendered within a frame on a foreign domain (clickjacking protection)
+		X-Frame-Options "SAMEORIGIN"
+		# Prevent search engines from indexing
+		X-Robots-Tag "none"
+		# Remove the server name
+		-Server
+	}
 
-        reverse_proxy http://netmaker-ui
+	reverse_proxy http://netmaker-ui
 }
 
 # API
 https://api.NETMAKER_BASE_DOMAIN {
-        reverse_proxy http://netmaker:8081
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	reverse_proxy http://netmaker:8081
 }
 
 # STUN
 https://stun.NETMAKER_BASE_DOMAIN {
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy netmaker:3478
 }
 
 # TURN
 https://turn.NETMAKER_BASE_DOMAIN {
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy host.docker.internal:3479
 }
 
-#TURN API
+# TURN API
 https://turnapi.NETMAKER_BASE_DOMAIN {
-        reverse_proxy http://host.docker.internal:8089
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+    reverse_proxy http://host.docker.internal:8089
 }
 
 # MQ
 wss://broker.NETMAKER_BASE_DOMAIN {
-        reverse_proxy ws://mq:8883 # For EMQX websockets use `reverse_proxy ws://mq:8083`
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	reverse_proxy ws://mq:8883 # For EMQX websockets use `reverse_proxy ws://mq:8083`
 }

+ 32 - 29
docker/Caddyfile-EE

@@ -1,66 +1,69 @@
-{
-        # ZeroSSL account
-        acme_ca https://acme.zerossl.com/v2/DV90
-        email YOUR_EMAIL
-}
-
 # Dashboard
 https://dashboard.NETMAKER_BASE_DOMAIN {
-        # Apply basic security headers
-        header {
-                # Enable cross origin access to *.NETMAKER_BASE_DOMAIN
-                Access-Control-Allow-Origin *.NETMAKER_BASE_DOMAIN
-                # Enable HTTP Strict Transport Security (HSTS)
-                Strict-Transport-Security "max-age=31536000;"
-                # Enable cross-site filter (XSS) and tell browser to block detected attacks
-                X-XSS-Protection "1; mode=block"
-                # Disallow the site to be rendered within a frame on a foreign domain (clickjacking protection)
-                X-Frame-Options "SAMEORIGIN"
-                # Prevent search engines from indexing
-                X-Robots-Tag "none"
-                # Remove the server name
-                -Server
-        }
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	# Apply basic security headers
+	header {
+		# Enable cross origin access to *.NETMAKER_BASE_DOMAIN
+		Access-Control-Allow-Origin *.NETMAKER_BASE_DOMAIN
+		# Enable HTTP Strict Transport Security (HSTS)
+		Strict-Transport-Security "max-age=31536000;"
+		# Enable cross-site filter (XSS) and tell browser to block detected attacks
+		X-XSS-Protection "1; mode=block"
+		# Disallow the site to be rendered within a frame on a foreign domain (clickjacking protection)
+		X-Frame-Options "SAMEORIGIN"
+		# Prevent search engines from indexing
+		X-Robots-Tag "none"
+		# Remove the server name
+		-Server
+	}
 
-        reverse_proxy http://netmaker-ui
+	reverse_proxy http://netmaker-ui
 }
 
 # Netmaker Exporter
 https://netmaker-exporter.NETMAKER_BASE_DOMAIN {
-        reverse_proxy http://netmaker-exporter:8085
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	reverse_proxy http://netmaker-exporter:8085
 }
 
 # Prometheus
 https://prometheus.NETMAKER_BASE_DOMAIN {
-        reverse_proxy http://prometheus:9090
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	reverse_proxy http://prometheus:9090
 }
 
 # Grafana
 https://grafana.NETMAKER_BASE_DOMAIN {
-        reverse_proxy http://grafana:3000
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	reverse_proxy http://grafana:3000
 }
 
 # API
 https://api.NETMAKER_BASE_DOMAIN {
-        reverse_proxy http://netmaker:8081
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	reverse_proxy http://netmaker:8081
 }
 
 # STUN
 https://stun.NETMAKER_BASE_DOMAIN {
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy netmaker:3478
 }
 
 # TURN
 https://turn.NETMAKER_BASE_DOMAIN {
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy host.docker.internal:3479
 }
 
-#TURN API
+# TURN API
 https://turnapi.NETMAKER_BASE_DOMAIN {
-        reverse_proxy http://host.docker.internal:8089
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	reverse_proxy http://host.docker.internal:8089
 }
 
 # MQ
 wss://broker.NETMAKER_BASE_DOMAIN {
-        reverse_proxy ws://mq:8883
+	tls /root/certs/fullchain.pem /root/certs/privkey.pem
+	reverse_proxy ws://mq:8883
 }

+ 1 - 1
go.mod

@@ -14,7 +14,7 @@ require (
 	github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/stretchr/testify v1.8.2
-	github.com/txn2/txeh v1.3.0
+	github.com/txn2/txeh v1.4.0
 	golang.org/x/crypto v0.8.0
 	golang.org/x/net v0.9.0 // indirect
 	golang.org/x/oauth2 v0.7.0

+ 2 - 26
go.sum

@@ -6,15 +6,10 @@ cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxB
 filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
 filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/c-robinson/iplib v1.0.6 h1:FfZV9BWNrah3BgLCFl5/nDXe4RbOi/C9n+DeXFOv5CQ=
 github.com/c-robinson/iplib v1.0.6/go.mod h1:i3LuuFL1hRT5gFpBRnEydzw8R6yhGkF4szNDIbF8pgo=
-github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
 github.com/coreos/go-oidc/v3 v3.5.0 h1:VxKtbccHZxs8juq7RdJntSqtXFtde9YpNpGn0yqgEHw=
 github.com/coreos/go-oidc/v3 v3.5.0/go.mod h1:ecXRtV4romGPeO6ieExAsUK9cb/3fp9hXNz1tlv8PIM=
-github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -28,7 +23,6 @@ github.com/eclipse/paho.mqtt.golang v1.4.2/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2
 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
 github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
-github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
 github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
 github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@@ -64,8 +58,6 @@ github.com/guumaster/tablewriter v0.0.10 h1:A0HD94yMdt4usgxBjoEceNeE0XMJ027euoHA
 github.com/guumaster/tablewriter v0.0.10/go.mod h1:p4FRFhyfo0UD9ZLmMRbbJooTUsxo6b80qZTERVDWrH8=
 github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
 github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
@@ -81,7 +73,6 @@ github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA=
 github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
 github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
 github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
-github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
 github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
@@ -98,11 +89,8 @@ github.com/mdlayher/socket v0.1.1 h1:q3uOGirUPfAV2MUoaC7BavjQ154J7+JOkTWyiV+intI
 github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
 github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
 github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
-github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -117,41 +105,30 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV
 github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f h1:BSnJgAfHzEp7o8PYJ7YfwAVHhqu7BYUTggcn/LGlUWY=
 github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f/go.mod h1:UW/gxgQwSePTvL1KA8QEHsXeYHP4xkoXgbDdN781p34=
-github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
-github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
-github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
 github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
-github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
-github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
 github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/txn2/txeh v1.3.0 h1:vnbv63htVMZCaQgLqVBxKvj2+HHHFUzNW7I183zjg3E=
-github.com/txn2/txeh v1.3.0/go.mod h1:O7M6gUTPeMF+vsa4c4Ipx3JDkOYrruB1Wry8QRsMcw8=
-github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/txn2/txeh v1.4.0 h1:0tdvpA4HGJrj8X3kmrU6o/JFStI009nKxwDpMK5CnRU=
+github.com/txn2/txeh v1.4.0/go.mod h1:Mgq0hY184zCrDBLgvkIp+9NYGHoYbJcu4xKqUcx1shc=
 github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -184,7 +161,6 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

+ 6 - 2
logic/enrollmentkey.go

@@ -41,12 +41,16 @@ func CreateEnrollmentKey(uses int, expiration time.Time, networks, tags []string
 		Unlimited:     unlimited,
 		Networks:      []string{},
 		Tags:          []string{},
+		Type:          models.Undefined,
 	}
 	if uses > 0 {
 		k.UsesRemaining = uses
-	}
-	if !expiration.IsZero() {
+		k.Type = models.Uses
+	} else if !expiration.IsZero() {
 		k.Expiration = expiration
+		k.Type = models.TimeExpiration
+	} else if k.Unlimited {
+		k.Type = models.Unlimited
 	}
 	if len(networks) > 0 {
 		k.Networks = networks

+ 3 - 1
main.go

@@ -19,6 +19,7 @@ import (
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic/pro"
+	"github.com/gravitl/netmaker/migrate"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/netclient/ncutils"
@@ -27,7 +28,7 @@ import (
 	stunserver "github.com/gravitl/netmaker/stun-server"
 )
 
-var version = "v0.19.0"
+var version = "v0.19.1"
 
 // Start DB Connection and start API Request Handler
 func main() {
@@ -74,6 +75,7 @@ func initialize() { // Client Mode Prereq Check
 		logger.FatalLog("Error connecting to database: ", err.Error())
 	}
 	logger.Log(0, "database successfully connected")
+	migrate.Run()
 
 	logic.SetJWTSecret()
 

+ 50 - 0
migrate/migrate.go

@@ -0,0 +1,50 @@
+package migrate
+
+import (
+	"encoding/json"
+
+	"github.com/gravitl/netmaker/database"
+	"github.com/gravitl/netmaker/logger"
+	"github.com/gravitl/netmaker/models"
+)
+
+// Run - runs all migrations
+func Run() {
+	updateEnrollmentKeys()
+}
+
+func updateEnrollmentKeys() {
+	rows, err := database.FetchRecords(database.ENROLLMENT_KEYS_TABLE_NAME)
+	if err != nil {
+		return
+	}
+	for _, row := range rows {
+		var key models.EnrollmentKey
+		if err = json.Unmarshal([]byte(row), &key); err != nil {
+			continue
+		}
+		if key.Type != models.Undefined {
+			logger.Log(2, "migration: enrollment key type already set")
+			continue
+		} else {
+			logger.Log(2, "migration: updating enrollment key type")
+			if key.Unlimited {
+				key.Type = models.Unlimited
+			} else if key.UsesRemaining > 0 {
+				key.Type = models.Uses
+			} else if !key.Expiration.IsZero() {
+				key.Type = models.TimeExpiration
+			}
+		}
+		data, err := json.Marshal(key)
+		if err != nil {
+			logger.Log(0, "migration: marshalling enrollment key: "+err.Error())
+			continue
+		}
+		if err = database.Insert(key.Value, string(data), database.ENROLLMENT_KEYS_TABLE_NAME); err != nil {
+			logger.Log(0, "migration: inserting enrollment key: "+err.Error())
+			continue
+		}
+
+	}
+}

+ 20 - 0
models/enrollment_key.go

@@ -4,6 +4,21 @@ import (
 	"time"
 )
 
+const (
+	Undefined KeyType = iota
+	TimeExpiration
+	Uses
+	Unlimited
+)
+
+// KeyType - the type of enrollment key
+type KeyType int
+
+// String - returns the string representation of a KeyType
+func (k KeyType) String() string {
+	return [...]string{"Undefined", "TimeExpiration", "Uses", "Unlimited"}[k]
+}
+
 // EnrollmentToken - the tokenized version of an enrollmentkey;
 // to be used for host registration
 type EnrollmentToken struct {
@@ -23,6 +38,7 @@ type EnrollmentKey struct {
 	Unlimited     bool      `json:"unlimited"`
 	Tags          []string  `json:"tags"`
 	Token         string    `json:"token,omitempty"` // B64 value of EnrollmentToken
+	Type          KeyType   `json:"type"`
 }
 
 // APIEnrollmentKey - used to create enrollment keys via API
@@ -32,6 +48,7 @@ type APIEnrollmentKey struct {
 	Networks      []string `json:"networks"`
 	Unlimited     bool     `json:"unlimited"`
 	Tags          []string `json:"tags"`
+	Type          KeyType  `json:"type"`
 }
 
 // RegisterResponse - the response to a successful enrollment register
@@ -51,6 +68,9 @@ func (k *EnrollmentKey) IsValid() bool {
 	if !k.Expiration.IsZero() && time.Now().Before(k.Expiration) {
 		return true
 	}
+	if k.Type == Undefined {
+		return false
+	}
 
 	return k.Unlimited
 }

+ 99 - 0
scripts/nm-certs.sh

@@ -0,0 +1,99 @@
+#!/bin/bash
+
+CONFIG_FILE=netmaker.env
+SCRIPT_DIR=$(dirname "$(realpath "$0")")
+
+# get and check the config
+if [ ! -f "$SCRIPT_DIR/$CONFIG_FILE" ]; then
+	echo "Config file missing"
+	exit 1
+fi
+source "$SCRIPT_DIR/$CONFIG_FILE"
+if [ -z "$NM_DOMAIN" ] || [ -z "$NM_EMAIL" ]; then
+	echo "Config not valid"
+	exit 1
+fi
+
+# TODO make sure this doesnt break, parse `certbot certificates` if yes
+CERT_DIR="$SCRIPT_DIR/letsencrypt/live/stun.$NM_DOMAIN"
+
+echo "Setting up SSL certificates..."
+
+# preserve the env state
+RESTART_CADDY=false
+if [ -n "$(docker ps | grep caddy)" ]; then
+	echo "Caddy is running, stopping for now..."
+	RESTART_CADDY=true
+	docker-compose -f /root/docker-compose.yml stop caddy
+fi
+
+CERTBOT_PARAMS=$(cat <<EOF
+certonly --standalone \
+	--non-interactive --agree-tos \
+	-m "$NM_EMAIL" \
+	-d "stun.$NM_DOMAIN" \
+	-d "api.$NM_DOMAIN" \
+	-d "broker.$NM_DOMAIN" \
+	-d "dashboard.$NM_DOMAIN" \
+	-d "turn.$NM_DOMAIN" \
+	-d "turnapi.$NM_DOMAIN" \
+	-d "netmaker-exporter.$NM_DOMAIN" \
+	-d "grafana.$NM_DOMAIN" \
+	-d "prometheus.$NM_DOMAIN"
+EOF
+)
+
+# generate an entrypoint for zerossl-certbot
+cat <<EOF >"$SCRIPT_DIR/certbot-entry.sh"
+#!/bin/sh
+# deps
+apk add bash curl
+# zerossl
+wget -qO zerossl-bot.sh "https://github.com/zerossl/zerossl-bot/raw/master/zerossl-bot.sh"
+chmod +x zerossl-bot.sh
+# request the certs
+./zerossl-bot.sh "$CERTBOT_PARAMS"
+EOF
+chmod +x certbot-entry.sh
+
+# request certs
+sudo docker run -it --rm --name certbot \
+	-p 80:80 -p 443:443 \
+	-v "$SCRIPT_DIR/certbot-entry.sh:/opt/certbot/certbot-entry.sh" \
+	-v "$SCRIPT_DIR/letsencrypt:/etc/letsencrypt" \
+	--entrypoint "/opt/certbot/certbot-entry.sh" \
+	certbot/certbot
+
+# clean up TODO enable
+#rm "$SCRIPT_DIR/certbot-entry.sh"
+
+# check if successful
+if [ ! -f "$CERT_DIR"/fullchain.pem ]; then
+	# fallback to letsencrypt-certbot
+	sudo docker run -it --rm --name certbot \
+		-p 80:80 -p 443:443 \
+		-v "$SCRIPT_DIR/letsencrypt:/etc/letsencrypt" \
+		--entrypoint "/opt/certbot/certbot-entry.sh" \
+		certbot/certbot "$CERTBOT_PARAMS"
+	if [ ! -f "$CERT_DIR"/fullchain.pem ]; then
+		echo "Missing file: $CERT_DIR/fullchain.pem"
+		echo "SSL certificates failed"
+		exit 1
+	fi
+fi
+
+# copy for mounting
+mkdir -p certs
+cp -L "$CERT_DIR/fullchain.pem" /root/certs/fullchain.pem
+cp -L "$CERT_DIR/privkey.pem" /root/certs/privkey.pem
+
+echo "SSL certificates ready"
+
+# preserve the env state
+if [ "$RESTART_CADDY" = true ]; then
+	echo "Starting Caddy..."
+	docker-compose -f /root/docker-compose.yml start caddy
+fi
+
+# install crontab
+ln -sfn "$SCRIPT_DIR"/nm-certs.sh /etc/cron.monthly/nm-certs.sh

+ 74 - 42
scripts/nm-quick.sh

@@ -1,31 +1,22 @@
 #!/bin/bash
 
+CONFIG_FILE=netmaker.env
+# location of nm-quick.sh (usually `/root`)
+SCRIPT_DIR=$(dirname "$(realpath "$0")")
+CONFIG_PATH="$SCRIPT_DIR/$CONFIG_FILE"
 LATEST=$(curl -s https://api.github.com/repos/gravitl/netmaker/releases/latest | grep "tag_name" | cut -d : -f 2,3 | tr -d [:space:],\")
 
-print_logo() { (
-	cat <<"EOF"
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-                                                                                         
- __   __     ______     ______   __    __     ______     __  __     ______     ______    
-/\ "-.\ \   /\  ___\   /\__  _\ /\ "-./  \   /\  __ \   /\ \/ /    /\  ___\   /\  == \   
-\ \ \-.  \  \ \  __\   \/_/\ \/ \ \ \-./\ \  \ \  __ \  \ \  _"-.  \ \  __\   \ \  __<   
- \ \_\\"\_\  \ \_____\    \ \_\  \ \_\ \ \_\  \ \_\ \_\  \ \_\ \_\  \ \_____\  \ \_\ \_\ 
-  \/_/ \/_/   \/_____/     \/_/   \/_/  \/_/   \/_/\/_/   \/_/\/_/   \/_____/   \/_/ /_/ 
-                                                                                                                                                                                                 
-
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-EOF
-); }
-
 if [ $(id -u) -ne 0 ]; then
 	echo "This script must be run as root"
 	exit 1
 fi
 
+# read the config file
+if [ -f "$CONFIG_PATH" ]; then
+	echo "Reading config from $CONFIG_PATH"
+	source "$CONFIG_PATH"
+fi
+
 unset INSTALL_TYPE
 unset BUILD_TYPE
 unset BUILD_TAG
@@ -246,22 +237,42 @@ confirm() { (
 		[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"
+	# email
+	if grep -q "^NM_EMAIL=" "$CONFIG_PATH"; then
+		sed -i "s/NM_EMAIL=.*/NM_EMAIL=$EMAIL/" "$CONFIG_PATH"
+	else
+		echo "NM_EMAIL=$EMAIL" >>"$CONFIG_PATH"
+	fi
+	# domain
+	if grep -q "^NM_DOMAIN=" "$CONFIG_PATH"; then
+		sed -i "s/NM_DOMAIN=.*/NM_DOMAIN=$NETMAKER_BASE_DOMAIN/" "$CONFIG_PATH"
+	else
+		echo "NM_DOMAIN=$NETMAKER_BASE_DOMAIN" >>"$CONFIG_PATH"
+	fi
+); }
+
 # local_install_setup - builds artifacts based on specified branch locally to use in install
 local_install_setup() { (
 	rm -rf netmaker-tmp
 	mkdir netmaker-tmp
 	cd netmaker-tmp
-	git clone https://www.github.com/gravitl/netmaker
+	git clone --single-branch --depth=1 --branch=$BUILD_TAG https://www.github.com/gravitl/netmaker
 	cd netmaker
-	git checkout $BUILD_TAG
-	git pull origin $BUILD_TAG
-	docker build --no-cache --build-arg version=$IMAGE_TAG -t gravitl/netmaker:$IMAGE_TAG .
+	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
 	if [ "$INSTALL_TYPE" = "ee" ]; then
 		cp compose/docker-compose.ee.yml /root/docker-compose.yml
 		cp docker/Caddyfile-EE /root/Caddyfile
@@ -269,6 +280,7 @@ local_install_setup() { (
 		cp compose/docker-compose.yml /root/docker-compose.yml
 		cp docker/Caddyfile /root/Caddyfile
 	fi
+	cp scripts/nm-certs.sh /root/nm-certs.sh
 	cp docker/mosquitto.conf /root/mosquitto.conf
 	cp docker/wait.sh /root/wait.sh
 	cd ../../
@@ -308,22 +320,14 @@ install_dependencies() {
 		dependencies="git wireguard wget jq docker.io docker-compose"
 		update_cmd='pkg update'
 		install_cmd='pkg install -y'
-	elif [ -f /etc/turris-version ]; then
-		dependencies="git wireguard-tools bash jq docker.io docker-compose"
-		OS="TurrisOS"
-		update_cmd='opkg update'
-		install_cmd='opkg install'
-	elif [ -f /etc/openwrt_release ]; then
-		dependencies="git wireguard-tools bash jq docker.io docker-compose"
-		OS="OpenWRT"
-		update_cmd='opkg update'
-		install_cmd='opkg install'
 	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
 
@@ -395,7 +399,8 @@ set_install_vars() {
 	fi
 
 	NETMAKER_BASE_DOMAIN=nm.$(echo $IP_ADDR | tr . -).nip.io
-	COREDNS_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
+	# TODO dead code?
+	# COREDNS_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
 	SERVER_PUBLIC_IP=$IP_ADDR
 	MASTER_KEY=$(
 		tr -dc A-Za-z0-9 </dev/urandom | head -c 30
@@ -440,7 +445,7 @@ set_install_vars() {
 	echo "             broker.$NETMAKER_BASE_DOMAIN"
 	echo "               stun.$NETMAKER_BASE_DOMAIN"
 	echo "               turn.$NETMAKER_BASE_DOMAIN"
-	echo "               turnapi.$NETMAKER_BASE_DOMAIN"
+	echo "            turnapi.$NETMAKER_BASE_DOMAIN"
 
 	if [ "$INSTALL_TYPE" = "ee" ]; then
 		echo "         prometheus.$NETMAKER_BASE_DOMAIN"
@@ -479,12 +484,18 @@ set_install_vars() {
 	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 $RAND_EMAIL): " GET_EMAIL
+		read -p "Email Address for Domain Registration (click 'enter' to use $EMAIL_SUGGESTED): " GET_EMAIL
 	fi
 	if [ -z "$GET_EMAIL" ]; then
-		echo "using rand email"
-		EMAIL="$RAND_EMAIL"
+		EMAIL="$EMAIL_SUGGESTED"
+		if [ "$EMAIL" = "$NM_EMAIL" ]; then
+			echo "using config email"
+		else
+			echo "using rand email"
+		fi
 	else
 		EMAIL="$GET_EMAIL"
 	fi
@@ -546,7 +557,7 @@ set_install_vars() {
 		read -p "TURN Username (click 'enter' to use 'netmaker'): " GET_TURN_USERNAME
 	fi
 	if [ -z "$GET_TURN_USERNAME" ]; then
-		echo "using default username for mq"
+		echo "using default username for TURN"
 		TURN_USERNAME="netmaker"
 	else
 		TURN_USERNAME="$GET_TURN_USERNAME"
@@ -603,6 +614,7 @@ set_install_vars() {
 
 	confirm
 
+	save_config
 }
 
 # install_netmaker - sets the config files and starts docker-compose
@@ -614,6 +626,7 @@ install_netmaker() {
 
 	wait_seconds 3
 
+	# TODO extract wgets to setup(), mirror local_setup()
 	echo "Pulling config files..."
 
 	COMPOSE_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG/compose/docker-compose.yml"
@@ -622,9 +635,13 @@ install_netmaker() {
 		COMPOSE_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG/compose/docker-compose.ee.yml"
 		CADDY_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG/docker/Caddyfile-EE"
 	fi
+
 	if [ ! "$BUILD_TYPE" = "local" ]; then
-		wget -O /root/docker-compose.yml $COMPOSE_URL && wget -O /root/mosquitto.conf https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG/docker/mosquitto.conf && wget -O /root/Caddyfile $CADDY_URL
-		wget -O /root/wait.sh https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG/docker/wait.sh
+		wget -qO /root/docker-compose.yml $COMPOSE_URL
+		wget -qO /root/Caddyfile $CADDY_URL
+		wget -qO /root/mosquitto.conf "https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG/docker/mosquitto.conf"
+		wget -qO /root/nm-certs.sh "https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG/scripts/nm-certs.sh"
+		wget -qO /root/wait.sh "https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG/docker/wait.sh"
 	fi
 
 	chmod +x /root/wait.sh
@@ -661,7 +678,12 @@ install_netmaker() {
 
 	echo "Starting containers..."
 
-	docker-compose -f /root/docker-compose.yml up -d
+	# increase the timeouts
+	export DOCKER_CLIENT_TIMEOUT=120
+	export COMPOSE_HTTP_TIMEOUT=120
+
+	# start docker and rebuild containers / networks
+	docker-compose -f /root/docker-compose.yml up -d --force-recreate
 
 	wait_seconds 2
 
@@ -747,6 +769,16 @@ set -e
 # 6. get user input for variables
 set_install_vars
 
+# stop
+for name in "mq" "netmaker-ui" "coredns" "turn" "caddy" "netmaker"; do
+	if test -n "$(docker ps | grep name)"; then
+		docker stop $name
+	fi
+done
+
+# Fetch / update certs using certbot
+"$SCRIPT_DIR"/nm-certs.sh
+
 # 7. get and set config files, startup docker-compose
 install_netmaker
 

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

@@ -27,6 +27,7 @@ backup_v17_files() {
 }
 
 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/