Browse Source

make nebula a service that can install itself

Ryan Huber 5 years ago
parent
commit
8ed69c8eaf
5 changed files with 181 additions and 15 deletions
  1. 23 15
      Makefile
  2. 49 0
      cmd/nebula-service/main.go
  3. 106 0
      cmd/nebula-service/service.go
  4. 1 0
      go.mod
  5. 2 0
      go.sum

+ 23 - 15
Makefile

@@ -1,55 +1,56 @@
+NEBULA_CMD_PATH = "./cmd/nebula"
 BUILD_NUMBER ?= dev+$(shell date -u '+%Y%m%d%H%M%S')
 GO111MODULE = on
 export GO111MODULE
 
 all:
-	make bin-linux
-	make bin-arm
-	make bin-arm6
-	make bin-arm64
-	make bin-darwin
-	make bin-windows
+	make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-linux
+	make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-arm
+	make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-arm6
+	make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-arm64
+	make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-darwin
+	make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-windows
 
 bin:
 	go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula ./cmd/nebula
 	go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula-cert ./cmd/nebula-cert
 
 install:
-	go install -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula
+	go install -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH}
 	go install -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert
 
 bin-arm:
 	mkdir -p build/arm
-	GOARCH=arm GOOS=linux go build -o build/arm/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula
+	GOARCH=arm GOOS=linux go build -o build/arm/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH}
 	GOARCH=arm GOOS=linux go build -o build/arm/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert
 
 bin-arm6:
 	mkdir -p build/arm6
-	GOARCH=arm GOARM=6 GOOS=linux go build -o build/arm6/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula
+	GOARCH=arm GOARM=6 GOOS=linux go build -o build/arm6/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH}
 	GOARCH=arm GOARM=6 GOOS=linux go build -o build/arm6/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert
 
 bin-arm64:
 	mkdir -p build/arm64
-	GOARCH=arm64 GOOS=linux go build -o build/arm64/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula
+	GOARCH=arm64 GOOS=linux go build -o build/arm64/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH}
 	GOARCH=arm64 GOOS=linux go build -o build/arm64/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert
 
 bin-vagrant:
-	GOARCH=amd64 GOOS=linux go build -o nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula
+	GOARCH=amd64 GOOS=linux go build -o nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH}
 	GOARCH=amd64 GOOS=linux go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula-cert ./cmd/nebula-cert
 
 bin-darwin:
 	mkdir -p build/darwin
-	GOARCH=amd64 GOOS=darwin go build -o build/darwin/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula
+	GOARCH=amd64 GOOS=darwin go build -o build/darwin/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH}
 	GOARCH=amd64 GOOS=darwin go build -o build/darwin/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert
 
 bin-windows:
 	mkdir -p build/windows
-	GOARCH=amd64 GOOS=windows go build -o build/windows/nebula.exe -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula
+	GOARCH=amd64 GOOS=windows go build -o build/windows/nebula.exe -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH}
 	GOARCH=amd64 GOOS=windows go build -o build/windows/nebula-cert.exe -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert
 
 bin-linux:
 	mkdir -p build/linux
-	GOARCH=amd64 GOOS=linux go build -o build/linux/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula
+	GOARCH=amd64 GOOS=linux go build -o build/linux/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH}
 	GOARCH=amd64 GOOS=linux go build -o build/linux/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert
 
 release: all
@@ -91,6 +92,13 @@ nebula.pb.go: nebula.proto .FORCE
 cert/cert.pb.go: cert/cert.proto .FORCE
 	$(MAKE) -C cert cert.pb.go
 
+service:
+	@echo > /dev/null
+	$(eval NEBULA_CMD_PATH := "./cmd/nebula-service")
+ifeq ($(words $(MAKECMDGOALS)),1)
+	$(MAKE) service ${.DEFAULT_GOAL} --no-print-directory
+endif
+
 .FORCE:
-.PHONY: test test-cov-html bench bench-cpu bench-cpu-long bin proto release
+.PHONY: test test-cov-html bench bench-cpu bench-cpu-long bin proto release service
 .DEFAULT_GOAL := bin

+ 49 - 0
cmd/nebula-service/main.go

