repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

pico / pipe
Antonio Mika · 07 Nov 24

ssh.go

 1package pipe
 2
 3import (
 4	"context"
 5	"fmt"
 6	"os"
 7	"os/signal"
 8	"syscall"
 9	"time"
10
11	"github.com/antoniomika/syncmap"
12	"github.com/charmbracelet/promwish"
13	"github.com/charmbracelet/ssh"
14	"github.com/charmbracelet/wish"
15	"github.com/picosh/pico/db/postgres"
16	"github.com/picosh/pico/shared"
17	wsh "github.com/picosh/pico/wish"
18	psub "github.com/picosh/pubsub"
19	"github.com/picosh/utils"
20)
21
22func StartSshServer() {
23	host := utils.GetEnv("PIPE_HOST", "0.0.0.0")
24	port := utils.GetEnv("PIPE_SSH_PORT", "2222")
25	portOverride := utils.GetEnv("PIPE_SSH_PORT_OVERRIDE", port)
26	promPort := utils.GetEnv("PIPE_PROM_PORT", "9222")
27	cfg := NewConfigSite()
28	logger := cfg.Logger
29	dbh := postgres.NewDB(cfg.DbURL, cfg.Logger)
30	defer dbh.Close()
31
32	cfg.Port = port
33	cfg.PortOverride = portOverride
34
35	pubsub := psub.NewMulticast(logger)
36	handler := &CliHandler{
37		Logger:  logger,
38		DBPool:  dbh,
39		PubSub:  pubsub,
40		Cfg:     cfg,
41		Waiters: syncmap.New[string, []string](),
42		Access:  syncmap.New[string, []string](),
43	}
44
45	sshAuth := shared.NewSshAuthHandler(dbh, logger, cfg)
46	s, err := wish.NewServer(
47		wish.WithAddress(fmt.Sprintf("%s:%s", host, port)),
48		wish.WithHostKeyPath("ssh_data/term_info_ed25519"),
49		wish.WithPublicKeyAuth(func(ctx ssh.Context, key ssh.PublicKey) bool {
50			sshAuth.PubkeyAuthHandler(ctx, key)
51			return true
52		}),
53		wish.WithMiddleware(
54			WishMiddleware(handler),
55			promwish.Middleware(fmt.Sprintf("%s:%s", host, promPort), "pipe-ssh"),
56			wsh.LogMiddleware(logger),
57		),
58	)
59	if err != nil {
60		logger.Error("wish server", "err", err.Error())
61		return
62	}
63
64	done := make(chan os.Signal, 1)
65	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
66	logger.Info("Starting SSH server", "host", host, "port", port)
67	go func() {
68		if err = s.ListenAndServe(); err != nil {
69			logger.Error("listen", "err", err.Error())
70		}
71	}()
72
73	<-done
74	logger.Info("Stopping SSH server")
75	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
76	defer func() { cancel() }()
77	if err := s.Shutdown(ctx); err != nil {
78		logger.Error("shutdown", "err", err.Error())
79	}
80}