Eric Bower
·
2026-01-25
ssh.go
1package pastes
2
3import (
4 "context"
5 "os"
6 "os/signal"
7 "syscall"
8 "time"
9
10 "github.com/picosh/pico/pkg/db/postgres"
11 "github.com/picosh/pico/pkg/filehandlers"
12 "github.com/picosh/pico/pkg/pssh"
13 "github.com/picosh/pico/pkg/send/auth"
14 "github.com/picosh/pico/pkg/send/list"
15 "github.com/picosh/pico/pkg/send/pipe"
16 "github.com/picosh/pico/pkg/send/protocols/rsync"
17 "github.com/picosh/pico/pkg/send/protocols/scp"
18 "github.com/picosh/pico/pkg/send/protocols/sftp"
19 "github.com/picosh/pico/pkg/shared"
20)
21
22func StartSshServer() {
23 appName := "pastes-ssh"
24
25 host := shared.GetEnv("PASTES_HOST", "0.0.0.0")
26 port := shared.GetEnv("PASTES_SSH_PORT", "2222")
27 promPort := shared.GetEnv("PASTES_PROM_PORT", "9222")
28 cfg := NewConfigSite(appName)
29 logger := cfg.Logger
30
31 ctx, cancel := context.WithCancel(context.Background())
32 defer cancel()
33
34 dbh := postgres.NewDB(cfg.DbURL, cfg.Logger)
35 defer func() {
36 _ = dbh.Close()
37 }()
38 hooks := &FileHooks{
39 Cfg: cfg,
40 Db: dbh,
41 }
42
43 fileMap := map[string]filehandlers.ReadWriteHandler{
44 "fallback": filehandlers.NewScpPostHandler(dbh, cfg, hooks),
45 }
46 handler := filehandlers.NewFileHandlerRouter(cfg, dbh, fileMap)
47 sshAuth := shared.NewSshAuthHandler(dbh, logger, "pastes")
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 sshAuth.PubkeyAuthHandler,
59 []pssh.SSHServerMiddleware{
60 pipe.Middleware(handler, ""),
61 list.Middleware(handler),
62 scp.Middleware(handler),
63 rsync.Middleware(handler),
64 auth.Middleware(handler),
65 pssh.PtyMdw(pssh.DeprecatedNotice(), 200*time.Millisecond),
66 pssh.LogMiddleware(handler, dbh),
67 },
68 []pssh.SSHServerMiddleware{
69 sftp.Middleware(handler),
70 pssh.LogMiddleware(handler, dbh),
71 },
72 nil,
73 )
74
75 if err != nil {
76 logger.Error("failed to create ssh server", "err", err.Error())
77 os.Exit(1)
78 }
79
80 done := make(chan os.Signal, 1)
81 signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
82 logger.Info("Starting SSH server", "addr", server.Config.ListenAddr)
83 go func() {
84 if err = server.ListenAndServe(); err != nil {
85 logger.Error("serve", "err", err.Error())
86 os.Exit(1)
87 }
88 }()
89
90 exit := func() {
91 logger.Info("stopping ssh server")
92 cancel()
93 }
94
95 <-done
96 exit()
97}