repos / pico

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

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

ssh.go

 1package pgs
 2
 3import (
 4	"context"
 5	"os"
 6	"os/signal"
 7	"syscall"
 8
 9	"github.com/picosh/pico/pkg/pssh"
10	"github.com/picosh/pico/pkg/send/auth"
11	"github.com/picosh/pico/pkg/send/list"
12	"github.com/picosh/pico/pkg/send/pipe"
13	"github.com/picosh/pico/pkg/send/protocols/rsync"
14	"github.com/picosh/pico/pkg/send/protocols/scp"
15	"github.com/picosh/pico/pkg/send/protocols/sftp"
16	"github.com/picosh/pico/pkg/shared"
17	"github.com/picosh/pico/pkg/tunkit"
18)
19
20func StartSshServer(cfg *PgsConfig, killCh chan error) {
21	host := shared.GetEnv("PGS_HOST", "0.0.0.0")
22	port := shared.GetEnv("PGS_SSH_PORT", "2222")
23	promPort := shared.GetEnv("PGS_PROM_PORT", "9222")
24	logger := cfg.Logger
25
26	ctx, cancel := context.WithCancel(context.Background())
27	defer cancel()
28
29	cacheClearingQueue := make(chan string, 100)
30	handler := NewUploadAssetHandler(
31		cfg,
32		cacheClearingQueue,
33		ctx,
34	)
35
36	sshAuth := shared.NewSshAuthHandler(cfg.DB, logger, "pgs")
37
38	webTunnel := &tunkit.WebTunnelHandler{
39		Logger:      logger,
40		HttpHandler: CreateHttpHandler(cfg),
41	}
42
43	// Create a new SSH server
44	server, err := pssh.NewSSHServerWithConfig(
45		ctx,
46		logger,
47		"pgs-ssh",
48		host,
49		port,
50		promPort,
51		"ssh_data/term_info_ed25519",
52		sshAuth.PubkeyAuthHandler,
53		[]pssh.SSHServerMiddleware{
54			pipe.Middleware(handler, ""),
55			list.Middleware(handler),
56			scp.Middleware(handler),
57			rsync.Middleware(handler),
58			auth.Middleware(handler),
59			Middleware(handler),
60			pssh.LogMiddleware(handler, handler.Cfg.DB),
61		},
62		[]pssh.SSHServerMiddleware{
63			sftp.Middleware(handler),
64			pssh.LogMiddleware(handler, handler.Cfg.DB),
65		},
66		map[string]pssh.SSHServerChannelMiddleware{
67			"direct-tcpip": tunkit.LocalForwardHandler(webTunnel),
68		},
69	)
70
71	if err != nil {
72		logger.Error("failed to create ssh server", "err", err.Error())
73		os.Exit(1)
74	}
75
76	done := make(chan os.Signal, 1)
77	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
78	logger.Info("Starting SSH server", "addr", server.Config.ListenAddr)
79	go func() {
80		if err = server.ListenAndServe(); err != nil {
81			logger.Error("serve", "err", err.Error())
82			os.Exit(1)
83		}
84	}()
85
86	exit := func() {
87		logger.Info("stopping ssh server")
88		cancel()
89	}
90
91	select {
92	case <-killCh:
93		exit()
94	case <-done:
95		exit()
96	}
97}