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 "net"
15 "os"
16 "os/signal"
17 "syscall"
18 "time"
19
20 "github.com/charmbracelet/log"
21
22 "github.com/charmbracelet/soft-serve/server"
23 "github.com/charmbracelet/soft-serve/server/config"
24)
25
26var (
27 port = flag.Int("port", 22, "port to listen on")
28 gid = flag.Int("gid", 1000, "group id to run as")
29 uid = flag.Int("uid", 1000, "user id to run as")
30)
31
32func main() {
33 flag.Parse()
34 addr := fmt.Sprintf(":%d", *port)
35 // To listen on port 22 we need root privileges
36 ls, err := net.Listen("tcp", addr)
37 if err != nil {
38 log.Fatal("Can't listen", "err", err)
39 }
40 // We don't need root privileges any more
41 if err := syscall.Setgid(*gid); err != nil {
42 log.Fatal("Setgid error", "err", err)
43 }
44 if err := syscall.Setuid(*uid); err != nil {
45 log.Fatal("Setuid error", "err", err)
46 }
47 cfg := config.DefaultConfig()
48 cfg.Port = *port
49 s := server.NewServer(cfg)
50
51 done := make(chan os.Signal, 1)
52 signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
53
54 log.Print("Starting SSH server", "addr", fmt.Sprintf("%s:%d", cfg.BindAddr, cfg.Port))
55 go func() {
56 if err := s.Serve(ls); err != nil {
57 log.Fatal(err)
58 }
59 }()
60
61 <-done
62
63 log.Print("Stopping SSH server", fmt.Sprintf("%s:%d", cfg.BindAddr, cfg.Port))
64 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
65 defer func() { cancel() }()
66 if err := s.Shutdown(ctx); err != nil {
67 log.Fatal(err)
68 }
69}