Commit f591848f8a
Verified · cmc
Layout: unified · split
LICENSE added +10
| @@ -0,0 +1,10 @@ | ||
| 1 | Permission to use, copy, modify, and/or distribute this software for any | |
| 2 | purpose with or without fee is hereby granted. | |
| 3 | ||
| 4 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
| 5 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
| 6 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
| 7 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 8 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
| 9 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
| 10 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
README.org added +118
| @@ -0,0 +1,118 @@ | ||
| 1 | #+title: gitbay | |
| 2 | #+author: Christian Cleberg | |
| 3 | ||
| 4 | A CLI-first git forge. One binary, SQLite, and the system =git= — designed | |
| 5 | so the command line is the product and the web UI is a rendering of state | |
| 6 | the CLI already manages. Runs at [[https://gitbay.org]]. | |
| 7 | ||
| 8 | * Design | |
| 9 | ||
| 10 | SSH is the API. The server authenticates by public key, then dispatches the | |
| 11 | requested command: =git-upload-pack= / =git-receive-pack= stream the git | |
| 12 | transport, anything else is a control command. The control plane is fully | |
| 13 | usable from stock OpenSSH with no client installed: | |
| 14 | ||
| 15 | #+begin_src sh | |
| 16 | ssh git@gitbay.org repo create you/project --private | |
| 17 | ssh git@gitbay.org issue create you/project --title "bug" --file - < body.md | |
| 18 | ssh git@gitbay.org repo log you/project --json | |
| 19 | #+end_src | |
| 20 | ||
| 21 | The =gitbay= CLI is ergonomics on top — instance profiles, repo inference | |
| 22 | from the origin remote, =$EDITOR= for long text — never a requirement. A | |
| 23 | registry test enforces that every command stays reachable over bare ssh. | |
| 24 | ||
| 25 | Properties that follow from the design: | |
| 26 | ||
| 27 | - pushing is SSH-only. HTTPS and =git://= serve anonymous reads of public | |
| 28 | repositories; a push over HTTPS is answered with a pkt-line ERR that | |
| 29 | every git version prints as =remote error:= — no credential prompt, | |
| 30 | ever. Private repositories answer 404/not-found identically to | |
| 31 | nonexistent ones on every surface. | |
| 32 | - commit signatures (OpenPGP and SSHSIG) are verified against registered | |
| 33 | keys and verified emails, with six distinct states — =verified=, | |
| 34 | =signed_unknown_key=, =signed_email_mismatch=, =signed_key_expired=, | |
| 35 | =signed_key_revoked=, =bad_signature=, =unsigned= — cached and | |
| 36 | invalidated by a global key epoch, so registering a key retroactively | |
| 37 | verifies old commits. | |
| 38 | - there is no server signing key. Server-created commits (web edits, | |
| 39 | merge/squash/rebase commits) display honestly as unsigned, and branches | |
| 40 | with =require_signed_commits= accept only fast-forward merges of | |
| 41 | verified commits — enforced at push time and merge time. | |
| 42 | - the web UI is server-rendered with no JavaScript required. In | |
| 43 | =view_only= mode the mutating routes are never registered on the mux; | |
| 44 | browser sessions, where enabled, are minted over SSH (=web login=) — | |
| 45 | there are no passwords. | |
| 46 | ||
| 47 | * Features | |
| 48 | ||
| 49 | - repositories with per-branch protection, forks, and organizations | |
| 50 | (shared owner namespace, membership-derived access) | |
| 51 | - issues and merge requests (fast-forward, merge-commit, squash, rebase) | |
| 52 | entirely over ssh, with reviews that go stale on force-push | |
| 53 | - merge request heads are fetched /into/ the target repository, so an MR | |
| 54 | survives deletion of its source fork | |
| 55 | - =repo import= mirrors from any http(s)/git URL, tokens via stdin only | |
| 56 | - registration modes: =closed= (admin creates users), =invite=, =open= | |
| 57 | with SMTP email verification | |
| 58 | - signed outbound webhooks with retries, dead-lettering, and SSRF | |
| 59 | guarding; a JSON API (=POST /api/v1/cmd=) fronting the same command | |
| 60 | registry, with bearer tokens mintable only over SSH | |
| 61 | - built-in ACME (Let's Encrypt) TLS; =admin backup= produces one | |
| 62 | restore-tested archive (database snapshot first, then repositories) | |
| 63 | ||
| 64 | * Server quickstart | |
| 65 | ||
| 66 | #+begin_src sh | |
| 67 | # /etc/gitbay/config.toml | |
| 68 | [server] | |
| 69 | root = "/var/lib/gitbay" | |
| 70 | site_url = "https://forge.example.org" | |
| 71 | ||
| 72 | [http] | |
| 73 | acme_email = "you@example.org" | |
| 74 | #+end_src | |
| 75 | ||
| 76 | #+begin_src sh | |
| 77 | gitbayd --config /etc/gitbay/config.toml check-config | |
| 78 | gitbayd --config /etc/gitbay/config.toml admin user create you \ | |
| 79 | --key ~/.ssh/id_ed25519.pub --email you@example.org --verified --admin | |
| 80 | gitbayd --config /etc/gitbay/config.toml serve | |
| 81 | #+end_src | |
| 82 | ||
| 83 | The embedded SSH listener takes port 22 (move the host sshd, or set | |
| 84 | =ssh.mode = "system"= to run under it via =AuthorizedKeysCommand=). See | |
| 85 | =deploy/= for a cloud-init file, hardened systemd unit, and nightly | |
| 86 | backup timer. | |
| 87 | ||
| 88 | * Client quickstart | |
| 89 | ||
| 90 | #+begin_src sh | |
| 91 | gitbay remote add myforge forge.example.org --default | |
| 92 | gitbay auth whoami | |
| 93 | gitbay repo create you/project | |
| 94 | gitbay repo clone you/project && cd project | |
| 95 | gitbay issue create --title "first issue" # repo inferred from origin | |
| 96 | gitbay mr checkout 4 # fetches refs/merge-requests/4/head | |
| 97 | #+end_src | |
| 98 | ||
| 99 | Every read command takes =--json=; stdout is data, stderr is messages; | |
| 100 | exit codes are stable (0 ok, 2 usage, 3 not found, 4 denied). Man pages | |
| 101 | via =gitbay man=, completions via =gitbay completion <shell>=. | |
| 102 | ||
| 103 | * Development | |
| 104 | ||
| 105 | #+begin_src sh | |
| 106 | go build ./... | |
| 107 | go test ./... # e2e drives real git, ssh, sshd, and gpg binaries | |
| 108 | #+end_src | |
| 109 | ||
| 110 | Layout: =cmd/gitbay= (CLI), =cmd/gitbayd= (daemon, hooks, admin), | |
| 111 | =internal/control= (command registry — the single source of truth fronted | |
| 112 | by ssh and the JSON API), =internal/sshd= / =httpd= / =gitd= (transports), | |
| 113 | =internal/sig= (signature verification), =internal/policy= (access rules), | |
| 114 | =internal/store= (SQLite, migrations), =e2e/= (integration tests). | |
| 115 | ||
| 116 | * License | |
| 117 | ||
| 118 | 0BSD. | |