Monorepo for Tangled tangled.org
6

Configure Feed

Select the types of activity you want to include in your feed.

1package knotserver 2 3import ( 4 "context" 5 "fmt" 6 "net/http" 7 8 "github.com/bluesky-social/indigo/xrpc" 9 "github.com/urfave/cli/v3" 10 "tangled.org/core/api/tangled" 11 "tangled.org/core/hook" 12 "tangled.org/core/idresolver" 13 "tangled.org/core/jetstream" 14 "tangled.org/core/knotserver/config" 15 "tangled.org/core/knotserver/db" 16 "tangled.org/core/log" 17 "tangled.org/core/notifier" 18 "tangled.org/core/rbac" 19) 20 21func Command() *cli.Command { 22 return &cli.Command{ 23 Name: "server", 24 Usage: "run a knot server", 25 Action: Run, 26 Description: ` 27 Environment variables: 28 KNOT_SERVER_LISTEN_ADDR (default: 0.0.0.0:5555) 29 KNOT_SERVER_INTERNAL_LISTEN_ADDR (default: 127.0.0.1:5444) 30 KNOT_SERVER_DB_PATH (default: knotserver.db) 31 KNOT_SERVER_HOSTNAME (required) 32 KNOT_SERVER_JETSTREAM_ENDPOINT (default: wss://jetstream1.us-west.bsky.network/subscribe) 33 KNOT_SERVER_OWNER (required) 34 KNOT_SERVER_LOG_DIDS (default: true) 35 KNOT_SERVER_DEV (default: false) 36 KNOT_REPO_SCAN_PATH (default: /home/git) 37 KNOT_REPO_README (comma-separated list) 38 KNOT_REPO_MAIN_BRANCH (default: main) 39 KNOT_GIT_USER_NAME (default: Tangled) 40 KNOT_GIT_USER_EMAIL (default: noreply@tangled.sh) 41 APPVIEW_ENDPOINT (default: https://tangled.sh) 42 `, 43 } 44} 45 46func Run(ctx context.Context, cmd *cli.Command) error { 47 logger := log.FromContext(ctx) 48 logger = log.SubLogger(logger, cmd.Name) 49 ctx = log.IntoContext(ctx, logger) 50 51 c, err := config.Load(ctx) 52 if err != nil { 53 return fmt.Errorf("failed to load config: %w", err) 54 } 55 56 err = hook.Setup(hook.Config( 57 hook.WithScanPath(c.Repo.ScanPath), 58 hook.WithInternalApi(c.Server.InternalListenAddr), 59 )) 60 if err != nil { 61 return fmt.Errorf("failed to setup hooks: %w", err) 62 } 63 logger.Info("successfully finished setting up hooks") 64 65 if c.Server.Dev { 66 logger.Info("running in dev mode, signature verification is disabled") 67 } 68 69 db, err := db.Setup(ctx, c.Server.DBPath) 70 if err != nil { 71 return fmt.Errorf("failed to load db: %w", err) 72 } 73 74 e, err := rbac.NewEnforcer(c.Server.DBPath) 75 if err != nil { 76 return fmt.Errorf("failed to setup rbac enforcer: %w", err) 77 } 78 79 e.E.EnableAutoSave(true) 80 81 jc, err := jetstream.NewJetstreamClient(c.Server.JetstreamEndpoint, "knotserver", []string{ 82 tangled.PublicKeyNSID, 83 tangled.KnotMemberNSID, 84 tangled.RepoNSID, 85 tangled.RepoPullNSID, 86 tangled.RepoCollaboratorNSID, 87 }, nil, log.SubLogger(logger, "jetstream"), db, true, c.Server.LogDids) 88 if err != nil { 89 logger.Error("failed to setup jetstream", "error", err) 90 } 91 92 notifier := notifier.New() 93 94 resolver := idresolver.DefaultResolver(c.Server.PlcUrl) 95 96 if err := BackfillKnotMembers(ctx, db, e, resolver, c.Server.Hostname, logger); err != nil { 97 logger.Warn("knot members backfill failed, continuing", "err", err) 98 } 99 100 go migrateReposOnStartup(ctx, c, db, e, &notifier, log.SubLogger(logger, "migrate")) 101 102 mux, err := Setup(ctx, c, db, e, jc, &notifier, resolver) 103 if err != nil { 104 return fmt.Errorf("failed to setup server: %w", err) 105 } 106 107 imux := Internal(ctx, c, db, e, &notifier, resolver) 108 109 logger.Info("starting internal server", "address", c.Server.InternalListenAddr) 110 go http.ListenAndServe(c.Server.InternalListenAddr, imux) 111 112 // TODO(boltless): too lazy here. should clear this up 113 go func() { 114 input := &tangled.SyncRequestCrawl_Input{ 115 Hostname: c.Server.Hostname, 116 } 117 for _, knotmirror := range c.KnotMirrors { 118 xrpcc := xrpc.Client{Host: knotmirror} 119 if err := tangled.SyncRequestCrawl(ctx, &xrpcc, input); err != nil { 120 logger.Error("error requesting crawl", "err", err) 121 } else { 122 logger.Info("crawl requested successfully") 123 } 124 } 125 }() 126 127 logger.Info("starting main server", "address", c.Server.ListenAddr) 128 logger.Error("server error", "error", http.ListenAndServe(c.Server.ListenAddr, mux)) 129 130 return nil 131}