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}