package main import ( "flag" "fmt" "log" "net" "net/http" "os" "os/exec" "os/signal" "strings" "syscall" ) func indexHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("Hello, this is a Unix socket HTTP server in Go!")) } func healthCheckHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("healthy")) } func main() { socketPath, users := getArgs() os.Remove(socketPath) listener, err := net.Listen("unix", socketPath) if err != nil { panic(err) } os.Chmod(socketPath, 0700) sigc := make(chan os.Signal, 1) signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM) go func(c chan os.Signal) { // Wait for a SIGINT or SIGKILL: sig := <-c log.Printf("Caught signal %s: shutting down.", sig) listener.Close() os.Exit(0) }(sigc) defer listener.Close() for _, user := range strings.Split(users, ",") { setACL(socketPath, user) } mux := http.NewServeMux() mux.HandleFunc("/", indexHandler) mux.HandleFunc("/health", healthCheckHandler) http.Serve(listener, mux) } func setACL(socketPath, user string) { cmd := exec.Command("setfacl", "-m", "u:"+user+":rwx", socketPath) if err := cmd.Run(); err != nil { panic("failed to set ACL: " + err.Error()) } } func getArgs() (string, string) { socketPath := flag.String("socket-path", "/tmp/go-server.sock", "Path to the Unix socket") users := flag.String("users", "", "Comma-separated list of users for ACL") flag.Parse() if *users == "" { fmt.Println("You must specify at least one user with --users") os.Exit(1) } return *socketPath, *users }