Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Code

392 commit(s) on main

Merge change request 01M70WES5ZZDJ6RP226WB11BBZ: Let people rename and remove their own passkeys keenan · 2h ago 4b8c9e1d
history blame raw 1.4 KiB
1package main
2
3import (
4 "context"
5 "fmt"
6 "log/slog"
7 "os"
8 "os/signal"
9 "path/filepath"
10 "syscall"
11
12 "rodent.software/vole/forge/config"
13 "rodent.software/vole/server"
14)
15
16// ---------- serve ----------
17
18const serveUsage = `usage: vole serve [--config <path>] [--log debug]`
19
20func cmdServe(args []string) error {
21 f, err := parseFlags(args, configFlag(), flagSpec{long: "log"})
22 if err != nil {
23 return err
24 }
25 if f.help {
26 fmt.Fprintln(os.Stdout, serveUsage)
27 return nil
28 }
29 if len(f.rest) > 0 {
30 return usagef("unexpected argument %q", f.rest[0])
31 }
32 cfg, err := config.Load(config.ResolvePath(f.cfgPath))
33 if err != nil {
34 return err
35 }
36 level := slog.LevelInfo
37 switch f.one("log") {
38 case "", "info":
39 case "debug":
40 level = slog.LevelDebug
41 default:
42 return usagef("--log must be info or debug")
43 }
44 log := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level}))
45 slog.SetDefault(log)
46
47 bin, err := os.Executable()
48 if err != nil {
49 return err
50 }
51 bin, _ = filepath.Abs(bin)
52
53 srv, err := server.New(cfg, bin, log)
54 if err != nil {
55 return err
56 }
57 defer srv.Close()
58
59 if n := srv.Identity.Snapshot().Count; n == 0 {
60 log.Warn("no accounts yet; add one with: vole admin account create <name> --key ~/.ssh/id_ed25519.pub")
61 }
62
63 ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
64 defer stop()
65 return srv.Run(ctx)
66}
67