1package server
2
3import (
4 "context"
5 "fmt"
6 "log"
7
8 "github.com/charmbracelet/soft-serve/config"
9 appCfg "github.com/charmbracelet/soft-serve/internal/config"
10 "github.com/charmbracelet/soft-serve/internal/tui"
11
12 "github.com/charmbracelet/wish"
13 bm "github.com/charmbracelet/wish/bubbletea"
14 gm "github.com/charmbracelet/wish/git"
15 lm "github.com/charmbracelet/wish/logging"
16 rm "github.com/charmbracelet/wish/recover"
17 "github.com/gliderlabs/ssh"
18)
19
20// Server is the Soft Serve server.
21type Server struct {
22 SSHServer *ssh.Server
23 Config *config.Config
24 config *appCfg.Config
25}
26
27// NewServer returns a new *ssh.Server configured to serve Soft Serve. The SSH
28// server key-pair will be created if none exists. An initial admin SSH public
29// key can be provided with authKey. If authKey is provided, access will be
30// restricted to that key. If authKey is not provided, the server will be
31// publicly writable until configured otherwise by cloning the `config` repo.
32func NewServer(cfg *config.Config) *Server {
33 ac, err := appCfg.NewConfig(cfg)
34 if err != nil {
35 log.Fatal(err)
36 }
37 mw := []wish.Middleware{
38 rm.MiddlewareWithLogger(
39 cfg.ErrorLog,
40 bm.Middleware(tui.SessionHandler(ac)),
41 gm.Middleware(cfg.RepoPath, ac),
42 lm.Middleware(),
43 ),
44 }
45 s, err := wish.NewServer(
46 ssh.PublicKeyAuth(ac.PublicKeyHandler),
47 ssh.PasswordAuth(ac.PasswordHandler),
48 wish.WithAddress(fmt.Sprintf("%s:%d", cfg.BindAddr, cfg.Port)),
49 wish.WithHostKeyPath(cfg.KeyPath),
50 wish.WithMiddleware(mw...),
51 )
52 if err != nil {
53 log.Fatalln(err)
54 }
55 return &Server{
56 SSHServer: s,
57 Config: cfg,
58 config: ac,
59 }
60}
61
62// Reload reloads the server configuration.
63func (srv *Server) Reload() error {
64 return srv.config.Reload()
65}
66
67// Start starts the SSH server.
68func (srv *Server) Start() error {
69 return srv.SSHServer.ListenAndServe()
70}
71
72// Shutdown lets the server gracefully shutdown.
73func (srv *Server) Shutdown(ctx context.Context) error {
74 return srv.SSHServer.Shutdown(ctx)
75}