repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

Eric Bower  ·  2026-02-24

ssh.go

 1package git
 2
 3import (
 4	"context"
 5	"fmt"
 6	"os"
 7	"path/filepath"
 8
 9	"github.com/picosh/pico/pkg/pssh"
10	"golang.org/x/crypto/ssh"
11)
12
13func authHandler(pr *PrCmd) func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
14	return func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
15		pubkey := pr.Backend.Pubkey(key)
16		userName := conn.User()
17		perms := &ssh.Permissions{
18			Extensions: map[string]string{
19				"pubkey": pubkey,
20			},
21		}
22		err := pr.IsBanned(pubkey, userName)
23		if err != nil {
24			pr.Backend.Logger.Info(
25				"user denied access",
26				"err", err,
27				"username", userName,
28				"pubkey", pubkey,
29			)
30			return perms, err
31		}
32		return perms, nil
33	}
34}
35
36func GitSshServer(ctx context.Context, cfg *GitCfg) *pssh.SSHServer {
37	dbpath := filepath.Join(cfg.DataDir, "pr.db?_fk=on")
38	dbh, err := SqliteOpen("file:"+dbpath, cfg.Logger)
39	if err != nil {
40		panic(fmt.Sprintf("cannot find database file, check folder and perms: %s: %s", dbpath, err))
41	}
42
43	be := &Backend{
44		DB:     dbh,
45		Logger: cfg.Logger,
46		Cfg:    cfg,
47	}
48
49	prCmd := &PrCmd{
50		Backend: be,
51	}
52
53	server, err := pssh.NewSSHServerWithConfig(
54		ctx,
55		cfg.Logger,
56		"git-pr",
57		cfg.Host,
58		cfg.SshPort,
59		cfg.PromPort,
60		filepath.Join(cfg.DataDir, "term_info_ed25519"),
61		authHandler(prCmd),
62		[]pssh.SSHServerMiddleware{
63			GitPatchRequestMiddleware(be, prCmd),
64		},
65		[]pssh.SSHServerMiddleware{},
66		nil,
67	)
68
69	if err != nil {
70		cfg.Logger.Error("failed to create ssh server", "err", err)
71		os.Exit(1)
72	}
73
74	return server
75}