@@ -0,0 +1,49 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"os"
+
+	"github.com/slackhq/nebula"
+)
+
+// A version string that can be set with
+//
+//     -ldflags "-X main.Build=SOMEVERSION"
+//
+// at compile-time.
+var Build string
+
+func main() {
+	serviceFlag := flag.String("service", "", "Control the system service.")
+	configPath := flag.String("config", "", "Path to either a file or directory to load configuration from")
+	configTest := flag.Bool("test", false, "Test the config and print the end result. Non zero exit indicates a faulty config")
+	printVersion := flag.Bool("version", false, "Print version")
+	printUsage := flag.Bool("help", false, "Print command line usage")
+
+	flag.Parse()
+
+	if *printVersion {
+		fmt.Printf("Build: %s\n", Build)
+		os.Exit(0)
+	}
+
+	if *printUsage {
+		flag.Usage()
+		os.Exit(0)
+	}
+
+	if *serviceFlag != "" {
+		doService(configPath, configTest, Build, serviceFlag)
+		os.Exit(1)
+	}
+
+	if *configPath == "" {
+		fmt.Println("-config flag must be set")
+		flag.Usage()
+		os.Exit(1)
+	}
+
+	nebula.Main(*configPath, *configTest, Build)
+}

+ 106 - 0
cmd/nebula-service/service.go

@@ -0,0 +1,106 @@
+package main
+
+import (
+	"log"
+	"os"
+	"path/filepath"
+
+	"github.com/kardianos/service"
+	"github.com/slackhq/nebula"
+)
+
+var logger service.Logger
+
+type program struct {
+	exit       chan struct{}
+	configPath *string
+	configTest *bool
+	build      string
+}
+
+func (p *program) Start(s service.Service) error {
+	if service.Interactive() {
+		logger.Info("Running in terminal.")
+	} else {
+		logger.Info("Running under service manager.")
+	}
+	p.exit = make(chan struct{})
+
+	// Start should not block. Do the actual work async.
+	go p.run()
+	return nil
+}
+
+func (p *program) run() error {
+	nebula.Main(*p.configPath, *p.configTest, Build)
+	return nil
+}
+
+func (p *program) Stop(s service.Service) error {
+	// Any work in Stop should be quick, usually a few seconds at most.
+	logger.Info("I'm Stopping!")
+	close(p.exit)
+	return nil
+}
+
+func doService(configPath *string, configTest *bool, build string, serviceFlag *string) {
+
+	if *configPath == "" {
+		ex, err := os.Executable()
+		if err != nil {
+			panic(err)
+		}
+		*configPath = filepath.Dir(ex) + "/config.yaml"
+	}
+
+	svcConfig := &service.Config{
+		Name:        "Nebula",
+		DisplayName: "Nebula Network Service",
+		Description: "Nebula network connectivity daemon for encrypted communications",
+		Arguments:   []string{"-service", "run", "-config", *configPath},
+	}
+
+	prg := &program{
+		configPath: configPath,
+		configTest: configTest,
+		build:      build,
+	}
+
+	s, err := service.New(prg, svcConfig)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	errs := make(chan error, 5)
+	logger, err = s.Logger(errs)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	go func() {
+		for {
+			err := <-errs
+			if err != nil {
+				log.Print(err)
+			}
+		}
+	}()
+
+	//if len(*serviceFlag) != 0 {
+	switch *serviceFlag {
+	case "run":
+		err = s.Run()
+		if err != nil {
+			logger.Error(err)
+		}
+	default:
+		err := service.Control(s, *serviceFlag)
+		if err != nil {
+			log.Printf("Valid actions: %q\n", service.ControlAction)
+			log.Fatal(err)
+		}
+		return
+		//}
+	}
+
+}

+ 1 - 0
go.mod

@@ -10,6 +10,7 @@ require (
 	github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6
 	github.com/golang/protobuf v1.3.1
 	github.com/imdario/mergo v0.3.7
+	github.com/kardianos/service v1.0.0
 	github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
 	github.com/kr/pretty v0.1.0 // indirect
 	github.com/miekg/dns v1.1.12

+ 2 - 0
go.sum

@@ -30,6 +30,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
 github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
 github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kardianos/service v1.0.0/go.mod h1:8CzDhVuCuugtsHyZoTvsOBuvonN/UDBvl0kH+BUxvbo=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -97,6 +98,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=