repos / pico

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

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

ssh.go

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