main.go

 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}