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	"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}