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 ctx := context.Background()
48 config.SSH.ListenAddr = fmt.Sprintf(":%d", *port)
49 s, err := server.NewServer(ctx)
50 if err != nil {
51 log.Fatal(err)
52 }
53
54 done := make(chan os.Signal, 1)
55 signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
56
57 log.Print("Starting SSH server", "addr", config.SSH.ListenAddr)
58 go func() {
59 if err := s.SSHServer.Serve(ls); err != nil {
60 log.Fatal(err)
61 }
62 }()
63
64 <-done
65
66 log.Print("Stopping SSH server", "addr", config.SSH.ListenAddr)
67 ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
68 defer func() { cancel() }()
69 if err := s.Shutdown(ctx); err != nil {
70 log.Fatal(err)
71 }
72}