docs/admin.org

b937a769f31481aa5f2e4e70711dea53e22ce6da
gitbay/docs/admin.org rendered · source · history · blame · raw

193 lines · 7945 bytes

  1#+title: gitbay admin guide
  2
  3One static binary (=gitbayd=), one SQLite file, bare repositories on
  4disk, and the system =git=. Schema migrations run automatically on
  5startup and on every admin command.
  6
  7* Install
  8
  9Build from source (=go build ./cmd/gitbayd=), install via the vanity
 10module path (=go install gitbay.org/gitbay/cmd/gitbayd@latest=), or use
 11a release build: =deploy/release.sh <tag>= cross-compiles reproducible
 12linux/amd64, linux/arm64, and darwin/arm64 binaries with a SHA256SUMS
 13manifest (CGO off, trimpath, stripped — byte-identical per commit and
 14toolchain).
 15
 16#+begin_src sh
 17install -m 755 gitbayd /usr/local/bin/
 18adduser --system --group --home /var/lib/gitbay --shell /usr/sbin/nologin gitbay
 19install -d -o gitbay -g gitbay -m 750 /var/lib/gitbay
 20gitbayd --config /etc/gitbay/config.toml check-config
 21#+end_src
 22
 23=deploy/= in the source tree has a cloud-init file, a hardened systemd
 24unit, and a nightly backup timer. Run as the unprivileged =gitbay= user;
 25the unit's =AmbientCapabilities=CAP_NET_BIND_SERVICE= covers ports
 2622/80/443 without root.
 27
 28** The SSH port decision
 29
 30- =ssh.mode = "embedded"= (default): gitbayd itself listens, normally on
 31  22 — move the host's admin sshd to another port. Remotes read
 32  =git@host:owner/repo= with no port gymnastics.
 33- =ssh.mode = "system"=: the host sshd owns 22 and invokes gitbayd via
 34  =AuthorizedKeysCommand=:
 35  #+begin_example
 36  AuthorizedKeysCommand /usr/local/bin/gitbayd --config /etc/gitbay/config.toml authorized-keys %t %k
 37  AuthorizedKeysCommandUser gitbay
 38  #+end_example
 39  sshd requires that binary to be root-owned and not group/world
 40  writable. Unknown keys fail authentication inside sshd, so system mode
 41  requires =registration.mode = "closed"= (check-config enforces this).
 42
 43* Configuration reference
 44
 45=/etc/gitbay/config.toml=. =check-config= validates and names every
 46contradiction; =--no-host-checks= skips port/path probes.
 47
 48** [server]
 49- =root= (default =/var/lib/gitbay=) — repositories, database, host
 50  keys, ACME cache all live here.
 51- =site_url= (required) — canonical =https://host=; drives ACME, clone
 52  URLs, mail links.
 53
 54** [ssh]
 55- =mode= — =embedded= | =system= (above).
 56- =port= (22) — embedded listener port.
 57- =host_keys= — list of private key paths; empty generates an ed25519
 58  key at =<root>/ssh/host_ed25519=.
 59
 60** [http]
 61- =addr= (=:443=), =tls= — =acme= | =files= | =off=.
 62- =acme=: certificates via TLS-ALPN-01 on the HTTPS port, cached at
 63  =<root>/acme=; =acme_email= for the CA account; =acme_http_addr=
 64  (=:80=, ="off"= to disable) adds HTTP-01 and an https redirect —
 65  failing to bind it is a warning, not fatal. Requires an =https://=
 66  site_url with a public DNS name.
 67- =files=: =cert_file= + =key_file=.
 68- =off=: plain HTTP — development, or behind a TLS-terminating proxy.
 69
 70** [web]
 71- =mode= — =view_only= (default) | =accounts=. In view_only the mutating
 72  web routes are never registered; in accounts, browser sessions are
 73  minted over SSH (=web login=), and users with write access can create
 74  repos, comment, and make simple file edits (which commit unsigned,
 75  honestly). =password_auth= is reserved and currently rejected.
 76
 77** [registration]
 78- =mode= — =closed= (default) | =invite= | =open=. invite/open require
 79  [mail]. See the user guide for the flows.
 80
 81** [mail]
 82- =smtp_host= (host:port, 587 assumed), =from=, optional =smtp_user= /
 83  =smtp_pass=. STARTTLS when offered. Required for invite/open
 84  registration and self-service =email add=; in closed mode you may omit
 85  it entirely and assert addresses by hand (below).
 86
 87** [api]
 88- =enabled= (false) — the JSON API surface; see =docs/api.org=. Off
 89  means no credential-bearing HTTP endpoint exists at all.
 90
 91** [webhooks]
 92- =allow_local= (false) — permit webhook targets on loopback/private
 93  addresses. Leave off unless you know why you need it (SSRF).
 94
 95** [limits]
 96- =clone_timeout= (3600s) — cap on =repo import= fetches.
 97- =max_blob_bytes= (100MB) — cap on raw file serving over the web.
 98- =max_asset_bytes= (512MB) — cap per uploaded release asset.
 99- =max_pack_bytes=, =ssh_auth_rate= — reserved, not yet enforced.
