A CLI-first git forge.

cli forge git self-hosted

https://gitbay.org

Commit dc0ea39b4b

dc0ea39b4be599c340d888a080b5b2ebfc106736

parent: 617b05d09b

Verified · cmc ci/build: success

cmc <hello@cleberg.net> · 2026-08-25T17:05:11Z

Pages apex: on-demand cert and redirect to the forge
cmd/gitbayd/main.go +3
@@ -184,6 +184,9 @@ func serveCmd() *cobra.Command {
184184 return nil
185185 }
186186 if pd := cfg.Pages.Domain; pd != "" {
187 if h == pd {
188 return nil // apex: serves a redirect to the forge
189 }
187190 if owner, ok := strings.CutSuffix(h, "."+pd); ok &&
188191 !strings.Contains(owner, ".") && st.OwnerExists(owner) {
189192 return nil
e2e/pages_test.go +4 −1
@@ -107,12 +107,15 @@ func TestPages(t *testing.T) {
107107 for _, tc := range []struct{ host, path string }{
108108 {"alice.p.test", "/secret/"},
109109 {"bob.p.test", "/"},
110 {"p.test", "/"},
111110 } {
112111 if resp, _ = inst.pagesGet(t, tc.host, tc.path); resp.StatusCode != 404 {
113112 t.Fatalf("%s%s: %d, want 404", tc.host, tc.path, resp.StatusCode)
114113 }
115114 }
115 // The apex redirects to the forge.
116 if resp, _ = inst.pagesGet(t, "p.test", "/"); resp.StatusCode != 302 || !strings.Contains(resp.Header.Get("Location"), "gitbay.test") {
117 t.Fatalf("apex: %d -> %s", resp.StatusCode, resp.Header.Get("Location"))
118 }
116119
117120 // The forge itself still answers on its own host.
118121 if status, _ := inst.get(t, "/explore"); status != 200 {
internal/httpd/pages.go +5
@@ -46,6 +46,11 @@ func (s *Server) servePage(w http.ResponseWriter, r *http.Request, host string)
4646 http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
4747 return
4848 }
49 // The apex has no site of its own; send visitors to the forge.
50 if host == s.cfg.Pages.Domain {
51 http.Redirect(w, r, s.cfg.Server.SiteURL, http.StatusFound)
52 return
53 }
4954 owner, ok := strings.CutSuffix(host, "."+s.cfg.Pages.Domain)
5055 if !ok || owner == "" || strings.Contains(owner, ".") {
5156 http.NotFound(w, r)