Compare commits
	
		
			No commits in common. "fb4f0c5a69924c74954888d14dc3d71ab755001e" and "1e9f95295d82441d71bcd391cf738ed7f3b80b47" have entirely different histories.
		
	
	
		
			fb4f0c5a69
			...
			1e9f95295d
		
	
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,4 +1,6 @@ | |||||||
| /cmd/watchdog/installer/static | installer | ||||||
|  | watchdog.service | ||||||
|  | /cmd/install/static | ||||||
| /watchdog | /watchdog | ||||||
| /cmd/watchdog/watchdog | /cmd/watchdog/watchdog | ||||||
| xversion.go | xversion.go | ||||||
|  | |||||||
| @ -1,24 +1,18 @@ | |||||||
| # Pre-req | # Pre-req | ||||||
| # sudo mkdir -p {{ .Local }}/opt/{{ .Name }}/ {{ .Local }}/var/log/{{ .Name }} | # sudo adduser {{ .Exec }} --home /opt/{{ .Exec }} | ||||||
| {{ if not .Local -}} | # sudo mkdir -p /opt/{{ .Exec }}/ /var/log/{{ .Exec }} | ||||||
| {{ if .User -}} | # sudo chown -R {{ .Exec }}:{{ .Exec }} /opt/{{ .Exec }}/ /var/log/{{ .Exec }} | ||||||
| # sudo adduser {{ .User }} --home /opt/{{ .Name }} |  | ||||||
| # sudo chown -R {{ .User }}:{{ .Group }} /opt/{{ .Name }}/ /var/log/{{ .Name }} |  | ||||||
| {{- end }} |  | ||||||
| {{- end }} |  | ||||||
| 
 | 
 | ||||||
| # Post-install | # Post-install | ||||||
| # sudo systemctl {{ if .Local -}} --user {{- end }} daemon-reload | # sudo systemctl daemon-reload | ||||||
| # sudo systemctl {{ if .Local -}} --user {{- end }} restart {{ .Name }}.service | # sudo systemctl restart {{ .Exec }}.service | ||||||
| # sudo journalctl {{ if .Local -}} --user {{- end }} -xefu {{ .Name }} | # sudo journalctl -xefu {{ .Exec }} | ||||||
| 
 | 
 | ||||||
| [Unit] | [Unit] | ||||||
| Description={{ .Title }} - {{ .Desc }} | Description={{ .Name }} - {{ .Desc }} | ||||||
| Documentation={{ .URL }} | Documentation={{ .URL }} | ||||||
| {{ if not .Local -}} |  | ||||||
| After=network-online.target | After=network-online.target | ||||||
| Wants=network-online.target systemd-networkd-wait-online.service | Wants=network-online.target systemd-networkd-wait-online.service | ||||||
| {{- end }} |  | ||||||
| 
 | 
 | ||||||
| [Service] | [Service] | ||||||
| # Restart on crash (bad signal), but not on 'clean' failure (error exit code) | # Restart on crash (bad signal), but not on 'clean' failure (error exit code) | ||||||
| @ -34,8 +28,8 @@ User={{ .User }} | |||||||
| Group={{ .Group }} | Group={{ .Group }} | ||||||
| 
 | 
 | ||||||
| {{ end -}} | {{ end -}} | ||||||
| WorkingDirectory={{ .Local }}/opt/{{ .Name }} | WorkingDirectory=/opt/{{ .Exec }} | ||||||
| ExecStart={{if .Interpreter }}{{ .Interpreter }} {{ end }}{{ .Local }}/opt/{{ .Name }}/{{ .Name }} {{ .Args }} | ExecStart=/opt/{{ .Exec }}/{{ .Exec }} {{ .Args }} | ||||||
| ExecReload=/bin/kill -USR1 $MAINPID | ExecReload=/bin/kill -USR1 $MAINPID | ||||||
| 
 | 
 | ||||||
