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}