Eric Bower
·
2026-03-05
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 createSshServer(cfg *PgsConfig, ctx context.Context, cacheClearingQueue chan string) (*pssh.SSHServer, 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 handler := NewUploadAssetHandler(
27 cfg,
28 cacheClearingQueue,
29 ctx,
30 )
31
32 sshAuth := shared.NewSshAuthHandler(cfg.DB, logger, "pgs")
33
34 webTunnel := &tunkit.WebTunnelHandler{
35 Logger: logger,
36 HttpHandler: CreateHttpHandler(cfg),
37 }
38
39 // Create a new SSH server
40 server, err := pssh.NewSSHServerWithConfig(
41 ctx,
42 logger,
43 "pgs-ssh",
44 host,
45 port,
46 promPort,
47 "ssh_data/term_info_ed25519",
48 sshAuth.PubkeyAuthHandler,
49 []pssh.SSHServerMiddleware{
50 pipe.Middleware(handler, ""),
51 list.Middleware(handler),
52 scp.Middleware(handler),
53 rsync.Middleware(handler),
54 auth.Middleware(handler),
55 Middleware(handler),
56 pssh.LogMiddleware(handler, handler.Cfg.DB),
57 },
58 []pssh.SSHServerMiddleware{
59 sftp.Middleware(handler),
60 pssh.LogMiddleware(handler, handler.Cfg.DB),
61 },
62 map[string]pssh.SSHServerChannelMiddleware{
63 "direct-tcpip": tunkit.LocalForwardHandler(webTunnel),
64 },
65 )
66
67 return server, err
68}
69
70func StartSshServer(cfg *PgsConfig, killCh chan error) {
71 ctx, cancel := context.WithCancel(context.Background())
72 defer cancel()
73
74 cacheClearingQueue := make(chan string, 100)
75 logger := cfg.Logger
76
77 server, err := createSshServer(cfg, ctx, cacheClearingQueue)
78 if err != nil {
79 logger.Error("failed to create ssh server", "err", err.Error())
80 os.Exit(1)
81 }
82
83 // start cron job for bin project ttl
84 go BinCron(cfg)
85
86 done := make(chan os.Signal, 1)
87 signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
88 logger.Info("Starting SSH server", "addr", server.Config.ListenAddr)
89 go func() {
90 if err = server.ListenAndServe(); err != nil {
91 logger.Error("serve", "err", err.Error())
92 os.Exit(1)
93 }
94 }()
95
96 exit := func() {
97 logger.Info("stopping ssh server")
98 cancel()
99 }
100
101 select {
102 case <-killCh:
103 exit()
104 case <-done:
105 exit()
106 }
107}