| {{if .Production -}} | {{if .Production -}} | ||||||
| @ -55,14 +49,14 @@ PrivateDevices=true | |||||||
| ProtectHome=true | ProtectHome=true | ||||||
| # Make /usr, /boot, /etc and possibly some more folders read-only. | # Make /usr, /boot, /etc and possibly some more folders read-only. | ||||||
| ProtectSystem=full | ProtectSystem=full | ||||||
| # ... except /opt/{{ .Name }} because we want a place for the database | # ... except /opt/{{ .Exec }} because we want a place for the database | ||||||
| # and /var/log/{{ .Name }} because we want a place where logs can go. | # and /var/log/{{ .Exec }} because we want a place where logs can go. | ||||||
| # This merely retains r/w access rights, it does not add any new. | # This merely retains r/w access rights, it does not add any new. | ||||||
| # Must still be writable on the host! | # Must still be writable on the host! | ||||||
| ReadWriteDirectories=/opt/{{ .Name }} /var/log/{{ .Name }} | ReadWriteDirectories=/opt/{{ .Exec }} /var/log/{{ .Exec }} | ||||||
| 
 | 
 | ||||||
| # Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories | # Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories | ||||||
| ; ReadWritePaths=/opt/{{ .Name }} /var/log/{{ .Name }} | ; ReadWritePaths=/opt/{{ .Exec }} /var/log/{{ .Exec }} | ||||||
| 
 | 
 | ||||||
| {{ end -}} | {{ end -}} | ||||||
| {{if .PrivilegedPorts -}} | {{if .PrivilegedPorts -}} | ||||||
| @ -81,8 +75,4 @@ NoNewPrivileges=true | |||||||
| 
 | 
 | ||||||
| {{ end -}} | {{ end -}} | ||||||
| [Install] | [Install] | ||||||
| {{ if not .Local -}} |  | ||||||
| WantedBy=multi-user.target | WantedBy=multi-user.target | ||||||
| {{- else -}} |  | ||||||
| WantedBy=default.target |  | ||||||
| {{- end }} |  | ||||||
							
								
								
									
										23
									
								
								cmd/install/install.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								cmd/install/install.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | //go:generate go run -mod=vendor github.com/UnnoTed/fileb0x b0x.toml | ||||||
|  | 
 | ||||||
