repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

pico / pkg / apps / pipe
Antonio Mika  ·  2025-03-30

ssh.go

  1package pipe
  2
  3import (
  4	"context"
  5	"os"
  6	"os/signal"
  7	"syscall"
  8
  9	"github.com/antoniomika/syncmap"
 10	"github.com/picosh/pico/pkg/db/postgres"
 11	"github.com/picosh/pico/pkg/pssh"
 12	"github.com/picosh/pico/pkg/shared"
 13	psub "github.com/picosh/pubsub"
 14	"github.com/picosh/utils"
 15	"golang.org/x/crypto/ssh"
 16)
 17
 18func StartSshServer() {
 19	appName := "pipe-ssh"
 20
 21	host := utils.GetEnv("PIPE_HOST", "0.0.0.0")
 22	port := utils.GetEnv("PIPE_SSH_PORT", "2222")
 23	portOverride := utils.GetEnv("PIPE_SSH_PORT_OVERRIDE", port)
 24	promPort := utils.GetEnv("PIPE_PROM_PORT", "9222")
 25	cfg := NewConfigSite(appName)
 26	logger := cfg.Logger
 27
 28	ctx, cancel := context.WithCancel(context.Background())
 29	defer cancel()
 30
 31	dbh := postgres.NewDB(cfg.DbURL, cfg.Logger)
 32	defer dbh.Close()
 33
 34	cfg.Port = port
 35	cfg.PortOverride = portOverride
 36
 37	pubsub := psub.NewMulticast(logger)
 38	handler := &CliHandler{
 39		Logger:  logger,
 40		DBPool:  dbh,
 41		PubSub:  pubsub,
 42		Cfg:     cfg,
 43		Waiters: syncmap.New[string, []string](),
 44		Access:  syncmap.New[string, []string](),
 45	}
 46
 47	sshAuth := shared.NewSshAuthHandler(dbh, logger)
 48
 49	// Create a new SSH server
 50	server, err := pssh.NewSSHServerWithConfig(
 51		ctx,
 52		logger,
 53		appName,
 54		host,
 55		port,
 56		promPort,
 57		"ssh_data/term_info_ed25519",
 58		func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
 59			perms, _ := sshAuth.PubkeyAuthHandler(conn, key)
 60			if perms == nil {
 61				perms = &ssh.Permissions{
 62					Extensions: map[string]string{
 63						"pubkey": utils.KeyForKeyText(key),
 64					},
 65				}
 66			}
 67
 68			return perms, nil
 69		},
 70		[]pssh.SSHServerMiddleware{
 71			Middleware(handler),
 72			pssh.LogMiddleware(handler, dbh),
 73		},
 74		nil,
 75		nil,
 76	)
 77
 78	if err != nil {
 79		logger.Error("failed to create ssh server", "err", err.Error())
 80		os.Exit(1)
 81	}
 82
 83	done := make(chan os.Signal, 1)
 84	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
 85	logger.Info("Starting SSH server", "addr", server.Config.ListenAddr)
 86	go func() {
 87		if err = server.ListenAndServe(); err != nil {
 88			logger.Error("serve", "err", err.Error())
 89			os.Exit(1)
 90		}
 91	}()
 92
 93	exit := func() {
 94		logger.Info("stopping ssh server")
 95		cancel()
 96	}
 97
 98	<-done
 99	exit()
100}