repos / pico

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

pico / pkg / apps / pipe
Eric Bower  ·  2026-01-25

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