|  | // I'm prototyping this out to be useful for more than just watchdog | ||||||
|  | // hence there are a few unnecessary things for the sake of the trying it out | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | type Config struct { | ||||||
|  | 	Name                string `json:"name"` | ||||||
|  | 	Desc                string `json:"desc"` | ||||||
|  | 	URL                 string `json:"url"` | ||||||
|  | 	Exec                string `json:"exec"` | ||||||
|  | 	Args                string `json:"args"` | ||||||
|  | 	User                string `json:"user"` | ||||||
|  | 	Group               string `json:"group"` | ||||||
|  | 	Production          bool   `json:"production"` | ||||||
|  | 	PrivilegedPorts     bool   `json:"privileged_ports"` | ||||||
|  | 	MultiuserProtection bool   `json:"multiuser_protection"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 
 | ||||||
|  | 	install() | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								cmd/install/install_darwin.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								cmd/install/install_darwin.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import "log" | ||||||
|  | 
 | ||||||
|  | func install() { | ||||||
|  | 	log.Fatal("not yet implemented") | ||||||
|  | } | ||||||
							
								
								
									
										60
									
								
								cmd/install/install_linux.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								cmd/install/install_linux.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | |||||||
|  | // +build !windows !darwin | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"log" | ||||||
|  | 	"text/template" | ||||||
|  | 
 | ||||||
|  | 	"git.rootprojects.org/root/watchdog.go/cmd/install/static" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func install() { | ||||||
|  | 	b, err := static.ReadFile("dist/etc/systemd/system/watchdog.service.tmpl") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	s := string(b) | ||||||
|  | 
 | ||||||
|  | 	j, err := static.ReadFile("dist/etc/systemd/system/watchdog.service.json") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	//conf := map[string]string{} | ||||||
|  | 	conf := &Config{} | ||||||
|  | 	err = json.Unmarshal(j, &conf) | ||||||
|  | 	if nil != err { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	if "" == conf.Group { | ||||||
|  | 		conf.Group = conf.User | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	serviceFile := conf.Exec + ".service" | ||||||
|  | 
 | ||||||
|  | 	rw := &bytes.Buffer{} | ||||||
|  | 	// not sure what the template name does, but whatever | ||||||
|  | 	tmpl, err := template.New("service").Parse(s) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = tmpl.Execute(rw, conf) | ||||||
|  | 	if nil != err { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := ioutil.WriteFile(serviceFile, rw.Bytes(), 0644); err != nil { | ||||||
|  | 		log.Fatalf("ioutil.WriteFile error: %v", err) | ||||||
|  | 	} | ||||||
|  | 	fmt.Printf("Wrote %q\n", serviceFile) | ||||||
|  | } | ||||||
| @ -1,7 +1,7 @@ | |||||||
| package installer | package main | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"log" | ||||||
| 	//"golang.org/x/sys/windows" | 	//"golang.org/x/sys/windows" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -11,7 +11,7 @@ import ( | |||||||
| // https://stackoverflow.com/questions/27366298/check-if-application-is-running-as-administrator-in-golang | // https://stackoverflow.com/questions/27366298/check-if-application-is-running-as-administrator-in-golang | ||||||
| // https://www.reddit.com/r/golang/comments/53dthc/way_to_detect_if_the_programs_running_with/ | // https://www.reddit.com/r/golang/comments/53dthc/way_to_detect_if_the_programs_running_with/ | ||||||
| // https://play.golang.org/p/bBtRZrk4_p | // https://play.golang.org/p/bBtRZrk4_p | ||||||
| func install(c *Config) error { | func install() { | ||||||
| 	//token := windows.Token(0) | 	//token := windows.Token(0) | ||||||
| 	return fmt.Errorf("not yet implemented") | 	log.Fatal("not yet implemented") | ||||||
| } | } | ||||||
| @ -1,63 +0,0 @@ | |||||||
| package main |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"log" |  | ||||||
| 	"os" |  | ||||||
| 	"strings" |  | ||||||
| 
 |  | ||||||
| 	"git.rootprojects.org/root/watchdog.go/cmd/watchdog/installer" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func install(binpath string, args []string) { |  | ||||||
| 	system := true |  | ||||||
| 	production := false |  | ||||||
| 	config := "./config.json" |  | ||||||
| 	for i := range os.Args { |  | ||||||
| 		switch { |  | ||||||
| 		case strings.HasSuffix(os.Args[i], "userspace"): |  | ||||||
| 			system = false |  | ||||||
| 		case strings.HasSuffix(os.Args[i], "production"): |  | ||||||
| 			fmt.Println("Warning: production options don't work on all systems. If you have trouble, drop this first.") |  | ||||||
| 			production = false |  | ||||||
| 		case "-c" == os.Args[i]: |  | ||||||
| 			if len(os.Args) <= i+1 { |  | ||||||
| 				fmt.Println("-c requires a string path to the config file") |  | ||||||
| 				os.Exit(1) |  | ||||||
| 			} |  | ||||||
| 			config = os.Args[i+1] |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	/* |  | ||||||
| 		j, err := static.ReadFile("dist/etc/systemd/system/watchdog.service.json") |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatal(err) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		//conf := map[string]string{} |  | ||||||
| 		conf := &Config{} |  | ||||||
| 		err = json.Unmarshal(j, &conf) |  | ||||||
| 		if nil != err { |  | ||||||
| 			log.Fatal(err) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 	*/ |  | ||||||
| 	err := installer.Install(&installer.Config{ |  | ||||||
| 		Title:               "Watchdog", |  | ||||||
| 		Desc:                "Get notified when sites go down", |  | ||||||
| 		URL:                 "https://git.rootprojects.org/root/watchdog.go", |  | ||||||
| 		Name:                "watchdog", |  | ||||||
| 		Exec:                "watchdog", |  | ||||||
| 		Local:               "", |  | ||||||
| 		System:              system, |  | ||||||
| 		Restart:             true, |  | ||||||
| 		Argv:                []string{"-c", config}, |  | ||||||
| 		PrivilegedPorts:     false, |  | ||||||
| 		MultiuserProtection: false, |  | ||||||
| 		Production:          production, |  | ||||||
| 	}) |  | ||||||
| 	if nil != err { |  | ||||||
| 		log.Fatal(err) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -1,71 +0,0 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> |  | ||||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |  | ||||||
| <plist version="1.0"> |  | ||||||
| <dict> |  | ||||||
| 	<key>Label</key> |  | ||||||
| 	<string>{{ .Title }}</string> |  | ||||||
| 	<key>ProgramArguments</key> |  | ||||||
| 	<array> |  | ||||||
| 		{{- if .Interpreter }} |  | ||||||
| 		<string>{{ .Interpreter }}</string> |  | ||||||
| 		{{- end }} |  | ||||||
| 		<string>{{ .Local }}/opt/{{ .Name }}/{{ .Exec }}</string> |  | ||||||
| 	  {{- if .Argv }} |  | ||||||
| 		{{- range $arg := .Argv }} |  | ||||||
| 		<string>{{ $arg }}</string> |  | ||||||
| 		{{- end }} |  | ||||||
| 	  {{- end }} |  | ||||||
| 	</array> |  | ||||||
| 	{{- if .Envs }} |  | ||||||
| 	<key>EnvironmentVariables</key> |  | ||||||
| 	<dict> |  | ||||||
| 		{{- range $key, $value := .Envs }} |  | ||||||
| 		<key>{{ $key }}</key> |  | ||||||
| 		<string>{{ $value }}</string> |  | ||||||
| 		{{- end }} |  | ||||||
| 	</dict> |  | ||||||
| 	{{- end }} |  | ||||||
| 
 |  | ||||||
| 	{{if .User -}} |  | ||||||
| 	<key>UserName</key> |  | ||||||
| 	<string>{{ .User }}</string> |  | ||||||
| 	<key>GroupName</key> |  | ||||||
| 	<string>{{ .Group }}</string> |  | ||||||
| 	<key>InitGroups</key> |  | ||||||
| 	<true/> |  | ||||||
| 
 |  | ||||||
| 	{{end -}} |  | ||||||
| 	<key>RunAtLoad</key> |  | ||||||
| 	<true/> |  | ||||||
| 	{{ if .Restart -}} |  | ||||||
| 	<key>KeepAlive</key> |  | ||||||
| 	<true/> |  | ||||||
| 	<!--dict> |  | ||||||
| 		<key>Crashed</key> |  | ||||||
| 		<true/> |  | ||||||
| 		<key>NetworkState</key> |  | ||||||
| 		<true/> |  | ||||||
| 		<key>SuccessfulExit</key> |  | ||||||
| 		<false/> |  | ||||||
| 	</dict--> |  | ||||||
| 
 |  | ||||||
| 	{{ end -}} |  | ||||||
| 	{{ if .Production -}} |  | ||||||
| 	<key>SoftResourceLimits</key> |  | ||||||
| 	<dict> |  | ||||||
| 		<key>NumberOfFiles</key> |  | ||||||
| 		<integer>8192</integer> |  | ||||||
| 	</dict> |  | ||||||
| 	<key>HardResourceLimits</key> |  | ||||||
| 	<dict/> |  | ||||||
| 
 |  | ||||||
| 	{{ end -}} |  | ||||||
| 	<key>WorkingDirectory</key> |  | ||||||
| 	<string>{{ .Local }}/opt/{{ .Name }}</string> |  | ||||||
| 
 |  | ||||||
| 	<key>StandardErrorPath</key> |  | ||||||
| 	<string>{{ .LogDir }}/{{ .Name }}.log</string> |  | ||||||
| 	<key>StandardOutPath</key> |  | ||||||
| 	<string>{{ .LogDir }}/{{ .Name }}.log</string> |  | ||||||
| </dict> |  | ||||||
| </plist> |  | ||||||
| @ -1,23 +0,0 @@ | |||||||
| package installer |  | ||||||
| 
 |  | ||||||
| // "A little copying is better than a little dependency" |  | ||||||
| // These are here so that we don't need a dependency on http.FileSystem and http.File |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"io" |  | ||||||
| 	"os" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // Same as http.FileSystem |  | ||||||
| type FileSystem interface { |  | ||||||
| 	Open(name string) (File, error) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Same as http.File |  | ||||||
| type File interface { |  | ||||||
| 	io.Closer |  | ||||||
| 	io.Reader |  | ||||||
| 	io.Seeker |  | ||||||
| 	Readdir(count int) ([]os.FileInfo, error) |  | ||||||
| 	Stat() (os.FileInfo, error) |  | ||||||
| } |  | ||||||
| @ -1,68 +0,0 @@ | |||||||
| //go:generate go run -mod=vendor github.com/UnnoTed/fileb0x b0x.toml |  | ||||||
| 
 |  | ||||||
| // I'm prototyping this out to be useful for more than just watchdog |  | ||||||
| // hence there are a few unnecessary things for the sake of the trying it out |  | ||||||
| package installer |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| type Config struct { |  | ||||||
| 	Title               string            `json:"title"` |  | ||||||
| 	Name                string            `json:"name"` |  | ||||||
| 	Desc                string            `json:"desc"` |  | ||||||
| 	URL                 string            `json:"url"` |  | ||||||
| 	Interpreter         string            `json:"interpreter"` // i.e. node, python |  | ||||||
| 	Exec                string            `json:"exec"` |  | ||||||
| 	Argv                []string          `json:"argv"` |  | ||||||
| 	Args                string            `json:"-"` |  | ||||||
| 	Envs                map[string]string `json:"envs"` |  | ||||||
| 	User                string            `json:"user"` |  | ||||||
| 	Group               string            `json:"group"` |  | ||||||
| 	home                string            `json:"-"` |  | ||||||
| 	Local               string            `json:"local"` |  | ||||||
| 	LogDir              string            `json:"-"` |  | ||||||
| 	System              bool              `json:"system"` |  | ||||||
| 	Restart             bool              `json:"restart"` |  | ||||||
| 	Production          bool              `json:"production"` |  | ||||||
| 	PrivilegedPorts     bool              `json:"privileged_ports"` |  | ||||||
| 	MultiuserProtection bool              `json:"multiuser_protection"` |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func Install(c *Config) error { |  | ||||||
| 	if "" == c.Exec { |  | ||||||
| 		c.Exec = c.Name |  | ||||||
| 	} |  | ||||||
| 	c.Args = strings.Join(c.Argv, " ") |  | ||||||
| 
 |  | ||||||
| 	// TODO handle non-system installs |  | ||||||
| 	// * ~/.local/opt/watchdog/watchdog |  | ||||||
| 	// * ~/.local/share/watchdog/var/log/ |  | ||||||
| 	// * ~/.config/watchdog/watchdog.json |  | ||||||
| 	if !c.System { |  | ||||||
| 		home, err := os.UserHomeDir() |  | ||||||
| 		if nil != err { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		c.home = home |  | ||||||
| 		c.Local = filepath.Join(c.home, ".local") |  | ||||||
| 		c.LogDir = filepath.Join(c.home, ".local", "share", c.Name, "var", "log") |  | ||||||
| 	} else { |  | ||||||
| 		c.LogDir = "/var/log/" + c.Name |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	err := install(c) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	err = os.MkdirAll(c.LogDir, 0750) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| @ -1,64 +0,0 @@ | |||||||
| package installer |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"bytes" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io/ioutil" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" |  | ||||||
| 	"text/template" |  | ||||||
| 
 |  | ||||||
| 	"git.rootprojects.org/root/watchdog.go/cmd/watchdog/installer/static" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func install(c *Config) error { |  | ||||||
| 	// Darwin-specific config options |  | ||||||
| 	if c.PrivilegedPorts { |  | ||||||
| 		if !c.System { |  | ||||||
| 			return fmt.Errorf("You must use root-owned LaunchDaemons (not user-owned LaunchAgents) to use priveleged ports on OS X") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	plistDir := "/Library/LaunchDaemons/" |  | ||||||
| 	if !c.System { |  | ||||||
| 		plistDir = filepath.Join(c.home, "Library/LaunchAgents") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Check paths first |  | ||||||
| 	err := os.MkdirAll(filepath.Dir(plistDir), 0750) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Create service file from template |  | ||||||
| 	b, err := static.ReadFile("dist/Library/LaunchDaemons/_rdns_.plist.tmpl") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	s := string(b) |  | ||||||
| 	rw := &bytes.Buffer{} |  | ||||||
| 	// not sure what the template name does, but whatever |  | ||||||
| 	tmpl, err := template.New("service").Parse(s) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	err = tmpl.Execute(rw, c) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Write the file out |  | ||||||
| 	// TODO rdns |  | ||||||
| 	plistName := c.Name + ".plist" |  | ||||||
| 	plistPath := filepath.Join(plistDir, plistName) |  | ||||||
| 	if err := ioutil.WriteFile(plistPath, rw.Bytes(), 0644); err != nil { |  | ||||||
| 		fmt.Println("Use 'sudo' to install as a privileged system service.") |  | ||||||
| 		fmt.Println("Use '--userspace' to install as an user service.") |  | ||||||
| 		return fmt.Errorf("ioutil.WriteFile error: %v", err) |  | ||||||
| 	} |  | ||||||
| 	fmt.Printf("Installed. To start '%s' run the following:\n", c.Name) |  | ||||||
| 	// TODO template config file |  | ||||||
| 	fmt.Printf("\tlaunchctl load -w %s\n", strings.Replace(plistPath, c.home, "~", 1)) |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| @ -1,65 +0,0 @@ | |||||||
| package installer |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"bytes" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io/ioutil" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"text/template" |  | ||||||
| 
 |  | ||||||
| 	"git.rootprojects.org/root/watchdog.go/cmd/watchdog/installer/static" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func install(c *Config) error { |  | ||||||
| 	// Linux-specific config options |  | ||||||
| 	if c.System { |  | ||||||
| 		if "" == c.User { |  | ||||||
| 			c.User = "root" |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if "" == c.Group { |  | ||||||
| 		c.Group = c.User |  | ||||||
| 	} |  | ||||||
| 	serviceDir := "/etc/systemd/system/" |  | ||||||
| 
 |  | ||||||
| 	// Check paths first |  | ||||||
| 	serviceName := c.Name + ".service" |  | ||||||
| 	if !c.System { |  | ||||||
| 		// Not sure which of these it's supposed to be... |  | ||||||
| 		// * ~/.local/share/systemd/user/watchdog.service |  | ||||||
| 		// * ~/.config/systemd/user/watchdog.service |  | ||||||
| 		// https://wiki.archlinux.org/index.php/Systemd/User |  | ||||||
| 		serviceDir = filepath.Join(c.home, ".local/share/systemd/user") |  | ||||||
| 	} |  | ||||||
| 	err = os.MkdirAll(filepath.Dir(serviceDir), 0750) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Create service file from template |  | ||||||
| 	b, err := static.ReadFile("dist/etc/systemd/system/_name_.service.tmpl") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	s := string(b) |  | ||||||
| 	rw := &bytes.Buffer{} |  | ||||||
| 	// not sure what the template name does, but whatever |  | ||||||
| 	tmpl, err := template.New("service").Parse(s) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	err = tmpl.Execute(rw, c) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Write the file out |  | ||||||
| 	servicePath := filepath.Join(serviceDir, serviceName) |  | ||||||
| 	if err := ioutil.WriteFile(servicePath, rw.Bytes(), 0644); err != nil { |  | ||||||
| 		return fmt.Errorf("ioutil.WriteFile error: %v", err) |  | ||||||
| 	} |  | ||||||
| 	fmt.Printf("Wrote %q\n", servicePath) |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| @ -1,7 +0,0 @@ | |||||||
| // +build !windows,!linux,!darwin |  | ||||||
| 
 |  | ||||||
| package installer |  | ||||||
| 
 |  | ||||||
| func install(c *Config) error { |  | ||||||
| 	return nil, nil |  | ||||||
| } |  | ||||||
| @ -1,29 +0,0 @@ | |||||||
| # Pre-req |  | ||||||
| # sudo adduser watchdog --home /opt/watchdog |  | ||||||
| # sudo mkdir -p /opt/watchdog/ /var/log/watchdog |  | ||||||
| # sudo chown -R watchdog:watchdog /opt/watchdog/ /var/log/watchdog |  | ||||||
| 
 |  | ||||||
| [Unit] |  | ||||||
| Description=Watchdog - Get notified when sites go down |  | ||||||
| Documentation=https://git.rootprojects.org/root/watchdog.go |  | ||||||
| After=network-online.target |  | ||||||
| Wants=network-online.target systemd-networkd-wait-online.service |  | ||||||
| 
 |  | ||||||
| [Service] |  | ||||||
| # Restart on crash (bad signal), but not on 'clean' failure (error exit code) |  | ||||||
| # Allow up to 3 restarts within 10 seconds |  | ||||||
| # (it's unlikely that a user or properly-running script will do this) |  | ||||||
| Restart=on-abnormal |  | ||||||
| StartLimitInterval=10 |  | ||||||
| StartLimitBurst=3 |  | ||||||
| 
 |  | ||||||
| # User and group the process will run as |  | ||||||
| User=root |  | ||||||
| Group=root |  | ||||||
| 
 |  | ||||||
| WorkingDirectory=/opt/watchdog |  | ||||||
| ExecStart=/opt/watchdog -c ./config.json |  | ||||||
| ExecReload=/bin/kill -USR1 $MAINPID |  | ||||||
| 
 |  | ||||||
| [Install] |  | ||||||
| WantedBy=multi-user.target |  | ||||||
| @ -1,15 +0,0 @@ | |||||||
| // +build !windows |  | ||||||
| 
 |  | ||||||
| package installer |  | ||||||
| 
 |  | ||||||
| import "os/user" |  | ||||||
| 
 |  | ||||||
| func IsAdmin() bool { |  | ||||||
| 	u, err := user.Current() |  | ||||||
| 	if nil != err { |  | ||||||
| 		return false |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// not quite, but close enough for now |  | ||||||
| 	return "0" == u.Uid |  | ||||||
| } |  | ||||||
| @ -1,26 +0,0 @@ | |||||||
| package installer |  | ||||||
| 
 |  | ||||||
| import "os/user" |  | ||||||
| 
 |  | ||||||
| func IsAdmin() { |  | ||||||
| 	u, err := user.Current() |  | ||||||
| 	if nil != err { |  | ||||||
| 		return false |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems |  | ||||||
| 	// not quite, but close enough for now |  | ||||||
| 	// BUILTIN\ADMINISTRATORS |  | ||||||
| 	if "S-1-5-32-544" == u.Uid || "S-1-5-32-544" == u.Gid { |  | ||||||
| 		return true |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	ids := u.GroupIds() |  | ||||||
| 	for i := range ids { |  | ||||||
| 		if "S-1-5-32-544" == ids[i] { |  | ||||||
| 			return true |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return false |  | ||||||
| } |  | ||||||
| @ -11,7 +11,7 @@ import ( | |||||||
| 	"os" | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"git.rootprojects.org/root/watchdog.go" | 	watchdog "git.rootprojects.org/root/watchdog.go" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var GitRev, GitVersion, GitTimestamp string | var GitRev, GitVersion, GitTimestamp string | ||||||
| @ -21,7 +21,6 @@ func usage() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
| 	fmt.Println("Watchdog " + GitVersion) |  | ||||||
| 	for i := range os.Args { | 	for i := range os.Args { | ||||||
| 		switch { | 		switch { | ||||||
| 		case strings.HasSuffix(os.Args[i], "version"): | 		case strings.HasSuffix(os.Args[i], "version"): | ||||||
| @ -32,13 +31,6 @@ func main() { | |||||||
| 		case strings.HasSuffix(os.Args[i], "help"): | 		case strings.HasSuffix(os.Args[i], "help"): | ||||||
| 			usage() | 			usage() | ||||||
| 			os.Exit(0) | 			os.Exit(0) | ||||||
| 		case os.Args[i] == "install": |  | ||||||
| 			args := []string{} |  | ||||||
| 			if len(os.Args) > i+1 { |  | ||||||
| 				args = os.Args[i+1:] |  | ||||||
| 			} |  | ||||||
| 			install(os.Args[0], args) |  | ||||||
| 			os.Exit(0) |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,10 +0,0 @@ | |||||||
| { |  | ||||||
| 	"name": "Watchdog", |  | ||||||
| 	"desc": "Get notified when sites go down", |  | ||||||
| 	"url": "https://git.rootprojects.org/root/watchdog.go", |  | ||||||
| 	"exec": "watchdog", |  | ||||||
| 	"args": "-c ./config.json", |  | ||||||
| 	"user": "root", |  | ||||||
| 	"privileged_ports": false, |  | ||||||
| 	"multiuser_protection": false |  | ||||||
| } |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user