@@ -0,0 +1,65 @@
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package main
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+
+ "github.com/charmbracelet/soft-serve/config"
+ "github.com/charmbracelet/soft-serve/server"
+)
+
+const (
+ port = 22
+ gid = 1000
+ uid = 1000
+)
+
+var (
+ addr = fmt.Sprintf(":%d", port)
+)
+
+func main() {
+ // To listen on port 22 we need root privileges
+ ls, err := net.Listen("tcp", addr)
+ if err != nil {
+ log.Fatalf("Can't listen: %s", err)
+ }
+ // We don't need root privileges any more
+ if err := syscall.Setgid(gid); err != nil {
+ log.Fatalf("Setgid error: %s", err)
+ }
+ if err := syscall.Setuid(uid); err != nil {
+ log.Fatalf("Setuid error: %s", err)
+ }
+ cfg := config.DefaultConfig()
+ cfg.Port = port
+ s := server.NewServer(cfg)
+
+ done := make(chan os.Signal, 1)
+ signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
+
+ log.Printf("Starting SSH server on %s:%d", cfg.BindAddr, cfg.Port)
+ go func() {
+ if err := s.Serve(ls); err != nil {
+ log.Fatalln(err)
+ }
+ }()
+
+ <-done
+
+ log.Printf("Stopping SSH server on %s:%d", cfg.BindAddr, cfg.Port)
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer func() { cancel() }()
+ if err := s.Shutdown(ctx); err != nil {
+ log.Fatalln(err)
+ }
+}
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log"
+ "net"
"github.com/charmbracelet/soft-serve/config"
appCfg "github.com/charmbracelet/soft-serve/internal/config"
@@ -69,6 +70,11 @@ func (srv *Server) Start() error {
return srv.SSHServer.ListenAndServe()
}
+// Serve serves the SSH server using the provided listener.
+func (srv *Server) Serve(l net.Listener) error {
+ return srv.SSHServer.Serve(l)
+}
+
// Shutdown lets the server gracefully shutdown.
func (srv *Server) Shutdown(ctx context.Context) error {
return srv.SSHServer.Shutdown(ctx)