100
101** [git_daemon]
102- =enabled= (false), =port= (9418) — the anonymous =git://= listener.
103  Serves only public repositories that additionally ran
104  =repo settings git-daemon <repo> on=.
105
106** [mirrors]
107- =pull_interval_minutes= (15) — how often pull mirrors fetch their
108  upstream. Push mirrors sync shortly after each local ref update.
109  Mirror URLs pass the same SSRF rules as webhook targets.
110
111** [go_import]
112Vanity Go module paths, one per line: ="host/module" = "owner/repo"=.
113Requests with =?go-get=1= at or under the module path answer with the
114go-import meta tag pointing at the repository's HTTPS clone URL, so
115=go install host/module/cmd/...@latest= resolves. The repository should
116be public (the module path itself confirms it exists).
117
118* Users, email, invites
119
120#+begin_src sh
121gitbayd admin user create alice --key alice.pub --email a@example.org --verified [--admin]
122gitbayd admin email verify alice a@example.org   # admin assertion, no SMTP needed
123gitbayd admin invite --email b@example.org       # mails a code; prints it if no SMTP
124#+end_src
125
126"Verified" means SMTP-confirmed or host-admin-asserted; the database
127records which. Verified emails are what make commit signatures
128meaningful — an unverified address never produces a =verified= badge.
129
130* Audit and account control
131
132The audit log is the security feed (events are the product feed): every
133successful mutating command with its argv and source credential (SSH key
134fingerprint or API), registrations, admin actions, force-pushes, and
135auth failures/throttling. Secrets never appear — they travel on stdin,
136never in argv.
137
138#+begin_src sh
139gitbayd admin audit [--limit n]      # host-local
140ssh git@<host> audit [--limit n]     # instance admins, SSH only
141gitbayd admin user disable <name>    # suspend: SSH, web, API all refused;
142gitbayd admin user enable <name>     #   sessions dropped, nothing deleted
143#+end_src
144
145=limits.ssh_auth_rate= (10) throttles per-IP authentication *failures*
146per minute — successful auths never count and clear the slate.
147=limits.max_pack_bytes= is enforced as =receive.maxInputSize= on every
148push.
149
150* Maintenance
151
152#+begin_src sh
153gitbayd admin stats [--json]         # counts, database size, per-repo disk
154gitbayd admin gc [--repo owner/name] # git gc: repack and prune; per-repo sizes
155gitbayd admin gc --aggressive        # thorough repack; slow, rarely needed
156#+end_src
157
158=deploy/cloud-init.yaml= ships a =gitbay-gc.timer= that runs =admin gc=
159weekly (Sunday 07:00 UTC). Imported repositories keep whatever pack
160layout the source sent, so a first manual =admin gc= after a bulk
161import is worthwhile.
162
163* Backup and restore
164
165#+begin_src sh
166gitbayd admin backup --out /var/backups/gitbay/backup.tar.gz
167#+end_src
168
169One archive: a consistent SQLite snapshot (taken *before* the
170repositories are read, so the database never references objects the
171archive missed), every repository, and the SSH host keys. Excluded:
172hook socket, regenerated hook scripts, WAL files. Safe to run against a
173live daemon.
174
175Restore: extract into an empty directory, point =server.root= at it,
176start gitbayd. Host keys are preserved, so clients keep their
177known_hosts entries; hooks regenerate at startup.
178
179* Upgrades
180
181Replace the binary, restart the unit. Migrations apply automatically and
182are transactional; hook scripts under =<root>/hooks= are rewritten at
183startup to point at the current binary path.
184
185* Odds and ends
186
187- deleting a fork marks MRs sourced from it =source_gone=; their diffs
188  remain viewable and mergeable because the target repo owns the
189  objects.
190- =refs/merge-requests/*= is server-owned and unpushable by clients.
191- audit-relevant activity (issue/MR lifecycle, imports, pushes) lands in
192  the =events= table, which also feeds webhooks.
193- the daemon idles under 10MB RSS; the smallest VPS tier is adequate.