repos / pico

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

pico / pkg / apps / prose
Antonio Mika  ·  2025-04-10

ssh.go

  1package prose
  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	uploadimgs "github.com/picosh/pico/pkg/filehandlers/imgs"
 13	"github.com/picosh/pico/pkg/pssh"
 14	"github.com/picosh/pico/pkg/send/auth"
 15	"github.com/picosh/pico/pkg/send/list"
 16	"github.com/picosh/pico/pkg/send/pipe"
 17	"github.com/picosh/pico/pkg/send/protocols/rsync"
 18	"github.com/picosh/pico/pkg/send/protocols/scp"
 19	"github.com/picosh/pico/pkg/send/protocols/sftp"
 20	"github.com/picosh/pico/pkg/shared"
 21	"github.com/picosh/pico/pkg/shared/storage"
 22	"github.com/picosh/utils"
 23)
 24
 25func StartSshServer() {
 26	appName := "prose-ssh"
 27
 28	host := utils.GetEnv("PROSE_HOST", "0.0.0.0")
 29	port := utils.GetEnv("PROSE_SSH_PORT", "2222")
 30	promPort := utils.GetEnv("PROSE_PROM_PORT", "9222")
 31	cfg := NewConfigSite(appName)
 32	logger := cfg.Logger
 33
 34	ctx, cancel := context.WithCancel(context.Background())
 35	defer cancel()
 36
 37	dbh := postgres.NewDB(cfg.DbURL, cfg.Logger)
 38	defer dbh.Close()
 39
 40	hooks := &MarkdownHooks{
 41		Cfg: cfg,
 42		Db:  dbh,
 43	}
 44
 45	var st storage.StorageServe
 46	var err error
 47	if cfg.MinioURL == "" {
 48		st, err = storage.NewStorageFS(cfg.Logger, cfg.StorageDir)
 49	} else {
 50		st, err = storage.NewStorageMinio(cfg.Logger, cfg.MinioURL, cfg.MinioUser, cfg.MinioPass)
 51	}
 52
 53	if err != nil {
 54		logger.Error("storage", "err", err.Error())
 55		return
 56	}
 57
 58	fileMap := map[string]filehandlers.ReadWriteHandler{
 59		".md":      filehandlers.NewScpPostHandler(dbh, cfg, hooks),
 60		".css":     filehandlers.NewScpPostHandler(dbh, cfg, hooks),
 61		"fallback": uploadimgs.NewUploadImgHandler(dbh, cfg, st),
 62	}
 63	handler := filehandlers.NewFileHandlerRouter(cfg, dbh, fileMap)
 64
 65	sshAuth := shared.NewSshAuthHandler(dbh, logger)
 66
 67	// Create a new SSH server
 68	server, err := pssh.NewSSHServerWithConfig(
 69		ctx,
 70		logger,
 71		appName,
 72		host,
 73		port,
 74		promPort,
 75		"ssh_data/term_info_ed25519",
 76		sshAuth.PubkeyAuthHandler,
 77		[]pssh.SSHServerMiddleware{
 78			pipe.Middleware(handler, ".md"),
 79			list.Middleware(handler),
 80			scp.Middleware(handler),
 81			rsync.Middleware(handler),
 82			auth.Middleware(handler),
 83			pssh.PtyMdw(pssh.DeprecatedNotice(), 200*time.Millisecond),
 84			pssh.LogMiddleware(handler, dbh),
 85		},
 86		[]pssh.SSHServerMiddleware{
 87			sftp.Middleware(handler),
 88			pssh.LogMiddleware(handler, dbh),
 89		},
 90		nil,
 91	)
 92
 93	if err != nil {
 94		logger.Error("failed to create ssh server", "err", err.Error())
 95		os.Exit(1)
 96	}
 97
 98	done := make(chan os.Signal, 1)
 99	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
100	logger.Info("Starting SSH server", "addr", server.Config.ListenAddr)
101	go func() {
102		if err = server.ListenAndServe(); err != nil {
103			logger.Error("serve", "err", err.Error())
104			os.Exit(1)
105		}
106	}()
107
108	exit := func() {
109		logger.Info("stopping ssh server")
110		cancel()
111	}
112
113	<-done
114	exit()
115}