1//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
2// +build darwin dragonfly freebsd linux netbsd openbsd solaris
3
4// This is an example of binding soft-serve ssh port to a restricted port (<1024) and
5// then droping root privileges to a different user to run the server.
6// Make sure you run this as root.
7
8package main
9
10import (
11 "context"
12 "flag"
13 "fmt"
14 "log"
15 "net"
16 "os"
17 "os/signal"
18 "syscall"
19 "time"
20
21 "github.com/charmbracelet/soft-serve/server"
22 "github.com/charmbracelet/soft-serve/server/config"
23)
24
25var (
26 port = flag.Int("port", 22, "port to listen on")
27 gid = flag.Int("gid", 1000, "group id to run as")
28 uid = flag.Int("uid", 1000, "user id to run as")
29)
30
31func main() {
32 flag.Parse()
33 addr := fmt.Sprintf(":%d", *port)
34 // To listen on port 22 we need root privileges
35 ls, err := net.Listen("tcp", addr)
36 if err != nil {
37 log.Fatalf("Can't listen: %s", err)
38 }
39 // We don't need root privileges any more
40 if err := syscall.Setgid(*gid); err != nil {
41 log.Fatalf("Setgid error: %s", err)
42 }
43 if err := syscall.Setuid(*uid); err != nil {
44 log.Fatalf("Setuid error: %s", err)
45 }
46 cfg := config.DefaultConfig()
47 cfg.Port = *port
48 s := server.NewServer(cfg)
49
50 done := make(chan os.Signal, 1)
51 signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
52
53 log.Printf("Starting SSH server on %s:%d", cfg.BindAddr, cfg.Port)
54 go func() {
55 if err := s.SSHServer.Serve(ls); err != nil {
56 log.Fatalln(err)
57 }
58 }()
59
60 <-done
61
62 log.Printf("Stopping SSH server on %s:%d", cfg.BindAddr, cfg.Port)
63 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
64 defer func() { cancel() }()
65 if err := s.Shutdown(ctx); err != nil {
66 log.Fatalln(err)
67 }
68}